// Copyright 2017 The Fuchsia 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 project

import (
	"encoding/json"
	"fmt"
	"io/ioutil"
	"net/url"
	"os"
	"path/filepath"
	"strings"
	"sync"

	"go.fuchsia.dev/jiri"
	"go.fuchsia.dev/jiri/gerrit"
	"go.fuchsia.dev/jiri/gitutil"
)

const (
	SourceManifestVersion = int32(0)
)

// This was created using proto file: https://github.com/luci/recipes-py/blob/master/recipe_engine/source_manifest.proto.
type SourceManifest_GitCheckout struct {
	// The canonicalized URL of the original repo that is considered the “source
	// of truth” for the source code. Ex.
	//   https://chromium.googlesource.com/chromium/tools/build.git
	//   https://github.com/luci/recipes-py
	RepoUrl string `json:"repo_url,omitempty"`

	// If different from repo_url, this can be the URL of the repo that the source
	// was actually fetched from (i.e. a mirror). Ex.
	//   https://chromium.googlesource.com/external/github.com/luci/recipes-py
	//
	// If this is empty, it's presumed to be equal to repo_url.
	FetchUrl string `json:"fetch_url,omitempty"`

	// The fully resolved revision (commit hash) of the source. Ex.
	//   3617b0eea7ec74b8e731a23fed2f4070cbc284c4
	//
	// Note that this is the raw revision bytes, not their hex-encoded form.
	Revision string `json:"revision,omitempty"`

	// The ref that the task used to resolve/fetch the revision of the source
	// (if any). Ex.
	//   refs/heads/master
	//   refs/changes/04/511804/4
	//
	// This should always be a ref on the hosted repo (not any local alias
	// like 'refs/remotes/...').
	//
	// This should always be an absolute ref (i.e. starts with 'refs/'). An
	// example of a non-absolute ref would be 'master'.
	FetchRef string `json:"fetch_ref,omitempty"`
}

type SourceManifest_Directory struct {
	GitCheckout *SourceManifest_GitCheckout `json:"git_checkout,omitempty"`
}

type SourceManifest struct {
	// Version will increment on backwards-incompatible changes only. Backwards
	// compatible changes will not alter this version number.
	//
	// Currently, the only valid version number is 0.
	Version int32 `json:"version"`

	// Map of local file system directory path (with forward slashes) to
	// a Directory message containing one or more deployments.
	//
	// The local path is relative to some job-specific root. This should be used
	// for informational/display/organization purposes, and should not be used as
	// a global primary key. i.e. if you depend on chromium/src.git being in
	// a folder called “src”, I will find you and make really angry faces at you
	// until you change it...（╬ಠ益ಠ). Instead, implementations should consider
	// indexing by e.g. git repository URL or cipd package name as more better
	// primary keys.
	Directories map[string]*SourceManifest_Directory `json:"directories"`
}

func getCLRefByCommit(jirix *jiri.X, gerritHost, revision string) (string, error) {
	hostUrl, err := url.Parse(gerritHost)
	if err != nil {
		return "", fmt.Errorf("invalid gerrit host %q: %s", gerritHost, err)
	}
	g := gerrit.New(jirix, hostUrl)
	cls, err := g.ListChangesByCommit(revision)
	if err != nil {
		return "", fmt.Errorf("not able to get CL for revision %s: %s", revision, err)
	}
	for _, c := range cls {
		if v, ok := c.Revisions[revision]; ok {
			return v.Fetch.Ref, nil
		}
	}
	return "", nil
}

func NewSourceManifest(jirix *jiri.X, projects Projects) (*SourceManifest, MultiError) {
	jirix.TimerPush("create source manifest")
	defer jirix.TimerPop()

	workQueue := make(chan Project, len(projects))
	for _, proj := range projects {
		if err := proj.relativizePaths(jirix.Root); err != nil {
			return nil, MultiError{err}
		}
		workQueue <- proj
	}
	close(workQueue)
	errs := make(chan error, len(projects))
	sm := &SourceManifest{
		Version:     SourceManifestVersion,
		Directories: make(map[string]*SourceManifest_Directory),
	}
	var mux sync.Mutex
	processProject := func(proj Project) error {
		gc := &SourceManifest_GitCheckout{
			RepoUrl: rewriteRemote(jirix, proj.Remote),
		}
		scm := gitutil.New(jirix, gitutil.RootDirOpt(filepath.Join(jirix.Root, proj.Path)))
		if rev, err := scm.CurrentRevision(); err != nil {
			return err
		} else {
			gc.Revision = rev
		}
		if proj.RemoteBranch == "" {
			proj.RemoteBranch = "master"
		}
		branchMap, err := scm.ListRemoteBranchesContainingRef(gc.Revision)
		if err != nil {
			return err
		}
		if branchMap["origin/"+proj.RemoteBranch] {
			gc.FetchRef = "refs/heads/" + proj.RemoteBranch
		} else {
			for b := range branchMap {
				if strings.HasPrefix(b, "origin/HEAD ") {
					continue
				}
				if strings.HasPrefix(b, "origin") {
					gc.FetchRef = "refs/heads/" + strings.TrimLeft(b, "origin/")
					break
				}
			}

			// Try getting from gerrit
			if gc.FetchRef == "" && proj.GerritHost != "" {
				if ref, err := getCLRefByCommit(jirix, proj.GerritHost, gc.Revision); err != nil {
					// Don't fail
					jirix.Logger.Debugf("Error while fetching from gerrit for project %q: %s", proj.Name, err)
				} else if ref == "" {
					jirix.Logger.Debugf("Cannot get ref for project: %q, revision: %q", proj.Name, gc.Revision)
				} else {
					gc.FetchRef = ref
				}
			}
		}
		mux.Lock()
		sm.Directories[proj.Path] = &SourceManifest_Directory{GitCheckout: gc}
		mux.Unlock()
		return nil
	}

	var wg sync.WaitGroup
	for i := uint(0); i < jirix.Jobs; i++ {
		wg.Add(1)
		go func() {
			defer wg.Done()
			for p := range workQueue {
				if err := processProject(p); err != nil {
					errs <- err
				}
			}
		}()
	}
	wg.Wait()
	close(errs)
	var multiErr MultiError
	for err := range errs {
		multiErr = append(multiErr, err)
	}
	return sm, multiErr
}

func (sm *SourceManifest) ToFile(jirix *jiri.X, filename string) error {
	if err := os.MkdirAll(filepath.Dir(filename), 0755); err != nil {
		return fmtError(err)
	}
	out, err := json.MarshalIndent(sm, "", "  ")
	if err != nil {
		return fmt.Errorf("failed to serialize JSON output: %s\n", err)
	}

	err = ioutil.WriteFile(filename, out, 0600)
	if err != nil {
		return fmt.Errorf("failed write JSON output to %s: %s\n", filename, err)
	}

	return nil
}
