// Copyright 2015 The Vanadium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package base_profile

import (
	"flag"
	"fmt"

	"v.io/jiri"
	"v.io/jiri/profiles"
	"v.io/jiri/profiles/profilesmanager"
	"v.io/jiri/profiles/profilesreader"
	"v.io/x/lib/envvar"
)

type versionSpec struct {
	dependencies []struct{ name, version string }
}

func Register(installer, profile string) {
	m := &Manager{
		profileInstaller: installer,
		profileName:      profile,
		qualifiedName:    profiles.QualifiedProfileName(installer, profile),
		versionInfo: profiles.NewVersionInfo(profile,
			map[string]interface{}{
				"1": &versionSpec{[]struct{ name, version string }{
					{"go", ""},
					{"syncbase", ""}},
				},
				"2": &versionSpec{[]struct{ name, version string }{
					{"go", "1.5.1.1:2738c5e0"},
					{"syncbase", ""}},
				},
				"3": &versionSpec{[]struct{ name, version string }{
					{"go", "1.5.2"},
					{"syncbase", ""}},
				},
				"4": &versionSpec{[]struct{ name, version string }{
					{"go", "1.5.2.1:56093743"},
					{"syncbase", ""}},
				},
				"5": &versionSpec{[]struct{ name, version string }{
					{"go", "1.6"},
					{"syncbase", ""}},
				},
			}, "5"),
	}
	profilesmanager.Register(m)
}

type Manager struct {
	profileInstaller, profileName, qualifiedName string
	versionInfo                                  *profiles.VersionInfo
	spec                                         versionSpec
}

func (m Manager) Name() string {
	return m.profileName
}

func (m Manager) Installer() string {
	return m.profileInstaller
}

func (m Manager) String() string {
	return fmt.Sprintf("%s[%s]", m.qualifiedName, m.versionInfo.Default())
}

func (m Manager) Info() string {
	return `
The base profile is a convenient shorthand for installing the profiles that all
vanadium projects need, this is currently go and syncbase.`
}

func (m Manager) VersionInfo() *profiles.VersionInfo {
	return m.versionInfo
}

func (m *Manager) AddFlags(flags *flag.FlagSet, action profiles.Action) {
}

func (m *Manager) OSPackages(jirix *jiri.X, pdb *profiles.DB, root jiri.RelPath, target profiles.Target) ([]string, error) {
	if err := m.versionInfo.Lookup(target.Version(), &m.spec); err != nil {
		return nil, err
	}
	var packages []string
	if !target.CrossCompiling() && target.OS() == "linux" && (target.Version() == "1" || target.Version() == "2" || target.Version() == "3" || target.Version() == "4") {
		// Version 5 onwards uses go 1.6+, where there is no need for "libssl-dev".
		packages = []string{"libssl-dev"}
	}
	// Get packages from dependent profiles.
	// TODO(nlacasse): Consider making the notion of "dependent profiles"
	// something that jiri understands, and move this logic (and the similar
	// logic in Install) into jiri.
	for _, profile := range m.spec.dependencies {
		qname := profiles.QualifiedProfileName(m.profileInstaller, profile.name)
		depManager := profilesmanager.LookupManager(qname)
		if depManager == nil {
			return nil, fmt.Errorf("no manager found for dependent profile %v", profile.name)
		}
		depPackages, err := depManager.OSPackages(jirix, pdb, root, target)
		if err != nil {
			return nil, err
		}
		packages = append(packages, depPackages...)
	}
	return packages, nil
}

func (m *Manager) Install(jirix *jiri.X, pdb *profiles.DB, root jiri.RelPath, target profiles.Target) error {
	if err := m.versionInfo.Lookup(target.Version(), &m.spec); err != nil {
		return err
	}
	// Install profiles.
	profileEnvs := [][]string{}
	for _, profile := range m.spec.dependencies {
		dependency := target
		dependency.SetVersion(profile.version)
		if err := profilesmanager.EnsureProfileTargetIsInstalled(jirix, pdb, m.profileInstaller, profile.name, root, dependency); err != nil {
			return err
		}
		installed := pdb.LookupProfileTarget(m.profileInstaller, profile.name, dependency)
		if installed == nil {
			return fmt.Errorf("%s %s should have been installed, but apparently is not", profile.name, dependency)
		}
		profileEnvs = append(profileEnvs, installed.Env.Vars)
	}
	// Merge the environments for go and syncbase and store it in the base profile.
	base := envvar.VarsFromSlice(target.Env.Vars)
	base.Set("GOARCH", target.Arch())
	// iOS specifically uses Darwin as its GOOS. Using "ios" aka target.OS() will make go cry.
	os := target.OS()
	if target.OS() == "ios" {
		os = "darwin"
	}
	base.Set("GOOS", os)
	// Slight modifications to ProfileMergePolicies: Want the values from
	// the "go" profile we depend on to prevail.
	mp := profilesreader.ProfileMergePolicies()
	mp["GOROOT"] = profilesreader.UseLast
	mp["GOROOT_BOOTSTRAP"] = profilesreader.IgnoreBaseUseLast
	mp["CGO_ENABLED"] = profilesreader.IgnoreBaseUseLast
	profilesreader.MergeEnv(mp, base, profileEnvs...)
	target.Env.Vars = base.ToSlice()
	pdb.InstallProfile(m.profileInstaller, m.profileName, string(root))
	return pdb.AddProfileTarget(m.profileInstaller, m.profileName, target)
}

func (m *Manager) Uninstall(jirix *jiri.X, pdb *profiles.DB, root jiri.RelPath, target profiles.Target) error {
	if err := m.versionInfo.Lookup(target.Version(), &m.spec); err != nil {
		return err
	}
	for _, profile := range m.spec.dependencies {
		dependency := target
		dependency.SetVersion(profile.version)
		if err := profilesmanager.EnsureProfileTargetIsUninstalled(jirix, pdb, m.profileInstaller, profile.name, root, dependency); err != nil {
			return err
		}
	}
	pdb.RemoveProfileTarget(m.profileInstaller, m.profileName, target)
	return nil
}
