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.Constraint = gps.Revision(val.(string))
		}
		if val, ok := gom.options["tag"]; ok {
			dep.Constraint = gps.NewVersion(val.(string))
		}
		if val, ok := gom.options["branch"]; ok {
			dep.Constraint = gps.NewBranch(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{}
}
