package vendor

import (
	"bytes"
	"encoding/json"
	"errors"
	"fmt"
	"io"
	"log"
	"os"
	"reflect"
	"sort"
	"strings"
)

// gb-vendor manifest support

// Manifest describes the layout of $PROJECT/vendor/manifest.
type Manifest struct {
	// Manifest version. Current manifest version is 0.
	Version int `json:"version"`

	// Depenencies is a list of vendored dependencies.
	Dependencies []Dependency `json:"dependencies"`
}

var (
	DepPresent       = errors.New("dependency already present")
	DepSubPkgPresent = errors.New("subpackages of this dependency are already present")
	DepMissing       = errors.New("dependency does not exist")
)

// AddDependency adds a Dependency to the current Manifest.
// If the dependency exists already then it returns and error.
func (m *Manifest) AddDependency(dep Dependency) error {
	if m.HasImportpath(dep.Importpath) {
		return DepPresent
	}
	if m.GetSubpackages(dep.Importpath) != nil {
		return DepSubPkgPresent
	}
	m.Dependencies = append(m.Dependencies, dep)
	return nil
}

// RemoveDependency removes a Dependency from the current Manifest.
// If the dependency does not exist then it returns an error.
func (m *Manifest) RemoveDependency(dep Dependency) error {
	for i, d := range m.Dependencies {
		if reflect.DeepEqual(d, dep) {
			m.Dependencies = append(m.Dependencies[:i], m.Dependencies[i+1:]...)
			return nil
		}
	}
	return DepMissing
}

// HasImportpath reports whether the Manifest contains the import path,
// or a parent of it.
func (m *Manifest) HasImportpath(path string) bool {
	_, err := m.GetDependencyForImportpath(path)
	return err == nil
}

// GetDependencyForRepository return a dependency for specified import
// path. Note that it might be a parent of the specified path.
// If the dependency does not exist it returns an error.
func (m *Manifest) GetDependencyForImportpath(path string) (Dependency, error) {
	for _, d := range m.Dependencies {
		if path == d.Importpath || strings.HasPrefix(path, d.Importpath+"/") {
			return d, nil
		}
	}
	return Dependency{}, fmt.Errorf("dependency for %s does not exist", path)
}

// GetSubpackages returns any Dependency in the Manifest that is a subpackage
// of the given import path.
func (m *Manifest) GetSubpackages(path string) (deps []Dependency) {
	for _, d := range m.Dependencies {
		if path != d.Importpath && strings.HasPrefix(d.Importpath, path+"/") {
			deps = append(deps, d)
		}
	}
	return
}

// Dependency describes one vendored import path of code
// A Dependency is an Importpath sources from a Respository
// at Revision from Path.
type Dependency struct {
	// Importpath is name by which this dependency is known.
	Importpath string `json:"importpath"`

	// Repository is the remote DVCS location that this
	// dependency was fetched from.
	Repository string `json:"repository"`

	// VCS is the DVCS system found at Repository.
	VCS string `json:"vcs"`

	// Revision is the revision that describes the dependency's
	// remote revision.
	Revision string `json:"revision"`

	// Branch is the branch the Revision was located on.
	// Can be blank if not needed.
	Branch string `json:"branch"`

	// Path is the path inside the Repository where the
	// dependency was fetched from.
	Path string `json:"path,omitempty"`

	// NoTests indicates that test files were ignored.
	// In the negative for backwards compatibility.
	NoTests bool `json:"notests,omitempty"`

	// AllFiles indicates that no files were ignored.
	AllFiles bool `json:"allfiles,omitempty"`
}

// WriteManifest writes a Manifest to the path. If the manifest does
// not exist, it is created. If it does exist, it will be overwritten.
// If the manifest file is empty (0 dependencies) it will be deleted.
// The dependencies will be ordered by import path to reduce churn when making
// changes.
// TODO(dfc) write to temporary file and move atomically to avoid
// destroying a working vendorfile.
func WriteManifest(path string, m *Manifest) error {
	if len(m.Dependencies) == 0 {
		err := os.Remove(path)
		if !os.IsNotExist(err) {
			return err
		}
		return nil
	}

	f, err := os.Create(path)
	if err != nil {
		return err
	}
	if err := writeManifest(f, m); err != nil {
		f.Close()
		return err
	}
	return f.Close()
}

func writeManifest(w io.Writer, m *Manifest) error {
	sort.Sort(byImportpath(m.Dependencies))
	buf, err := json.MarshalIndent(m, "", "\t")
	if err != nil {
		return err
	}
	_, err = io.Copy(w, bytes.NewReader(buf))
	return err
}

// ReadManifest reads a Manifest from path. If the Manifest is not
// found, a blank Manifest will be returned.
func ReadManifest(path string) (*Manifest, error) {
	f, err := os.Open(path)
	if err != nil {
		if os.IsNotExist(err) {
			return new(Manifest), nil
		}
		return nil, err
	}
	defer f.Close()

	var m Manifest
	d := json.NewDecoder(f)
	if err := d.Decode(&m); err != nil {
		return nil, err
	}

	// Pass all dependencies through AddDependency to detect overlap
	deps := m.Dependencies
	m.Dependencies = nil
	sort.Sort(byImportpath(deps)) // so that subpackages come after parents
	for _, d := range deps {
		if err := m.AddDependency(d); err == DepPresent {
			log.Println("WARNING: overlapping dependency detected:", d.Importpath)
			log.Println("The subpackage will be ignored to fix undefined behavior. See https://git.io/vr8Mu")
		} else if err != nil {
			return nil, err
		}
	}

	return &m, err
}

type byImportpath []Dependency

func (s byImportpath) Len() int           { return len(s) }
func (s byImportpath) Less(i, j int) bool { return s[i].Importpath < s[j].Importpath }
func (s byImportpath) Swap(i, j int)      { s[i], s[j] = s[j], s[i] }
