package main

import (
	"encoding/binary"
	"encoding/json"
	"fmt"
	"net"
	"log"
	"io"
	"os"
)

func startctl(reportPostChan chan ReportPost) {
	log.Print("Starting ctl listener on 127.0.0.1:5555")
	l, err := net.Listen("tcp", "127.0.0.1:5555")
	if err != nil {
		log.Fatal("Unable to start listener:", err)
	}
	defer l.Close()

	commandClient := make(chan net.Conn)

	go func(l net.Listener) {
		for {
			c, err := l.Accept()
			if err != nil {
				log.Fatal("Error on accept", err)
			}
			commandClient <- c
		}
	}(l)

	for {
		c := <-commandClient	// New client connection
		go handleClient(c, reportPostChan)
	}

}

func handleClient(commandClient net.Conn, reportPostChan chan ReportPost) {

	sizebyte := make([]byte, 4)
	var commandmap CommandMap
	var responseback ResponseBack
	n, err := io.ReadFull(commandClient, sizebyte)
	if err != nil {
		fmt.Println("Read error", err)
		os.Exit(1)
	}
	if n != 4 {
		fmt.Println("Did not read 4 bytes, failure.")
		os.Exit(1)
	}
	jsonsize := int(binary.LittleEndian.Uint32(sizebyte))
	jsonbyte := make([]byte, jsonsize)
	n, err = io.ReadFull(commandClient, jsonbyte)
	if err != nil {
		log.Fatal("Unable to unmarshal")
	}
	if n != jsonsize {
		log.Fatal("Failed to read json size of ", n)
	}

	err = json.Unmarshal(jsonbyte, &commandmap)
	if err != nil {
		log.Fatal("Unable to unmarshal")
	}

	switch commandmap.Type {
	case "status":
		responseback.Message = "Ok"
	case "add":
		log.Print("Manually added instance: " + commandmap.Endpoint)
		ri_mutex.Lock()
		_, exists := runninginstances[commandmap.Endpoint]
		if exists == true {
			log.Println("Already exists: " + commandmap.Endpoint)
			responseback.Message = "Exists: " + commandmap.Endpoint
		} else {
			responseback.Message = "Added: " + commandmap.Endpoint
			runninginstances[commandmap.Endpoint] = RunningInstance{}
			go StartInstance(commandmap.Endpoint, reportPostChan)
		}
		ri_mutex.Unlock()
	case "suspend":
		fmt.Println("Suspend")
	case "resume":
		fmt.Println("Resume")
	default:
		fmt.Println("Something else")
	}


	responseback.Type = "status"
	responseback.RunningInstances = runninginstances

	responsebytes, err := json.Marshal(responseback)
	if err != nil {
		fmt.Println("Error: ", err)
		os.Exit(1)
	}

	n = len(responsebytes)
	binary.LittleEndian.PutUint32(sizebyte, uint32(n))

	_, err = commandClient.Write(sizebyte)
	if err != nil {
		fmt.Println("Error on write:", err)
		os.Exit(1)
	}

	responsebyte, err := json.Marshal(responseback)
	if err != nil {
		fmt.Println("Error response back: ", err)
		os.Exit(1)
	}

	_, err = commandClient.Write(responsebyte)
	if err != nil {
		fmt.Println("Error on write:", err)
		os.Exit(1)
	}
	commandClient.Close()
}