package appmanager

import (
	"errors"
	"fmt"
	"io/ioutil"
	"os"
	"os/exec"
	"path"
	"path/filepath"
	"strings"
	"syscall"

	"github.com/golang/glog"
	"gopkg.in/yaml.v2"
)

type Chart struct {
	Name string `yaml:"name"`
	Type string `yaml:"type"`
}

type HelmChart struct {
	Chart
	chartDir string
	Schema   Schema
	Triggers Triggers
	Actions  Actions
	Init     Init
	Yamls    []string
}

func HelmChartFromDir(chartDir string) (*HelmChart, error) {
	var chart HelmChart
	chart.chartDir = chartDir
	err := FromYamlFile(path.Join(chartDir, "Chart.yaml"), &chart.Chart)
	if err != nil {
		return nil, err
	}
	err = FromYamlFile(path.Join(chartDir, "Schema.yaml"), &chart.Schema)
	if err != nil && !os.IsNotExist(err) {
		return nil, err
	}
	err = FromYamlFile(path.Join(chartDir, "Triggers.yaml"), &chart.Triggers)
	if err != nil && !os.IsNotExist(err) {
		return nil, err
	}
	err = FromYamlFile(path.Join(chartDir, "Actions.yaml"), &chart.Actions)
	if err != nil && !os.IsNotExist(err) {
		return nil, err
	}
	err = FromYamlFile(path.Join(chartDir, "Init.yaml"), &chart.Init)
	if err != nil && !os.IsNotExist(err) {
		return nil, err
	}
	return &chart, nil
}

func HelmChartFromTar(chartTar string) (*HelmChart, error) {
	if !strings.HasSuffix(chartTar, ".tar.gz") {
		return nil, errors.New("Expected .tar.gz file")
	}
	dir := filepath.Dir(chartTar)
	archive := filepath.Base(chartTar)
	if err := syscall.Chdir(dir); err != nil {
		return nil, err
	}
	cmd := exec.Command("tar", "-xvf", archive)
	var stdout strings.Builder
	var stderr strings.Builder
	cmd.Stdout = &stdout
	cmd.Stderr = &stderr
	if err := cmd.Run(); err != nil {
		return nil, errors.New(stderr.String())
	}
	glog.Info(stdout.String())
	glog.Info(dir)
	return HelmChartFromDir(dir)
}

func (h *HelmChart) Install(
	helmBin string,
	values map[string]string) error {
	namespace := fmt.Sprintf("app-%s", h.Chart.Name)
	cmd := generateHelmInstallCmd(helmBin, h.chartDir, namespace, values)
	glog.Info(cmd.String())
	var stdout strings.Builder
	var stderr strings.Builder
	cmd.Stdout = &stdout
	cmd.Stderr = &stderr
	err := cmd.Run()
	if err != nil {
		return errors.New(stderr.String())
	}
	glog.Info(stdout.String())
	return nil
}

func generateHelmInstallCmd(
	helmBin string,
	archive string,
	namespace string,
	values map[string]string) *exec.Cmd {
	cmd := exec.Command(helmBin)
	cmd.Args = append(cmd.Args, "install")
	cmd.Args = append(cmd.Args, fmt.Sprintf("--namespace=%s", namespace))
	cmd.Args = append(cmd.Args, "--generate-name")
	cmd.Args = append(cmd.Args, fmt.Sprintf("%s", archive))
	// TODO(giolekva): validate values
	for key, value := range values {
		cmd.Args = append(cmd.Args, fmt.Sprintf("--set=%s=%s", key, value))
	}
	return cmd
}

func ChartFromYaml(str string) (*Chart, error) {
	var s Chart
	err := yaml.Unmarshal([]byte(str), &s)
	if err != nil {
		return nil, err
	}
	return &s, nil
}

func ReadChart(chartFile string) (*Chart, error) {
	f, err := os.Open(chartFile)
	if err != nil {
		return nil, err
	}
	defer f.Close()
	b, err := ioutil.ReadAll(f)
	if err != nil {
		return nil, err
	}
	return ChartFromYaml(string(b))
}
