package install

import (
    "fmt"
    "sync"
    "os"

    log "oc-deploy/log_wrapper"
    "oc-deploy/utils"
    "oc-deploy/tool"
    "oc-deploy/chart"
    "oc-deploy/helm"
    "oc-deploy/kubectl"
    "oc-deploy/versionOc"
)

type InstallClass struct {
    Version string
    Workspace string

    // versionFile string
    tools []tool.ToolData
    toolsBin map[string]string
    charts []chart.ChartRepoData
}

func (this *InstallClass) NewInstall() (string, error) {

    // Extraction du fichier de version
    dst := fmt.Sprintf("%s/oc.yml", this.Workspace)
    log.Log().Debug().Msg(fmt.Sprintf("Check du fichier de version : %s", dst))
    if _, err := os.Stat(dst); err == nil {
        log.Log().Debug().Msg("Existe déjà")
        version, err := versionOc.GetFromFile(dst)
        if err != nil {
            return "", err
        }
        this.Version = version
    } else {
        log.Log().Debug().Msg("Téléchargement du fichier de version")
        version, err := versionOc.Get(this.Version)
        if err != nil {
            return "", err
        }
        src := fmt.Sprintf("../offline/oc_%s.yml", version)
        err = utils.CopyFile(src, dst)
        if err != nil {
            return "", err
        }
    }

    // Lecture du fichier de conf
    // this.versionFile = dst

    this.tools = tool.FromConfigFile(dst)
    this.charts = chart.FromConfigFile(dst)

    return dst, nil
}


func (this *InstallClass) ChartRepo() (error) {

    bin_path, _ := this.getToolBin("helm")

    for _, v := range this.charts {
        log.Log().Info().Msg(fmt.Sprintf("  >> Helm Repo : %s", v.Name))
        repo := helm.HelmRepo{Bin: bin_path,
                              Name: v.Name,
                              Repository: v.Repository,
                              ForceUpdate: true}
        res, err := repo.AddRepository()
        if err != nil {
            log.Log().Info().Msg(fmt.Sprintf("  <<             %s ", err))
            return err
        }
        log.Log().Info().Msg(fmt.Sprintf("  <<             %s ", res))

    }
    return nil
}


func (this *InstallClass) InstallCharts() (error) {
    helm_bin, _ := this.getToolBin("helm")
    kubectl_bin, _ := this.getToolBin("kubectl")

    var wg sync.WaitGroup

    for _, v := range this.charts {
        for _, v1 := range v.Charts {
            wg.Add(1)

            go func() {
                defer wg.Done()
                this.installChart(helm_bin, kubectl_bin, v1)
            } ()
            
        }
    }
    wg.Wait()
    return nil
}

func (this *InstallClass) installChart(helm_bin string, kubectl_bin string, chart chart.ChartData) {

    log.Log().Info().Msg(fmt.Sprintf("  << Chart     : %s ", chart.Name))

    helmchart := helm.HelmChart{Bin: helm_bin,
                                Name: chart.Name,
                                Chart: chart.Chart,
                                Version: chart.Version,
                                Workspace: this.Workspace,
                                Opts: chart.Opts,
                                Values: chart.Values,
                                FileValues: chart.FileValues}

    obj := kubectl.KubeObject{Bin: kubectl_bin,
                              Name: chart.Name}

    res, err := helmchart.Install()
    if err != nil {
        log.Log().Error().Msg(fmt.Sprintf("  >>              %s %s (%s)", helmchart.Name, "KO", err))
        return
    }
    log.Log().Info().Msg(fmt.Sprintf("  >>             %s (%s)", helmchart.Name, res))

    err = obj.Wait()
    if err != nil {
        log.Log().Error().Msg(fmt.Sprintf("  >>             %s %s (%s)", chart.Name, "KO", err))
    } else {
        log.Log().Info().Msg(fmt.Sprintf("  >>             %s %s", chart.Name, "OK"))
    }
}