// 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 nacl_profile

import (
	"flag"
	"fmt"
	"path/filepath"
	"runtime"

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

const (
	gitRemote = "https://vanadium.googlesource.com/release.go.ppapi"
)

type versionSpec struct {
	gitRevision 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{"5e967194049bd1a6f097854f09fcbbbaa21afc05"},
			"2": &versionSpec{"5e967194049bd1a6f097854f09fcbbbaa21afc05"},
		}, "2"),
	}
	profilesmanager.Register(m)
}

type Manager struct {
	profileInstaller, profileName, qualifiedName string
	root, naclRoot                               jiri.RelPath
	naclSrcDir, naclInstDir                      jiri.RelPath
	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) VersionInfo() *profiles.VersionInfo {
	return m.versionInfo
}

func (m Manager) Info() string {
	return `
The nacl profile provides support for native client builds for chrome. It
clones and builds the go.ppapi git repository. It supports a single target of
amd64p32-nacl and assumes it as the default`
}

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

func (m *Manager) initForTarget(jirix *jiri.X, action string, root jiri.RelPath, target *profiles.Target) error {
	m.root = root
	m.naclRoot = root.Join("nacl")
	if !target.IsSet() {
		def := *target
		target.Set("amd64p32-nacl")
		fmt.Fprintf(jirix.Stdout(), "Default target %v reinterpreted as: %v\n", def, target)
	} else {
		if target.Arch() != "amd64p32" && target.OS() != "nacl" {
			return fmt.Errorf("this profile can only be %v as amd64p32-nacl and not as %v", action, target)
		}
	}
	if err := m.versionInfo.Lookup(target.Version(), &m.spec); err != nil {
		return err
	}
	m.naclSrcDir = m.naclRoot.Join(m.spec.gitRevision)
	m.naclInstDir = m.naclRoot.Join(target.TargetSpecificDirname(), m.spec.gitRevision)
	return nil
}

func (m *Manager) OSPackages(jirix *jiri.X, pdb *profiles.DB, root jiri.RelPath, target profiles.Target) ([]string, error) {
	switch runtime.GOOS {
	case "darwin":
	case "linux":
		return []string{"g++", "libc6-i386", "zip"}, nil
	default:
		return nil, fmt.Errorf("%q is not supported", target.OS)
	}
	return nil, nil
}

func (m *Manager) Install(jirix *jiri.X, pdb *profiles.DB, root jiri.RelPath, target profiles.Target) error {
	if err := m.initForTarget(jirix, "installed", root, &target); err != nil {
		return err
	}
	if p := pdb.LookupProfileTarget(m.profileInstaller, m.profileName, target); p != nil {
		fmt.Fprintf(jirix.Stdout(), "%v %v is already installed as %v\n", m.qualifiedName, target, p)
		return nil
	}
	if err := m.installNacl(jirix, target, m.spec); err != nil {
		return err
	}
	target.Env.Vars = envvar.MergeSlices(target.Env.Vars, []string{
		"GOARCH=amd64p32",
		"GOOS=nacl",
		"GOROOT=" + m.naclInstDir.Symbolic(),
	})
	target.InstallationDir = string(m.naclInstDir)
	pdb.InstallProfile(m.profileInstaller, m.profileName, string(m.naclRoot))
	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 {
	// ignore errors to allow for older installs to be removed.
	m.initForTarget(jirix, "uninstalled", root, &target)

	s := jirix.NewSeq()
	if err := s.RemoveAll(m.naclInstDir.Abs(jirix)).
		RemoveAll(m.naclSrcDir.Abs(jirix)).Done(); err != nil {
		return err
	}
	if pdb.RemoveProfileTarget(m.profileInstaller, m.profileName, target) {
		return s.RemoveAll(m.naclRoot.Abs(jirix)).Done()
	}
	return nil
}

// installNacl installs the nacl profile.
func (m *Manager) installNacl(jirix *jiri.X, target profiles.Target, spec versionSpec) error {
	naclSrcDir := m.naclSrcDir.Abs(jirix)
	naclInstDir := m.naclInstDir.Abs(jirix)
	cloneGoPpapiFn := func() error {
		s := jirix.NewSeq()
		tmpDir, err := s.TempDir("", "")
		if err != nil {
			return err
		}
		defer jirix.NewSeq().RemoveAll(tmpDir)
		return s.Pushd(tmpDir).
			Call(func() error { return gitutil.New(jirix.NewSeq()).CloneRecursive(gitRemote, tmpDir) }, "").
			Call(func() error { return gitutil.New(jirix.NewSeq()).Reset(m.spec.gitRevision) }, "").
			Popd().
			MkdirAll(m.naclRoot.Abs(jirix), profilesutil.DefaultDirPerm).
			RemoveAll(naclSrcDir).
			Rename(tmpDir, naclSrcDir).Done()
	}
	// Cloning is slow so we handle it as an atomic action and then create
	// a copy for the actual build.
	if err := profilesutil.AtomicAction(jirix, cloneGoPpapiFn, naclSrcDir, "Clone Go Ppapi repository"); err != nil {
		return err
	}

	// Compile the Go Ppapi compiler.
	compileGoPpapiFn := func() error {
		dir := filepath.Dir(naclInstDir)
		goPpapiCompileScript := filepath.Join(naclInstDir, "src", "make-nacl-amd64p32.sh")
		return jirix.NewSeq().MkdirAll(dir, profilesutil.DefaultDirPerm).
			Run("cp", "-r", naclSrcDir, naclInstDir).
			Last(goPpapiCompileScript)
	}
	return profilesutil.AtomicAction(jirix, compileGoPpapiFn, naclInstDir, "Compile Go Ppapi compiler")
}
