// Copyright (C) 2019 Marius Schellenberger

package otp

import (
	"bytes"
	"encoding/base64"
	"errors"
	"github.com/pquerna/otp"
	"github.com/pquerna/otp/totp"
	"html/template"
	"image/png"
)

const size = 200

func base64Image(key *otp.Key) (data template.URL, err error) {
	var buf bytes.Buffer
	img, err := key.Image(size, size)
	if err != nil {
		err = errors.New("otp: " + err.Error())
		return
	}
	err = png.Encode(&buf, img)
	if err != nil {
		err = errors.New("otp: " + err.Error())
		return
	}
	data = template.URL("data:image/png;base64," + base64.StdEncoding.EncodeToString(buf.Bytes()))
	return
}

type Request struct {
	Username string
	Image    template.URL
	Secret   string
	URL      string
}

func New(username string) (req Request, err error) {
	key, err := totp.Generate(totp.GenerateOpts{
		Issuer:      "docstore",
		AccountName: username,
	})
	if err != nil {
		return
	}
	data, err := base64Image(key)
	if err != nil {
		return
	}
	return Request{
		Username: username,
		Image:    data,
		Secret:   key.Secret(),
		URL:      key.URL(),
	}, nil
}

func Validate(pin, secret string) bool {
	if secret == "" {
		return true
	}
	return totp.Validate(pin, secret)
}

func ImageSecretFromURL(url string) (data template.URL, secret string, err error) {
	key, err := otp.NewKeyFromURL(url)
	if err != nil {
		err = errors.New("otp: " + err.Error())
		return
	}
	secret = key.Secret()
	data, err = base64Image(key)
	return
}
