// Package yaml provides the ability to work with glide.yaml files.
package yaml

import (
	"fmt"
	"reflect"
	"strings"

	"github.com/Masterminds/glide/util"
	"github.com/Masterminds/vcs"
	"gopkg.in/yaml.v2"
)

// FromYaml takes a yaml string and converts it to a Config instance.
func FromYaml(yml string) (*Config, error) {
	c := &Config{}
	err := yaml.Unmarshal([]byte(yml), &c)
	if err != nil {
		return nil, err
	}

	// The ref property is for the legacy yaml file structure.
	// This sets the currect version to the ref if a version isn't
	// already set.
	for _, v := range c.Imports {
		if v.Reference == "" && v.Ref != "" {
			v.Reference = v.Ref
		}
		v.Ref = ""

		// Make sure only legitimate VCS are listed.
		v.VcsType = filterVcsType(v.VcsType)

		// Get the root name for the package
		o := v.Name
		v.Name = util.GetRootFromPackage(v.Name)
		subpkg := strings.TrimPrefix(o, v.Name)
		if len(subpkg) > 0 && subpkg != o {
			v.Subpackages = append(v.Subpackages, strings.TrimPrefix(subpkg, "/"))
		}
	}
	for _, v := range c.DevImports {
		if v.Reference == "" && v.Ref != "" {
			v.Reference = v.Ref
		}
		v.Ref = ""

		v.VcsType = filterVcsType(v.VcsType)

		// Get the root name for the package
		o := v.Name
		v.Name = util.GetRootFromPackage(v.Name)
		subpkg := strings.TrimPrefix(o, v.Name)
		if len(subpkg) > 0 && subpkg != o {
			v.Subpackages = append(v.Subpackages, subpkg)
		}
	}
	return c, nil
}

// ToYaml takes a *Config instance and converts it into a yaml string.
func ToYaml(cfg *Config) (string, error) {
	yml, err := yaml.Marshal(&cfg)
	if err != nil {
		return "", err
	}
	return string(yml), nil
}

// Config is the top-level configuration object.
type Config struct {
	Parent     *Config
	Name       string       `yaml:"package"`
	Imports    Dependencies `yaml:"import"`
	DevImports Dependencies `yaml:"devimport,omitempty"`
}

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

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

// Dependency describes a package that the present package depends upon.
type Dependency struct {
	Name             string   `yaml:"package"`
	Reference        string   `yaml:"version,omitempty"`
	Ref              string   `yaml:"ref,omitempty"`
	Pin              string   `yaml:"pin,omitempty"`
	Repository       string   `yaml:"repo,omitempty"`
	VcsType          string   `yaml:"vcs,omitempty"`
	Subpackages      []string `yaml:"subpackages,omitempty"`
	Arch             []string `yaml:"arch,omitempty"`
	Os               []string `yaml:"os,omitempty"`
	UpdateAsVendored bool     `yaml:"-"`
}

// GetRepo retrieves a Masterminds/vcs repo object configured for the root
// of the package being retrieved.
func (d *Dependency) GetRepo(dest string) (vcs.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 vcs.Type(d.VcsType) {
		case vcs.Git:
			return vcs.NewGitRepo(remote, dest)
		case vcs.Svn:
			return vcs.NewSvnRepo(remote, dest)
		case vcs.Hg:
			return vcs.NewHgRepo(remote, dest)
		case vcs.Bzr:
			return vcs.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 vcs.NewRepo(remote, dest)
}

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

func filterVcsType(vcs string) string {
	switch vcs {
	case "git", "hg", "bzr", "svn":
		return vcs
	case "mercurial":
		return "hg"
	case "bazaar":
		return "bzr"
	case "subversion":
		return "svn"
	default:
		return ""
	}
}
