package cmd

import (
	"bytes"
	"fmt"
	"io"
	"os"
	"reflect"
	"strings"

	"github.com/Masterminds/cookoo"
	v "github.com/Masterminds/vcs"
	"github.com/kylelemons/go-gypsy/yaml"
)

// ParseYaml parses the glide.yaml format and returns a Configuration object.
//
// Params:
//	- filename (string): YAML filename as a string
//
// Context:
//	- yaml.File: This puts the parsed YAML file into the context.
//
// Returns:
//	- *Config: The configuration.
func ParseYaml(c cookoo.Context, p *cookoo.Params) (interface{}, cookoo.Interrupt) {
	fname := p.Get("filename", "glide.yaml").(string)
	//conf := new(Config)
	f, err := yaml.ReadFile(fname)
	if err != nil {
		return nil, err
	}

	c.Put("yaml.File", f)
	return FromYaml(f.Root)
}

// ParseYamlString parses a YAML string. This is similar but different to
// ParseYaml that parses an external file.
//
// Params:
//	- yaml (string): YAML as a string.
//
// Returns:
//	- *Config: The configuration.
func ParseYamlString(c cookoo.Context, p *cookoo.Params) (interface{}, cookoo.Interrupt) {
	yamlString := p.Get("yaml", "").(string)

	// Unfortunately, this does not wrap the root in a YAML file object.
	root, err := yaml.Parse(bytes.NewBufferString(yamlString))
	if err != nil {
		return nil, err
	}

	return FromYaml(root)
}

// WriteYaml writes a yaml.Node to the console as a string.
//
// Params:
//	- yaml.Node (yaml.Node): A yaml.Node to render.
// 	- out (io.Writer): An output stream to write to. Default is os.Stdout.
// 	- filename (string): If set, the file will be opened and the content will be written to it.
func WriteYaml(c cookoo.Context, p *cookoo.Params) (interface{}, cookoo.Interrupt) {
	top := p.Get("yaml.Node", yaml.Scalar("nothing to print")).(yaml.Node)
	toStdout := p.Get("toStdout", true).(bool)
	var out io.Writer
	if nn, ok := p.Has("filename"); ok && len(nn.(string)) > 0 {
		file, err := os.Create(nn.(string))
		if err != nil {
		}
		defer file.Close()
		out = io.Writer(file)
		fmt.Fprint(out, yaml.Render(top))
	} else if toStdout {
		out = p.Get("out", os.Stdout).(io.Writer)
		fmt.Fprint(out, yaml.Render(top))
	}
	// Otherwise we supress output.

	return true, nil
}

// MergeToYaml converts a Config object and a yaml.File to a single yaml.File.
//
// Params:
//	- conf (*Config): The configuration to merge.
//	- overwriteImports (bool, default true): If this is true, old config will
//		overwritten. If false, we attempt to merge the old and new config, with
//		preference to the old.
//
// Returns:
//	- The root yaml.Node of the modified config.
//
// Uses:
//	- cxt.Get("yaml.File") as the source for the YAML file.
func MergeToYaml(c cookoo.Context, p *cookoo.Params) (interface{}, cookoo.Interrupt) {
	root := c.Get("yaml.File", nil).(*yaml.File).Root
	cfg := p.Get("conf", nil).(*Config)
	overwrite := p.Get("overwriteImports", true).(bool)

	rootMap, ok := root.(yaml.Map)
	if !ok {
		return nil, fmt.Errorf("Expected root node to be a map.")
	}

	if len(cfg.Name) > 0 {
		rootMap["package"] = yaml.Scalar(cfg.Name)
	}

	if overwrite {
		// Imports
		imports := make([]yaml.Node, len(cfg.Imports))
		for i, imp := range cfg.Imports {
			imports[i] = imp.ToYaml()
		}
		rootMap["import"] = yaml.List(imports)
	} else {
		var err error
		rootMap, err = mergeImports(rootMap, cfg)
		if err != nil {
			Warn("Problem merging imports: %s\n", err)
		}
	}

	return root, nil
}

// mergeImports merges the imports on a *Config into an existing YAML doc.
func mergeImports(root yaml.Map, cfg *Config) (yaml.Map, error) {
	left, err := FromYaml(root)
	if err != nil {
		return root, err
	}

	leftnames := make(map[string]bool, len(left.Imports))
	for _, i := range left.Imports {
		leftnames[i.Name] = true
	}

	for _, right := range cfg.Imports {
		if _, ok := leftnames[right.Name]; !ok {
			left.Imports = append(left.Imports, right)
		}
	}

	return left.ToYaml().(yaml.Map), nil
}

// AddDependencies adds a list of *Dependency objects to the given *Config.
//
// This is used to merge in packages from other sources or config files.
func AddDependencies(c cookoo.Context, p *cookoo.Params) (interface{}, cookoo.Interrupt) {
	deps := p.Get("dependencies", []*Dependency{}).([]*Dependency)
	config := p.Get("conf", nil).(*Config)

	// Make a set of existing package names for quick comparison.
	pkgSet := make(map[string]bool, len(config.Imports))
	for _, p := range config.Imports {
		pkgSet[p.Name] = true
	}

	// If a dep is not already present, add it.
	for _, dep := range deps {
		if _, ok := pkgSet[dep.Name]; ok {
			Warn("Package %s is already in glide.yaml. Skipping.\n", dep.Name)
			continue
		}
		config.Imports = append(config.Imports, dep)
	}

	return true, nil
}

func valOrEmpty(key string, store map[string]yaml.Node) string {
	val, ok := store[key]
	if !ok {
		return ""
	}
	return strings.TrimSpace(val.(yaml.Scalar).String())
}

// boolOrDefault returns a bool, with the dft returned if there is an error or the value is not true/false
func boolOrDefault(key string, store map[string]yaml.Node, dft bool) bool {
	val, ok := store[key]
	if !ok {
		return dft
	}
	switch val.(yaml.Scalar).String() {
	case "true":
		return true
	case "false":
		return false
	default:
		return dft
	}
}

// valOrList gets a single value or a list of values.
//
// Supports syntaxes like:
//
// 	subpkg: foo
//
// and
//
// 	supkpg:
// 		-foo
// 		-bar
func valOrList(key string, store map[string]yaml.Node) []string {
	val, ok := store[key]

	subpackages := []string{}
	if !ok {
		return subpackages
	}

	pkgs, ok := val.(yaml.List)

	if !ok {

		// Special case: Allow 'subpackages: justOne'
		if one, ok := val.(yaml.Scalar); ok {
			return []string{one.String()}
		}

		Warn("Expected list of subpackages.\n")
		return subpackages
	}

	for _, pkg := range pkgs {
		subpackages = append(subpackages, pkg.(yaml.Scalar).String())
	}
	return subpackages
}

func getVcsType(store map[string]yaml.Node) string {
	val, ok := store["vcs"]
	if !ok {
		return string(v.NoVCS)
	}

	name := val.(yaml.Scalar).String()

	switch name {
	case "git", "hg", "bzr", "svn":
		return name
	case "mercurial":
		return "hg"
	case "bazaar":
		return "bzr"
	case "subversion":
		return "svn"
	default:
		return ""
	}
}

// NormalizeName takes a package name and normalizes it to the top level package.
//
// For example, golang.org/x/crypto/ssh becomes golang.org/x/crypto. 'ssh' is
// returned as extra data.
func NormalizeName(name string) (string, string) {
	parts := strings.SplitN(name, "/", 4)
	extra := ""
	if len(parts) < 3 {
		return name, extra
	}
	if len(parts) == 4 {
		extra = parts[3]
	}
	return strings.Join(parts[0:3], "/"), extra
}

// Config is the top-level configuration object.
type Config struct {
	Parent     *Config
	Name       string
	Imports    Dependencies
	DevImports Dependencies
}

// HasDependency returns true if the given name is listed as an import or dev import.
func (c *Config) HasDependency(name string) bool {
	for _, d := range c.Imports {
		if d.Name == name {
			return true
		}
	}
	for _, d := range c.DevImports {
		if d.Name == name {
			return true
		}
	}
	return false
}

// HasRecursiveDependency returns true if this config or one of it's parents has this dependency
func (c *Config) HasRecursiveDependency(name string) bool {
	if c.HasDependency(name) == true {
		return true
	} else if c.Parent != nil {
		return c.Parent.HasRecursiveDependency(name)
	}
	return false
}

// GetRoot follows the Parent down to the top node
func (c *Config) GetRoot() *Config {
	if c.Parent != nil {
		return c.Parent.GetRoot()
	}
	return c
}

// FromYaml creates a *Config from a  YAML node.
func FromYaml(top yaml.Node) (*Config, error) {
	conf := new(Config)

	vals, ok := top.(yaml.Map)
	if !ok {
		return conf, fmt.Errorf("Top YAML node must be a map.")
	}

	if name, ok := vals["package"]; ok {
		conf.Name = name.(yaml.Scalar).String()
	} else {
		Warn("The 'package' directive is required in Glide YAML.\n")
		conf.Name = "main"
	}

	conf.Imports = make(Dependencies, 0, 1)
	if imp, ok := vals["import"]; ok {
		imports, ok := imp.(yaml.List)

		if ok {
			for _, v := range imports {
				dep, err := DependencyFromYaml(v)
				if err != nil {
					Warn("Could not add a dependency: %s\n", err)
				}
				conf.Imports = append(conf.Imports, dep)
			}
		}
	}

	i, err := conf.Imports.DeDupe()
	if err != nil {
		return conf, err
	}
	conf.Imports = i

	// Same for (experimental) devimport.
	// These are currently unused. Not sure what we'll do with it yet.
	conf.DevImports = make(Dependencies, 0, 0)
	if imp, ok := vals["devimport"]; ok {
		imports, ok := imp.(yaml.List)
		if ok {
			for _, v := range imports {
				dep, err := DependencyFromYaml(v)
				if err != nil {
					Warn("Could not add a dependency: %s\n", err)
				}
				conf.DevImports = append(conf.DevImports, dep)
			}
		}
	}

	conf.DevImports, err = conf.DevImports.DeDupe()
	if err != nil {
		return conf, err
	}

	return conf, nil
}

// ToYaml returns a yaml.Map containing the data from Config.
func (c *Config) ToYaml() yaml.Node {
	cfg := make(map[string]yaml.Node, 5)

	cfg["package"] = yaml.Scalar(c.Name)

	imps := make([]yaml.Node, len(c.Imports))
	for i, imp := range c.Imports {
		imps[i] = imp.ToYaml()
	}
	devimps := make([]yaml.Node, len(c.DevImports))
	for i, dimp := range c.DevImports {
		devimps[i] = dimp.ToYaml()
	}

	// Fixed in 0.5.0. Prior to that, these were not being printed. Worried
	// that the "fix" might introduce an unintended side effect.
	if len(imps) > 0 {
		cfg["import"] = yaml.List(imps)
	}
	if len(devimps) > 0 {
		cfg["devimport"] = yaml.List(devimps)
	}

	return yaml.Map(cfg)
}

// Dependency describes a package that the present package depends upon.
type Dependency struct {
	Name, Reference, Pin, Repository string
	VcsType                          string
	Subpackages, Arch, Os            []string
	UpdateAsVendored                 bool
}

// DependencyFromYaml creates a dependency from a yaml.Node.
func DependencyFromYaml(node yaml.Node) (*Dependency, error) {
	pkg, ok := node.(yaml.Map)
	if !ok {
		return &Dependency{}, fmt.Errorf("Expected yaml.Node to be a dependency map.")
	}
	dep := &Dependency{
		Name:        valOrEmpty("package", pkg),
		Reference:   valOrEmpty("version", pkg),
		Pin:         valOrEmpty("pin", pkg),
		VcsType:     getVcsType(pkg),
		Repository:  valOrEmpty("repo", pkg),
		Subpackages: valOrList("subpackages", pkg),
		Arch:        valOrList("arch", pkg),
		Os:          valOrList("os", pkg),
	}

	// Continue to support the legacy ref property for the version. To remove
	// support remove the following block.
	if dep.Reference == "" {
		dep.Reference = valOrEmpty("ref", pkg)
	}

	if dep.Name != "" {
		orig := dep.Name
		dep.Name = getRepoRootFromPackage(orig)

		// The package name listed was actually a sub-package. Modify the
		// config to reflect reality.
		if orig != dep.Name {
			subpkg := strings.TrimPrefix(orig, dep.Name)
			if len(subpkg) > 0 && subpkg != "/" {
				dep.Subpackages = append(dep.Subpackages, strings.TrimPrefix(subpkg, "/"))
			}
		}
	}

	return dep, nil
}

// GetRepo retrieves a Masterminds/vcs repo object configured for the root
// of the package being retrieved.
func (d *Dependency) GetRepo(dest string) (v.Repo, error) {

	// The remote location is either the configured repo or the package
	// name as an https url.
	var remote string
	if len(d.Repository) > 0 {
		remote = d.Repository
	} else {
		remote = "https://" + d.Name
	}

	// If the VCS type has a value we try that first.
	if len(d.VcsType) > 0 && d.VcsType != "None" {
		switch v.Type(d.VcsType) {
		case v.Git:
			return v.NewGitRepo(remote, dest)
		case v.Svn:
			return v.NewSvnRepo(remote, dest)
		case v.Hg:
			return v.NewHgRepo(remote, dest)
		case v.Bzr:
			return v.NewBzrRepo(remote, dest)
		default:
			return nil, fmt.Errorf("Unknown VCS type %s set for %s", d.VcsType, d.Name)
		}
	}

	// When no type set we try to autodetect.
	return v.NewRepo(remote, dest)
}

func stripScheme(u string) string {
	parts := strings.Split(u, "://")
	if len(parts) > 1 {
		return parts[1]
	}
	return u
}

// ToYaml converts a *Dependency to a YAML Map node.
func (d *Dependency) ToYaml() yaml.Node {
	dep := make(map[string]yaml.Node, 8)
	dep["package"] = yaml.Scalar(d.Name)

	if len(d.Subpackages) > 0 {
		subp := make([]yaml.Node, len(d.Subpackages))
		for i, item := range d.Subpackages {
			subp[i] = yaml.Scalar(item)
		}

		dep["subpackages"] = yaml.List(subp)
	}
	vcs := d.VcsType
	if len(vcs) > 0 {
		dep["vcs"] = yaml.Scalar(vcs)
	}
	if len(d.Reference) > 0 {
		dep["version"] = yaml.Scalar(d.Reference)
	}
	if len(d.Pin) > 0 {
		dep["pin"] = yaml.Scalar(d.Pin)
	}
	if len(d.Repository) > 0 {
		dep["repo"] = yaml.Scalar(d.Repository)
	}

	if len(d.Arch) > 0 {
		archs := make([]yaml.Node, len(d.Arch))
		for i, a := range d.Arch {
			archs[i] = yaml.Scalar(a)
		}
		dep["arch"] = yaml.List(archs)
	}
	if len(d.Os) > 0 {
		oses := make([]yaml.Node, len(d.Os))
		for i, a := range d.Os {
			oses[i] = yaml.Scalar(a)
		}
		dep["os"] = yaml.List(oses)
	}

	return yaml.Map(dep)
}

// Dependencies is a collection of Dependency
type Dependencies []*Dependency

// Get a dependency by name
func (d Dependencies) Get(name string) *Dependency {
	for _, dep := range d {
		if dep.Name == name {
			return dep
		}
	}
	return nil
}

// DeDupe cleans up duplicates on a list of dependencies.
func (d Dependencies) DeDupe() (Dependencies, error) {
	checked := map[string]*Dependency{}
	for _, dep := range d {
		// The first time we encounter a dependency add it to the list
		if val, ok := checked[dep.Name]; !ok {
			checked[dep.Name] = dep
		} else {
			// In here we've encountered a dependency for the second time.
			// Make sure the details are the same or return an error.
			if dep.Reference != val.Reference {
				return d, fmt.Errorf("Import %s repeated with different versions '%s' and '%s'", dep.Name, dep.Reference, val.Reference)
			}
			if dep.Repository != val.Repository || dep.VcsType != val.VcsType {
				return d, fmt.Errorf("Import %s repeated with different Repository details", dep.Name)
			}
			if !reflect.DeepEqual(dep.Os, val.Os) || !reflect.DeepEqual(dep.Arch, val.Arch) {
				return d, fmt.Errorf("Import %s repeated with different OS or Architecture filtering", dep.Name)
			}
			checked[dep.Name].Subpackages = stringArrayDeDupe(checked[dep.Name].Subpackages, dep.Subpackages...)
		}
	}

	imports := make(Dependencies, 0, 1)
	for _, dep := range checked {
		imports = append(imports, dep)
	}

	return imports, nil
}

func stringArrayDeDupe(s []string, items ...string) []string {
	for _, item := range items {
		exists := false
		for _, v := range s {
			if v == item {
				exists = true
			}
		}
		if !exists {
			s = append(s, item)
		}
	}
	return s
}
