package main

import (
	"fmt"
	"io/ioutil"
	"net/http"
	"os"
	"strings"

	"go.wit.com/lib/protobuf/virtpb"
	"go.wit.com/lib/virtigolib"
	"go.wit.com/log"
)

// remove '?' part and trailing '/'
func cleanURL(url string) string {
	url = "/" + strings.Trim(url, "/")
	return url
}

func okHandler(w http.ResponseWriter, r *http.Request) {
	var route string
	route = cleanURL(r.URL.Path)
	log.HttpMode(w)
	defer log.HttpMode(nil)

	msg, err := ioutil.ReadAll(r.Body) // Read the body as []byte
	if err != nil {
		log.Info("ReadAll() error =", err)
		return
	}
	if route == "/uptime" {
		ok, s := uptimeCheck()
		log.Info(s)
		if ok {
			// log.Info("Handling URL:", route, "cluster is ok")
		} else {
			log.Info("Handling URL:", route, "cluster is not right yet")
		}
		return
	}

	if route == "/create" {
		var d *virtpb.Droplet
		d = new(virtpb.Droplet)
		if err := d.Unmarshal(msg); err != nil {
			log.Info("proto.Unmarshal() failed on wire message len", len(msg))
			log.Info("error =", err)
			return
		}
		log.Info("proto.Unmarshal() worked on msg len", len(msg), "hostname =", d.Hostname)
		found := me.cluster.FindDropletByName(d.Hostname)
		if found != nil {
			log.Info("already have hostname ", d.Hostname)
			return
		}
		log.Info("new hostname ", d.Hostname)
		if !me.cluster.AddDroplet(d) {
			log.Info("new hostname added ok ", d.Hostname)
		} else {
			log.Info("hostname add failed for ", d.Hostname)
		}
		if err := me.cluster.ConfigSave(); err != nil {
			log.Info("configsave error", err)
			os.Exit(-1)
		}
		log.Info("config file saved")
		return
	}

	if route == "/start" {
		hostname := r.URL.Query().Get("hostname")
		if hostname == "" {
			log.Warn("start failed. hostname is blank", cleanURL(r.URL.Path))
			return
		}
		log.Warn("hostname is", hostname)

		// log.Warn("Handling URL:", tmp, "start droplet", start)
		result, err := Start(hostname)
		if err == nil {
			log.Info(result)
			log.Info(hostname, "started output ok")
			log.Info(hostname, "need to parse the output here")
			log.Info(hostname, "todo: switch to protobuf here")
		} else {
			log.Info(result)
			log.Info(err)
			log.Info(hostname, "start failed")
		}
		return
	}

	if route == "/import" {
		log.Info("virtigo import starts here")
		result, err := importDomain(w, r)
		if err != nil {
			log.Info("virtigo import failed")
			log.Info(result)
			return
		}
		log.Info("virtigo import worked")
		return
	}

	// toggle poll logging
	if route == "/poll" {
		if POLL.Enabled() {
			log.Info("POLL is true")
			POLL.SetBool(false)
		} else {
			log.Info("POLL is false")
			POLL.SetBool(true)
		}
		return
	}

	if route == "/dumpcluster" {
		dumpCluster(w)
		return
	}

	if route == "/dumpdroplet" {
		me.cluster.DumpDroplet(w, r)
		return
	}

	if route == "/dumpdroplets" {
		dumpDroplets(w, false)
		return
	}

	if route == "/dumpdropletsfull" {
		dumpDroplets(w, true)
		return
	}

	if route == "/dumphypervisors" {
		dumpHypervisors(w)
		return
	}

	if route == "/dumplibvirtxml" {
		virtigolib.DumpLibvirtxmlDomainNames()
		return
	}

	if route == "/quit" {
		log.Warn("writing out config file and exiting virtigo")
		if err := me.cluster.ConfigSave(); err != nil {
			log.Info("configsave error", err)
		} else {
			os.Exit(-1)
		}
		return
	}

	if route == "/favicon.ico" {
		// w.Header().Set("Content-Type", "image/svg+xml")
		w.Header().Set("Content-Type", "image/png")
		writeFile(w, "ipv6.png")
		return
	}

	if route == "/goReference.svg" {
		w.Header().Set("Content-Type", "image/svg+xml")
		writeFile(w, "goReference.svg")
		return
	}

	log.Warn("BAD URL =", route)
}

// write a file out to the http socket
func writeFile(w http.ResponseWriter, filename string) {
	fullname := "resources/" + filename
	pfile, err := resources.ReadFile(fullname)
	if err != nil {
		log.Println("ERROR:", err)
		// w.Write(pfile)
		return
	}

	var repohtml string
	repohtml = string(pfile)
	if filename == "goReference.svg" {
		w.Header().Set("Content-Type", "image/svg+xml")
	}
	fmt.Fprintln(w, repohtml)
	log.Println("writeFile() found internal file:", filename)
}

// starts and sits waiting for HTTP requests
func startHTTP() {
	http.HandleFunc("/", okHandler)

	p := fmt.Sprintf(":%d", argv.Port)
	log.Println("Running on port", p)

	err := http.ListenAndServe(p, nil)
	if err != nil {
		log.Println("Error starting server:", err)
	}
}