package libamuse

import (
	"notabug.org/apiote/amuse/accounts"
	"notabug.org/apiote/amuse/config"
	"notabug.org/apiote/amuse/db"

	"crypto/sha256"
	"encoding/base64"
	"errors"
	"io/ioutil"

	"notabug.org/apiote/gott"
)

type Avatar struct {
	Data     []byte
	Mimetype string
	Etag     string
}

func getUser(args ...interface{}) (interface{}, error) {
	request := args[0].(*RequestData)
	result := args[1].(*Result)
	user, err := db.GetUser(request.id)
	result.result = user
	return gott.Tuple(args), err
}

func getAvatar(args ...interface{}) (interface{}, error) {
	result := args[1].(*Result)
	small := args[2].(bool)
	user := result.result.(*db.User)
	if small {
		if string(user.AvatarSmall) == "" {
			return gott.Tuple(args), errors.New("No avatar")
		} else {
			result.result = user.AvatarSmall
		}
	} else {
		if string(user.Avatar) == "" {
			return gott.Tuple(args), errors.New("No avatar")
		} else {
			result.result = user.Avatar
		}
	}
	result.result2 = "image/webp"
	return gott.Tuple(args), nil
}

func checkEtag(args ...interface{}) (interface{}, error) {
	request := args[0].(*RequestData)
	result := args[1].(*Result)
	h := sha256.New()
	_, err := h.Write(result.result.([]byte))
	if err != nil {
		return gott.Tuple(args), err
	}
	etag := base64.StdEncoding.EncodeToString(h.Sum(nil))
	if etag == request.etag {
		result.result = []byte{}
	}
	result.page = etag
	return gott.Tuple(args), nil
}

func recovery(args ...interface{}) (interface{}, error) {
	err := args[3].(error)
	switch err.Error() {
	case "No avatar":
		return getPlaceholder(args...)
	default:
		return gott.Tuple(args), err
	}
}

func getPlaceholder(args ...interface{}) (interface{}, error) {
	result := args[1].(*Result)
	img, err := ioutil.ReadFile(config.DataHome + "/static/img/avatar.webp") // todo path
	result.result = img
	result.result2 = "image/webp"
	return gott.Tuple(args), err
}

func ShowUserAvatar(username, etagReq string, auth accounts.Authentication, small bool) (Avatar, error) {
	auth.Necessary = true
	avatar := Avatar{}

	r, err := gott.
		NewResult(gott.Tuple{&RequestData{id: username, etag: etagReq, auth: auth, username: username}, &Result{}, small}).
		Bind(verifyToken).
		Bind(verifyUser).
		Bind(getUser).
		Bind(getAvatar).
		Recover(recovery).
		Bind(checkEtag).
		Finish()

	if err != nil {
		return avatar, err
	}
	r = r.(gott.Tuple)[1]
	avatar.Data = r.(*Result).result.([]byte)
	avatar.Mimetype = r.(*Result).result2.(string)
	avatar.Etag = r.(*Result).page

	return avatar, nil
}
