package commands

import (
	"fmt"
	"time"

	. "git.eugeniocarvalho.dev/eugeniucarvalho/apicodegen/common"
	. "git.eugeniocarvalho.dev/eugeniucarvalho/apicodegen/gen"
	"git.eugeniocarvalho.dev/eugeniucarvalho/apicodegen/flag"
	"github.com/kataras/iris/v12"
	"github.com/kataras/iris/v12/middleware/logger"
	"github.com/kataras/iris/v12/middleware/recover"
	"github.com/fsnotify/fsnotify"
	"os"
	"path/filepath"
	"encoding/json"
)

var watcher, _ = fsnotify.NewWatcher()

func serve() (err error) {
	var (
		project    *Project
		// done       = make(chan bool)
	)
	defer watcher.Close()

	fmt.Println("Serve WITH SETUP...")
	// Cria um novo projeto a partir do diretorio atual
	if project, err = CreateProject(*flag.Mode); err != nil {
		panic(err)
	}

	// starting at the root of the project, walk each file/directory searching for
	// directories
	if err := filepath.Walk("./", watchDir); err != nil {
		fmt.Println("ERROR", err)
	}


	HubInstance.EventHandlers["initialize"] = func(hub *Hub, event *Event) {
		payload, err := json.Marshal(project)
		if err != nil {
			fmt.Println("error:", err)
			return
		}
		
		fmt.Println("run .. initialize")

		go func(){
			hub.Broadcast <- &Event{
				Kind      : "project:update",
				Payload   : string(payload),
				Date      : time.Now(),
			}
		}()
	}

	go func() {
		count := 10
		for {
			select {
			case event, ok := <-watcher.Events:
				if !ok {
					return
				}
				// log.Println("event:", event)
				
				if event.Op & fsnotify.Write == fsnotify.Write {
					fmt.Println("modified file:", event.Name)
					fmt.Println("update...")
					time.Sleep(time.Second)
					if project, err = CreateProject(*flag.Mode); err != nil {
						panic(err)
					}
					
					payload, err := json.Marshal(project)
					if err != nil {
						fmt.Println("error:", err)
						return
					}

					HubInstance.Broadcast <- &Event{
						Kind      : "project:update",
						Payload   : string(payload),
						Date      : time.Now(),
					}
				}
				
				if count = count - 1; count == 0 {
					break
				}
			case err := <-watcher.Errors:
				fmt.Println("ERROR", err)
			}
		}
	}()


	project.OutDirectory(*flag.Out)

	app := iris.New()
	app.Logger().SetLevel("debug")
	// Optionally, add two built'n handlers
	// that can recover from any http-relative panics
	// and log the requests to the terminal.
	app.Use(recover.New())
	app.Use(logger.New())

	// Method:   GET
	// Resource: http://localhost:8080/hello
	app.Get("/project", func(ctx iris.Context) {
		ctx.JSON(project)
	})
	
	app.Get("/ws", WsUpgrader)

	app.Run(iris.Addr(":8080"), iris.WithoutServerError(iris.ErrServerClosed))
	return
}

func watchDir(path string, fi os.FileInfo, err error) error {
	
	if fi.Mode().IsDir() {
		return watcher.Add(path)
	}

	return nil
}