package gom

import (
	"errors"
	"os"
	"path/filepath"

	"github.com/Masterminds/glide/cfg"
	"github.com/Masterminds/glide/msg"
	gpath "github.com/Masterminds/glide/path"
	"github.com/Masterminds/glide/util"
	"github.com/sdboyer/gps"
)

// Has returns true if this dir has a Gomfile.
func Has(dir string) bool {
	path := filepath.Join(dir, "Gomfile")
	fi, err := os.Stat(path)
	return err == nil && !fi.IsDir()
}

// Parse parses a Gomfile.
func Parse(dir string) ([]*cfg.Dependency, error) {
	path := filepath.Join(dir, "Gomfile")
	if fi, err := os.Stat(path); err != nil || fi.IsDir() {
		return []*cfg.Dependency{}, nil
	}

	msg.Info("Found Gomfile in %s", gpath.StripBasepath(dir))
	msg.Info("--> Parsing Gomfile metadata...")
	buf := []*cfg.Dependency{}

	goms, err := parseGomfile(path)
	if err != nil {
		return []*cfg.Dependency{}, err
	}

	for _, gom := range goms {
		// Do we need to skip this dependency?
		if val, ok := gom.options["skipdep"]; ok && val.(string) == "true" {
			continue
		}

		// Check for custom cloning command
		if _, ok := gom.options["command"]; ok {
			return []*cfg.Dependency{}, errors.New("Glide does not support custom Gomfile commands")
		}

		// Check for groups/environments
		if val, ok := gom.options["group"]; ok {
			groups := toStringSlice(val)
			if !stringsContain(groups, "development") && !stringsContain(groups, "production") {
				// right now we only support development and production
				msg.Info("Skipping dependency '%s' because it isn't in the development or production group", gom.name)
				continue
			}
		}

		pkg, _ := util.NormalizeName(gom.name)

		dep := &cfg.Dependency{
			Name: pkg,
		}

		// Check for a specific revision
		if val, ok := gom.options["commit"]; ok {
			dep.Version = val.(string)
		}
		if val, ok := gom.options["tag"]; ok {
			dep.Version = val.(string)
		}
		if val, ok := gom.options["branch"]; ok {
			dep.Branch = val.(string)
		}

		buf = append(buf, dep)
	}

	return buf, nil
}

// AsMetadataPair attempts to extract manifest and lock data from gom metadata.
func AsMetadataPair(dir string) (gps.Manifest, gps.Lock, error) {
	path := filepath.Join(dir, "Gomfile")
	if _, err := os.Stat(path); err != nil {
		return nil, nil, err
	}

	goms, err := parseGomfile(path)
	if err != nil {
		return nil, nil, err
	}

	var l gps.SimpleLock
	m := gps.SimpleManifest{}

	for _, gom := range goms {
		// Do we need to skip this dependency?
		if val, ok := gom.options["skipdep"]; ok && val.(string) == "true" {
			continue
		}

		// Check for custom cloning command
		if _, ok := gom.options["command"]; ok {
			return nil, nil, errors.New("Glide does not support custom Gomfile commands")
		}

		// Check for groups/environments
		if val, ok := gom.options["group"]; ok {
			groups := toStringSlice(val)
			if !stringsContain(groups, "development") && !stringsContain(groups, "production") {
				// right now we only support development and production
				continue
			}
		}

		pkg, _ := util.NormalizeName(gom.name)

		dep := gps.ProjectConstraint{
			Ident: gps.ProjectIdentifier{
				ProjectRoot: gps.ProjectRoot(pkg),
			},
		}

		// Our order of preference for things to put in the manifest are
		//   - Semver
		//   - Version
		//   - Branch
		//   - Revision

		var v gps.UnpairedVersion
		if val, ok := gom.options["tag"]; ok {
			body := val.(string)
			v = gps.NewVersion(body)
			c, err := gps.NewSemverConstraint(body)
			if err != nil {
				c = gps.NewVersion(body)
			}
			dep.Constraint = c
		} else if val, ok := gom.options["branch"]; ok {
			body := val.(string)
			v = gps.NewBranch(body)
			dep.Constraint = gps.NewBranch(body)
		}

		if val, ok := gom.options["commit"]; ok {
			body := val.(string)
			if v != nil {
				v.Is(gps.Revision(body))
				l = append(l, gps.NewLockedProject(gps.ProjectRoot(dir), v, dir, nil))
			} else {
				// As with the other third-party system integrations, we're
				// going to choose not to put revisions into a manifest, even
				// though gom has a lot more information than most and the
				// argument could be made for it.
				dep.Constraint = gps.Any()
				l = append(l, gps.NewLockedProject(gps.ProjectRoot(dir), gps.Revision(body), dir, nil))
			}
		} else if v != nil {
			// This is kinda uncomfortable - lock w/no immut - but OK
			l = append(l, gps.NewLockedProject(gps.ProjectRoot(dir), v, dir, nil))
		}

		// TODO We ignore GOOS, GOARCH for now
	}

	return m, l, nil
}

func stringsContain(v []string, key string) bool {
	for _, s := range v {
		if s == key {
			return true
		}
	}
	return false
}

func toStringSlice(v interface{}) []string {
	if v, ok := v.(string); ok {
		return []string{v}
	}

	if v, ok := v.([]string); ok {
		return v
	}

	return []string{}
}
