package main

import (
	"bytes"
	"context"
	"encoding/json"
	"flag"
	"fmt"
	"io"
	"io/ioutil"
	"log"
	"net/http"
	"os"
	"syscall"

	"github.com/golang/glog"
	"github.com/google/uuid"
	apiv1 "k8s.io/api/core/v1"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"k8s.io/client-go/kubernetes"
	corev1 "k8s.io/client-go/kubernetes/typed/core/v1"
	"k8s.io/client-go/rest"
	"k8s.io/client-go/tools/clientcmd"

	app "github.com/giolekva/pcloud/appmanager"
)

var kubeconfig = flag.String("kubeconfig", "", "Absolute path to the kubeconfig file.")
var helmBin = flag.String("helm_bin", "/usr/local/bin/helm", "Path to the Helm binary.")
var port = flag.Int("port", 1234, "Port to listen on.")
var apiAddr = flag.String("api_addr", "", "PCloud API service address.")
var managerStoreFile = flag.String("manager_store_file", "", "Persistent file containing installed application information.")

var helmUploadPage = `
<html>
<head>
       <title>Upload Helm chart</title>
</head>
<body>
<form enctype="multipart/form-data" method="post">
    <input type="file" name="chartfile" />
    <input type="submit" value="upload" />
</form>
</body>
</html>
`

type handler struct {
	client   *kubernetes.Clientset
	manager  *app.Manager
	launcher app.Launcher
}

func (hn *handler) handleInstall(w http.ResponseWriter, r *http.Request) {
	if r.Method == "GET" {
		_, err := io.WriteString(w, helmUploadPage)
		if err != nil {
			http.Error(w, err.Error(), http.StatusInternalServerError)
		}
	} else if r.Method == "POST" {
		r.ParseMultipartForm(1000000)
		file, handler, err := r.FormFile("chartfile")
		if err != nil {
			http.Error(w, err.Error(), http.StatusInternalServerError)
			return
		}
		defer file.Close()
		tmp := uuid.New().String()
		if tmp == "" {
			http.Error(w, "Could not generate temp dir", http.StatusInternalServerError)
			return
		}
		p := "/tmp/" + tmp
		// TODO(giolekva): defer rmdir
		if err := syscall.Mkdir(p, 0777); err != nil {
			http.Error(w, "Could not create temp dir", http.StatusInternalServerError)
			return
		}
		p += "/" + handler.Filename
		f, err := os.OpenFile(p, os.O_WRONLY|os.O_CREATE, 0666)
		if err != nil {
			fmt.Println(err)
			return
		}
		defer f.Close()
		_, err = io.Copy(f, file)
		if err != nil {
			http.Error(w, err.Error(), http.StatusInternalServerError)
			return
		}
		if err = hn.installHelmChart(p); err != nil {
			http.Error(w, err.Error(), http.StatusInternalServerError)
			return
		}
		w.Write([]byte("Installed"))
	}
}

type trigger struct {
	Namespace string `json:"namespace"`
	Template  string `json:"template"`
}

func (hn *handler) handleTriggers(w http.ResponseWriter, r *http.Request) {
	if r.Method != "GET" {
		http.Error(w, "Only GET method is supported on /triggers", http.StatusBadRequest)
		return
	}
	if err := r.ParseForm(); err != nil {
		http.Error(w, err.Error(), http.StatusBadRequest)
		return
	}
	// TODO(giolekva): check if exists
	triggerOnType := r.Form["trigger_on_type"][0]
	triggerOnEvent := r.Form["trigger_on_event"][0]
	var triggers []trigger
	for _, a := range hn.manager.Apps {
		for _, t := range a.Triggers.Triggers {
			if t.TriggerOn.Type == triggerOnType && t.TriggerOn.Event == triggerOnEvent {
				triggers = append(triggers, trigger{a.Namespace, t.Template})
			}
		}
	}
	respBody, err := json.Marshal(triggers)
	if err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}
	if _, err := io.Copy(w, bytes.NewReader(respBody)); err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}
}

type actionReq struct {
	App    string                 `json:"app"`
	Action string                 `json:"action"`
	Args   map[string]interface{} `json:"args"`
}

func (hn *handler) handleLaunchAction(w http.ResponseWriter, r *http.Request) {
	actionStr, err := ioutil.ReadAll(r.Body)
	if err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}
	var req actionReq
	if err := json.Unmarshal(actionStr, &req); err != nil {
		http.Error(w, err.Error(), http.StatusBadRequest)
		return
	}
	for _, a := range hn.manager.Apps {
		if a.Name != req.App {
			continue
		}
		for _, action := range a.Actions.Actions {
			if action.Name != req.Action {
				continue
			}
			err := hn.launcher.Launch(a.Namespace, action.Template, req.Args)
			if err != nil {
				http.Error(w, err.Error(), http.StatusInternalServerError)
			}
			return
		}
	}
	http.Error(
		w,
		fmt.Sprintf("Application action not found: %s %s", req.App, req.Action),
		http.StatusBadRequest)
}

func (hn *handler) installHelmChart(path string) error {
	h, err := app.HelmChartFromTar(path)
	if err != nil {
		return err
	}
	if err = app.InstallSchema(h.Schema, *apiAddr); err != nil {
		return err
	}
	glog.Infof("Installed schema: %s", h.Schema)
	namespace := fmt.Sprintf("app-%s", h.Name)
	err = createNamespace(hn.client.CoreV1().Namespaces(), namespace)
	if err != nil {
		return err
	}
	glog.Infof("Created namespaces: %s", namespace)
	if h.Type == "application" {
		if err = h.Install(
			*helmBin,
			map[string]string{}); err != nil {
			return err
		}
		glog.Info("Deployed")
	} else {
		glog.Info("Skipping deployment as we got library chart.")
	}
	hn.manager.Apps[h.Name] = app.App{h.Name, namespace, h.Triggers, h.Actions}
	app.StoreManagerStateToFile(hn.manager, *managerStoreFile)
	glog.Info("Installed")
	return nil
}

func createNamespace(nsClient corev1.NamespaceInterface, name string) error {
	_, err := nsClient.Create(
		context.TODO(),
		&apiv1.Namespace{
			ObjectMeta: metav1.ObjectMeta{
				Name: name}},
		metav1.CreateOptions{})
	return err
}

func getKubeConfig() (*rest.Config, error) {
	if *kubeconfig != "" {
		return clientcmd.BuildConfigFromFlags("", *kubeconfig)
	} else {
		return rest.InClusterConfig()
	}
}

func main() {
	flag.Parse()
	config, err := getKubeConfig()
	if err != nil {
		glog.Fatalf("Could not initialize Kubeconfig: %v", err)
	}
	clientset, err := kubernetes.NewForConfig(config)
	if err != nil {
		glog.Fatalf("Could not create Kubernetes API client: %v", err)
	}
	manager, err := app.LoadManagerStateFromFile(*managerStoreFile)
	if err != nil {
		glog.Fatalf("Could ot initialize manager: %v", err)
	}
	h := handler{clientset, manager, app.NewK8sLauncher(clientset)}
	http.HandleFunc("/triggers", h.handleTriggers)
	http.HandleFunc("/launch_action", h.handleLaunchAction)
	http.HandleFunc("/", h.handleInstall)
	log.Fatal(http.ListenAndServe(fmt.Sprintf(":%d", *port), nil))

}
