// Author: Matthew Shiel
package main

import (
	"embed"
	"fmt"
	"html/template"
	"log"
	"net/http"
	"strings"

	"git.riomhaire.com/gremlin/elizaservice/eliza"
	"github.com/jaffee/commandeer"
	"github.com/labstack/echo/v4"
	"github.com/labstack/echo/v4/middleware"
)

//go:embed web/*
var web embed.FS

//go:embed templates/*
var templates embed.FS

type Main struct {
	BotName string `help:"What This Bot is Called."`
	Port    int    `help:"What port bot is listening too"`
}

func NewMain() *Main {
	return &Main{
		BotName: "Eliza",
		Port:    8070,
	}
}

func inputhandler(w http.ResponseWriter, r *http.Request) {
	// Extract question from GET request
	question := r.URL.Query().Get("value")

	// Return Eliza's response's so long as the user doesn't give a quit statement
	answer := eliza.ReplyTo(question)

	// Return Eliza's answer
	fmt.Fprintf(w, "%s", answer)
}

// func (c echo.Context) personalityHandler(w http.ResponseWriter, r *http.Request) {
// 	w.WriteHeader(http.StatusOK)
// 	w.Header().Set("Content-Type", "text/html")

// 	// Note the call to ParseFS instead of Parse
// 	t, err := template.ParseFS(templates, fmt.Sprintf("templates/%s.html", vars["personality"]))
// 	if err != nil {
// 		log.Fatal(err)
// 	}
// 	// respond with the output of template execution
// 	t.Execute(w, struct {
// 		Id         string
// 		GivenName  string
// 		FamilyName string
// 		Name       string
// 	}{
// 		Id:         queryParameter("user_id", r),
// 		GivenName:  queryParameter("given_name", r),
// 		FamilyName: queryParameter("family_name", r),
// 		Name:       queryParameter("name", r),
// 	})

// }

// func defaultPersonalityHandler(w http.ResponseWriter, r *http.Request) {
// 	http.Redirect(w, r, "/chatbot/eliza", 302)
// }

// func queryParameter(key string, r *http.Request) string {
// 	keys, ok := r.URL.Query()[key]

// 	if !ok || len(keys[0]) < 1 {
// 		return ""
// 	}
// 	return keys[0]
// }

func chantboInteractiontEndpoint(c echo.Context) error {
	// Extract question from GET request
	question := c.QueryParam("value")

	// Return Eliza's response's so long as the user doesn't give a quit statement
	answer := eliza.ReplyTo(question)

	// Return Eliza's answer
	fmt.Fprintf(c.Response(), "%s", answer)
	return nil
}

func chantbotEndpoint(c echo.Context) error {
	c.Response().WriteHeader(http.StatusOK)
	c.Response().Header().Add("Content-Type", "text/html")

	// Note the call to ParseFS instead of Parse
	personality := c.Param("personality")
	t, err := template.ParseFS(templates, fmt.Sprintf("templates/%s.html", personality))
	if err != nil {
		log.Fatal(err)
	}
	// respond with the output of template execution
	t.Execute(c.Response(), struct {
		Id         string
		GivenName  string
		FamilyName string
		Name       string
		Bot        string
	}{
		Id:         c.QueryParam("user_id"),
		GivenName:  c.QueryParam("given_name"),
		FamilyName: c.QueryParam("family_name"),
		Name:       c.QueryParam("name"),
		Bot:        strings.Title(strings.ToLower(personality)),
	})
	return nil
}

func (m *Main) Run() error {

	fmt.Println(`
####### #         ###   #######    #
#       #          #         #    # #
#       #          #        #    #   #
#####   #          #       #    #     #
#       #          #      #     #######
#       #          #     #      #     #
####### #######   ###   ####### #     #
	`)
	fmt.Println()

	e := echo.New()

	//e.GET("/chatbot/:personality", personalityHandler)
	// r.HandleFunc("/chatbot/{personality}", personalityHandler)
	// http.Handle("/", r)

	// fmt.Printf(" [*] %s ... Awaiting Conversations on port  %d\n", m.BotName, m.Port)

	//	http.ListenAndServe(fmt.Sprintf(":%d", m.Port), nil)
	var contentHandler = echo.WrapHandler(http.FileServer(http.FS(web)))
	var contentRewrite = middleware.Rewrite(map[string]string{"/*": "/web/$1"})

	e.GET("/user-input", chantboInteractiontEndpoint)
	e.GET("/chatbot/:personality", chantbotEndpoint)
	e.GET("/*", contentHandler, contentRewrite)
	e.Logger.Fatal(e.Start(fmt.Sprintf(":%d", m.Port)))

	return nil
}

func main() {
	err := commandeer.Run(NewMain())
	if err != nil {
		fmt.Println(err)
	}
}