package auth

import (
	"encoding/json"
	"html/template"
	"io"
	"log"
)

type Context struct {
	Config    ServerConfig
	Clients   ClientStore
	Tokens    TokenStore
	Profiles  ProfileStore
	Log       *log.Logger
	Templates Templates
}

type Templates struct {
	Error        *template.Template
	Confirmation *template.Template
	Login        *template.Template
}

type jsonError struct {
	Error       string `json:"error,omitempty"`
	Description string `json:"error_description,omitempty"`
	URI         string `json:"error_uri,omitempty"`
	State       string `json:"state,omitempty"`
}

func (c Context) RenderError(w io.Writer, err error) {
	if c.Templates.Error == nil {
		log.Println("Error template is nil, can't render error.")
		return
	}
	renderErr := c.Templates.Error.Execute(w, map[string]interface{}{
		"err": err,
	})
	if renderErr != nil {
		log.Printf("Error executing error template (oh, the irony): %s\n", renderErr)
		return
	}
}

func (c Context) RenderJSONError(w io.Writer, code, description, baseURI string) {
	d, err := json.Marshal(jsonError{
		Error:       code,
		Description: description,
		URI:         baseURI,
	})
	if err != nil {
		log.Printf("Error marshalling json error (oh, the irony): %s\n", err)
		return
	}
	_, err = w.Write(d)
	if err != nil {
		log.Printf("Error writing json error: %s\n", err)
		return
	}
}

func (c Context) RenderConfirmation(w io.Writer) {
	if c.Templates.Confirmation == nil {
		log.Println("Confirmation template is nil, can't render confirmation.")
		return
	}
	err := c.Templates.Confirmation.Execute(w, nil)
	if err != nil {
		log.Printf("Error executing confirmation template: %s\n", err)
		return
	}
}

func (c Context) RenderLogin(w io.Writer) {
	if c.Templates.Login == nil {
		log.Println("Login template is nil, can't render confirmation.")
		return
	}
	err := c.Templates.Login.Execute(w, nil)
	if err != nil {
		log.Printf("Error executing login template: %s\n", err)
		return
	}
}

func (c Context) RenderJSONToken(w io.Writer, data AccessData) {
	d, err := json.Marshal(data)
	if err != nil {
		log.Printf("Error marshalling json token: %s\n", err)
		return
	}
	_, err = w.Write(d)
	if err != nil {
		log.Printf("Error writing json token: %s\n", err)
		return
	}
}
