func NewCollectionWithData(data []byte) (*Collection, error) {
	c := NewCollection()
	err := c.Deserialize(data)
	return c, err
}
NewCollectionWithData creates a new Collection instance with data from a byte slice
package totp
import (
	"encoding/json"
	"errors"
	"io"
	"io/ioutil"
	"os"
	"time"
	"github.com/pquerna/otp/totp"
)
var errSecretNotFound = errors.New("secret not found")
var errNoFilename = errors.New("no save target")
var errSecretNameEmpty = errors.New("secret name empty")
var errSecretValueEmpty = errors.New("secret value empty")
type Secret struct {
	DateAdded    time.Time
	DateModified time.Time
	Name         string
	Value        string
}
type Collection struct {
	Secrets  map[string]Secret
	filename string
	writer   io.Writer
}
type CollectionInterface interface {
	DeleteSecret(string) (Secret, error)
	GetSecret(string) (Secret, error)
	GetSecrets() []Secret
	Save() error
	SetFilename(string) string
	UpdateSecret(string, string) (Secret, error)
}
func (c *Collection) Save() error {
	var err error
	var writerErr error
	serializedSettings, err := c.Serialize()
	if err == nil {
		if c.writer == nil && len(c.filename) == 0 {
			err = errNoFilename
		}
		if c.writer != nil {
			_, writerErr = c.writer.Write(serializedSettings)
		}
		if len(c.filename) != 0 {
			err = ioutil.WriteFile(c.filename, serializedSettings, 0600)
		}
		if err == nil {
			err = writerErr
		}
	}
	return err
}
func (c *Collection) DeleteSecret(name string) (Secret, error) {
	var err error
	retSecret, ok := c.Secrets[name]
	if ok {
		delete(c.Secrets, name)
	} else {
		err = errSecretNotFound
	}
	return retSecret, err
}
func (c *Collection) UpdateSecret(name, value string) (Secret, error) {
	var retSecret Secret
	var err error
	var ok bool
	if len(name) == 0 {
		err = errSecretNameEmpty
	} else if len(value) == 0 {
		err = errSecretValueEmpty
	} else {
		_, err = totp.GenerateCode(value, time.Now())
		if err == nil {
			retSecret, ok = c.Secrets[name]
			if ok {
				retSecret.Value = value
				retSecret.DateModified = time.Now()
				c.Secrets[name] = retSecret
			} else {
				dateAdded := time.Now()
				newSecret := Secret{Name: name, Value: value, DateAdded: dateAdded, DateModified: dateAdded}
				c.Secrets[name] = newSecret
				retSecret = newSecret
			}
		}
	}
	return retSecret, err
}
func (c *Collection) RenameSecret(oldName, newName string) (Secret, error) {
	var retSecret Secret
	var ok bool
	var err error
	if len(newName) != 0 {
		retSecret, ok = c.Secrets[oldName]
		if ok {
			retSecret.Name = newName
			retSecret.DateModified = time.Now()
			c.Secrets[newName] = retSecret
			delete(c.Secrets, oldName)
		} else {
			err = errSecretNotFound
		}
	} else {
		err = errSecretNameEmpty
	}
	return retSecret, err
}
func (c *Collection) GetSecret(name string) (Secret, error) {
	var err error
	retSecret, ok := c.Secrets[name]
	if !ok {
		err = errSecretNotFound
	}
	return retSecret, err
}
func (c *Collection) GetSecrets() []Secret {
	secrets := []Secret{}
	for _, secret := range c.Secrets {
		secrets = append(secrets, secret)
	}
	return secrets
}
func (c *Collection) GenerateCodeWithTime(name string, time time.Time) (string, error) {
	var code string
	secret, err := c.GetSecret(name)
	if err == nil {
		code, err = totp.GenerateCode(secret.Value, time)
	}
	return code, err
}
func (c *Collection) GenerateCode(name string) (string, error) {
	return c.GenerateCodeWithTime(name, time.Now())
}
func (c *Collection) Serialize() ([]byte, error) {
	return json.MarshalIndent(c, "", "  ")
}
func (c *Collection) Deserialize(data []byte) error {
	return json.Unmarshal(data, &c)
}
func (c *Collection) SetWriter(writer io.Writer) {
	c.writer = writer
}
func (c *Collection) SetFilename(filename string) string {
	c.filename = filename
	return c.filename
}
func NewCollection() *Collection {
	c := new(Collection)
	c.Secrets = make(map[string]Secret)
	return c
}