package api

import (
	"encoding/json"
	"fmt"
	"log"
	"net/http"
	"os"
	"path"

	"github.com/gin-gonic/gin"
)

var DashboardDir string

func declarePublicRoutes(router *gin.RouterGroup) {
	router.GET("/public/:sid", getPublic)
	router.DELETE("/public/:sid", deletePublic)
	router.PUT("/public/:sid", savePublic)
}

type FICPublicScene struct {
	Type   string                 `json:"type"`
	Params map[string]interface{} `json:"params"`
}

type FICPublicDisplay struct {
	Scenes          []FICPublicScene       `json:"scenes"`
	Side            []FICPublicScene       `json:"side"`
	CustomCountdown map[string]interface{} `json:"customCountdown"`
	HideEvents      bool                   `json:"hideEvents"`
	HideCountdown   bool                   `json:"hideCountdown"`
	HideCarousel    bool                   `json:"hideCarousel"`
}

func readPublic(path string) (FICPublicDisplay, error) {
	var s FICPublicDisplay
	if fd, err := os.Open(path); err != nil {
		return s, err
	} else {
		defer fd.Close()
		jdec := json.NewDecoder(fd)

		if err := jdec.Decode(&s); err != nil {
			return s, err
		}

		return s, nil
	}
}

func savePublicTo(path string, s FICPublicDisplay) error {
	if fd, err := os.Create(path); err != nil {
		return err
	} else {
		defer fd.Close()
		jenc := json.NewEncoder(fd)

		if err := jenc.Encode(s); err != nil {
			return err
		}

		return nil
	}
}

func getPublic(c *gin.Context) {
	if _, err := os.Stat(path.Join(DashboardDir, fmt.Sprintf("public%s.json", c.Params.ByName("sid")))); !os.IsNotExist(err) {
		p, err := readPublic(path.Join(DashboardDir, fmt.Sprintf("public%s.json", c.Params.ByName("sid"))))
		if err != nil {
			log.Println("Unable to readPublic in getPublic:", err.Error())
			c.AbortWithStatusJSON(http.StatusInternalServerError, gin.H{"errmsg": "An error occurs during scene retrieval."})
			return
		}

		c.JSON(http.StatusOK, p)
		return
	}

	c.JSON(http.StatusOK, FICPublicDisplay{Scenes: []FICPublicScene{}, Side: []FICPublicScene{}})
}

func deletePublic(c *gin.Context) {
	if err := savePublicTo(path.Join(DashboardDir, fmt.Sprintf("public%s.json", c.Params.ByName("sid"))), FICPublicDisplay{}); err != nil {
		log.Println("Unable to deletePublic:", err.Error())
		c.AbortWithStatusJSON(http.StatusInternalServerError, gin.H{"errmsg": "An error occurs during scene deletion."})
		return
	}

	c.JSON(http.StatusOK, FICPublicDisplay{Scenes: []FICPublicScene{}, Side: []FICPublicScene{}})
}

func savePublic(c *gin.Context) {
	var scenes FICPublicDisplay
	err := c.ShouldBindJSON(&scenes)
	if err != nil {
		c.AbortWithStatusJSON(http.StatusBadRequest, gin.H{"errmsg": err.Error()})
		return
	}

	if err := savePublicTo(path.Join(DashboardDir, fmt.Sprintf("public%s.json", c.Params.ByName("sid"))), scenes); err != nil {
		log.Println("Unable to savePublicTo:", err.Error())
		c.AbortWithStatusJSON(http.StatusInternalServerError, gin.H{"errmsg": "An error occurs during scene saving."})
		return
	}

	c.JSON(http.StatusOK, scenes)
}
