package main

//go:generate esc -o assets.go assets templates songs

import (
	"bufio"
	"flag"
	"fmt"
	"io/ioutil"
	"log"
	"net/http"
	"os"
	"strings"

	"golang.org/x/crypto/ssh/terminal"

	"github.com/gorilla/handlers"
	"github.com/gorilla/mux"
	"github.com/gorilla/sessions"
	"github.com/justinas/alice"
)

var port int
var ip string
var dir string

var sessionSecret = "AChKj7na128CrKPPG0Rc"
var sessionStore = sessions.NewCookieStore([]byte(sessionSecret))
var r *mux.Router
var site *siteData
var model *model

type siteData struct {
	Title   string
	DevMode bool
}

func init() {
	const (
		portDefault = 8080
		portUsage   = "the port to listen on"
		ipDefault   = "127.0.0.1"
		ipUsage     = "the ip mask to listen for connections from"
		dirDefault  = "./"
		dirUsage    = "the directory to serve the app out of\nThere should be a 'songs' directory here."
	)
	flag.StringVar(&ip, "ip", ipDefault, ipUsage)
	flag.IntVar(&port, "port", portDefault, portUsage)
	flag.StringVar(&dir, "dir", dirDefault, dirUsage)
	if !strings.HasSuffix(dir, "/") {
		dir = dir + "/"
	}
}

func main() {
	flag.Parse()
	loadModel()

	r := mux.NewRouter()
	r.StrictSlash(true)

	//r.PathPrefix("/assets/").Handler(http.FileServer(FS(site.DevMode)))
	// Public Subrouter
	pub := r.PathPrefix("/").Subrouter()
	pub.HandleFunc("/", handleMain)

	admin := r.PathPrefix("/admin").Subrouter()
	admin.HandleFunc("/", handleAdmin)
	admin.HandleFunc("/dologin", handleAdminDoLogin)
	admin.HandleFunc("/dologout", handleAdminDoLogout)
	admin.HandleFunc("/{action}", handleAdmin)

	http.Handle("/", r)

	chain := alice.New(loggingHandler).Then(r)

	listenAt := fmt.Sprintf("%s:%d", ip, port)
	fmt.Println("Songbook Server listening at", listenAt)
	log.Fatal(http.ListenAndServe(listenAt, chain))
}

func loadModel() {
	model := NewModel(dir)
	site = new(siteData)
	if !model.hasUser() {
		reader := bufio.NewReader(os.Stdin)
		fmt.Println("Create new Admin user")
		fmt.Print("Username: ")
		un, _ := reader.ReadString('\n')
		un = strings.TrimSpace(un)
		var pw1, pw2 []byte
		for string(pw1) != string(pw2) || string(pw1) == "" {
			fmt.Print("Password: ")
			pw1, _ = terminal.ReadPassword(0)
			fmt.Println("")
			fmt.Print("Repeat Password: ")
			pw2, _ = terminal.ReadPassword(0)
			fmt.Println("")
			if string(pw1) != string(pw2) {
				fmt.Println("Entered Passwords don't match!")
			}
		}
	}

}

func handleMain(w http.ResponseWriter, req *http.Request) {
	w.Header().Set("Content-Type", "text/html; charset=utf-8")
	output, err := ioutil.ReadFile(dir + "currentsongs.html")
	if err != nil {
		output = []byte("Error reading current songs")
	}
	fmt.Fprint(w, string(output))
}

func initPageData(w http.ResponseWriter, req *http.Request) *pageData {
	if site.DevMode {
		w.Header().Set("Cache-Control", "no-cache")
	}
	p := new(pageData)
	// Get the session
	var err error
	var s *sessions.Session
	if s, err = sessionStore.Get(req, "songbook"); err != nil {
		http.Error(w, err.Error(), 500)
		return p
	}
	p.session = new(pageSession)
	p.session.session = s
	p.session.req = req
	p.session.w = w

	// First check if we're logged in
	userName, _ := p.session.getStringValue("name")
	_ = userName

	p.Site = site
	p.SubTitle = "Songbook"
	p.Stylesheets = make([]string, 0, 0)
	p.Stylesheets = append(p.Stylesheets, "/assets/vendor/css/pure-min.css")
	p.Stylesheets = append(p.Stylesheets, "/assets/vendor/css/grids-responsive-min.css")
	p.Stylesheets = append(p.Stylesheets, "/assets/vendor/font-awesome/css/font-awesome.min.css")
	p.Stylesheets = append(p.Stylesheets, "/assets/css/gjvote.css")

	p.HeaderScripts = make([]string, 0, 0)

	p.Scripts = make([]string, 0, 0)

	p.FlashMessage, p.FlashClass = p.session.getFlashMessage()
	if p.FlashClass == "" {
		p.FlashClass = "hidden"
	}

	return p
}

func loggingHandler(h http.Handler) http.Handler {
	return handlers.LoggingHandler(os.Stdout, h)
}
