package main

import (
	"bufio"
	"fmt"
	"log"
	"net/http"
	"os"
	"strings"

	"github.com/labstack/echo/v4"
	"github.com/labstack/echo/v4/middleware"
)

type WebServer struct {
	Tv_ip       string
	Port        string
	Host        string
	At          string
	Device_list []string
	WakeOnLan   map[string]string
	Power       bool
}

func (w *WebServer) Init(tv, host, port string) {
	w.Tv_ip = tv
	w.Host = host
	w.Port = port
	w.WakeOnLan = make(map[string]string)
	if FileExists("WOL.txt") {
		log.Print("Loading WOLs from WOL.txt")
		file, err := os.Open("WOL.txt")
		if err != nil {
			log.Printf("Failed reading WOL.txt got %v", err)
		}
		defer file.Close()

		var scanner *bufio.Scanner = bufio.NewScanner(file)
		for scanner.Scan() {
			var line string = scanner.Text()
			if len(line) == 0 {
				continue
			}
			var parts []string = strings.Split(line, " = ")
			var ip string = parts[0]
			var mac string = parts[1]
			log.Printf("IP='%s' MAC='%s'", ip, mac)
			w.WakeOnLan[ip] = mac
		}
	}
}

func (w *WebServer) homepage(c echo.Context) error {
	//return c.String(http.StatusOK, "Hello World!")
	/*file, err := os.ReadFile("templates/index.html")
	if err != nil {
		return err
	}*/

	//return c.HTMLBlob(http.StatusOK, file)
	data := make(map[string]interface{})
	data["at"] = w.At
	return c.Render(http.StatusOK, "index.html", data)
}

func (w *WebServer) connectpage(c echo.Context) error {
	data := make(map[string]interface{})
	data["connected"] = "Connected: " + w.Tv_ip
	//var dev_list []string
	var list []string
	list = append(list, w.Device_list...)
	data["resp"] = list
	return c.Render(http.StatusOK, "connect.html", data)
}

func (w *WebServer) connector(c echo.Context) error {
	cmd := c.Param("cmd")
	w.Tv_ip = cmd
	log.Printf("Switched to %s", cmd)

	return c.Redirect(http.StatusOK, "/connect")
}

func (w *WebServer) con_refresh(c echo.Context) error {
	log.Printf("Recieved Connection Refresh")
	var list *[]string
	list, w.WakeOnLan = GetDevices(w.WakeOnLan)
	log.Printf("Found %d devices", len(*list))
	log.Printf("Obtained %d WOLs", len(w.WakeOnLan))
	var save_file []byte
	for ip, mac := range w.WakeOnLan {
		log.Printf("IP='%v' MAC='%v'\n", ip, mac)
		if ip != "" && mac != "" {
			for _, r := range ip {
				save_file = append(save_file, byte(r))
			}
			save_file = append(save_file, ' ')
			save_file = append(save_file, '=')
			save_file = append(save_file, ' ')
			for _, r := range mac {
				save_file = append(save_file, byte(r))
			}
		}
	}
	if len(save_file) != 0 {
		err := os.WriteFile("WOL.txt", save_file, 0775)
		if err != nil {
			log.Printf("Saving WOL.txt failed with %v", err)
		} else {
			log.Print("Saved WOL to WOL.txt")
		}
	}
	for _, ip := range *list {
		if ip != w.Tv_ip {
			w.Device_list = append(w.Device_list, ip)
		}
	}
	//w.Device_list = *list
	return c.Redirect(http.StatusTemporaryRedirect, "/connect")
}

func (w *WebServer) tvcmd(c echo.Context) error {
	//w.At = DebugInfo(w.Tv_ip)
	cmd := c.Param("cmd")
	switch cmd {
	case "power":
		PerformKey(w.Tv_ip, "power")
	case "back":
		PerformKey(w.Tv_ip, "back")
	case "home":
		PerformKey(w.Tv_ip, "home")
	case "up":
		PerformKey(w.Tv_ip, "up")
	case "left":
		PerformKey(w.Tv_ip, "left")
	case "ok":
		PerformKey(w.Tv_ip, "select")
	case "right":
		PerformKey(w.Tv_ip, "right")
	case "down":
		PerformKey(w.Tv_ip, "down")
	case "rewind":
		PerformKey(w.Tv_ip, "rev")
	case "play-pause":
		PerformKey(w.Tv_ip, "play")
	case "fast-forward":
		PerformKey(w.Tv_ip, "fwd")
	case "star":
		PerformKey(w.Tv_ip, "info")
	case "reload":
		PerformKey(w.Tv_ip, "instantreplay")
	case "vol+":
		PerformKey(w.Tv_ip, "volumeup")
	case "vol-":
		PerformKey(w.Tv_ip, "volumedown")
	case "mute":
		PerformKey(w.Tv_ip, "volumemute")
	case "display":
		w.At = DebugInfo(w.Tv_ip)
		device := GetDeviceInfo(w.Tv_ip)
		if device["power-mode"] == "PowerOn" {
			w.Power = true
		} else {
			w.Power = false
		}
		data := make(map[string]interface{})
		data["at"] = w.At
		data["power"] = w.Power
		return c.JSON(http.StatusOK, data)
	case "pluto":
		Post(fmt.Sprintf("http://%s:8060/launch/%d", w.Tv_ip, 74519))
	case "pluto-cops":
		Post(fmt.Sprintf("http://%s:8060/launch/%d?contentId=367&mediaType=live", w.Tv_ip, 74519))
	case "pluto-thefirst":
		Post(fmt.Sprintf("http://%s:8060/launch/%d?contentId=244&mediaType=live", w.Tv_ip, 74519))
	case "pluto-mst3k":
		Post(fmt.Sprintf("http://%s:8060/launch/%d?contentId=488&mediaType=live", w.Tv_ip, 74519))
	case "pluto-rifftrax":
		Post(fmt.Sprintf("http://%s:8060/launch/%d?contentId=489&mediaType=live", w.Tv_ip, 74519))
	case "pluto-startrek":
		Post(fmt.Sprintf("http://%s:8060/launch/%d?contentId=150&mediaType=live", w.Tv_ip, 74519))
	default:
		c.Echo().Logger.Printf("Got '%v'\r\n", cmd)
	}
	return c.Redirect(http.StatusOK, "/")
	//return c.Render(http.StatusOK, "index.html", data)
}

func main() {
	web := WebServer{}
	web.Init("192.168.254.75", "", "8000")

	e := echo.New()
	e.Use(middleware.Logger())
	e.Use(middleware.Static("static"))
	e.Renderer = NewRenderer("./templates/*.html", true)

	e.GET("/", web.homepage)
	e.GET("/tv/:cmd", web.tvcmd)
	e.GET("/connect", web.connectpage)
	e.GET("/con/:cmd", web.connector)
	e.GET("/conn_refresh", web.con_refresh)

	e.Logger.Fatal(e.Start(fmt.Sprintf("%s:%s", web.Host, web.Port)))
}
