package cmd

import (
	"container/list"
	"fmt"
	"os"
	"path/filepath"
	"sort"
	"strings"

	"github.com/Masterminds/cookoo"
)

// Tree prints a tree representing dependencies.
func Tree(c cookoo.Context, p *cookoo.Params) (interface{}, cookoo.Interrupt) {
	buildContext, err := GetBuildContext()
	if err != nil {
		return nil, err
	}
	showcore := p.Get("showcore", false).(bool)
	basedir := p.Get("dir", ".").(string)
	myName := guessPackageName(buildContext, basedir)

	if basedir == "." {
		var err error
		basedir, err = os.Getwd()
		if err != nil {
			Error("Could not get working directory")
			return nil, err
		}
	}

	fmt.Println(myName)
	l := list.New()
	l.PushBack(myName)
	displayTree(buildContext, basedir, myName, 1, showcore, l)
	return nil, nil
}

// ListDeps lists all of the dependencies of the current project.
//
// Params:
//
// Returns:
//
func ListDeps(c cookoo.Context, p *cookoo.Params) (interface{}, cookoo.Interrupt) {
	buildContext, err := GetBuildContext()
	if err != nil {
		return nil, err
	}
	basedir := p.Get("dir", ".").(string)
	myName := guessPackageName(buildContext, basedir)

	basedir, err = filepath.Abs(basedir)
	if err != nil {
		return nil, err
	}

	direct := map[string]*pinfo{}
	d := walkDeps(buildContext, basedir, myName)
	for _, i := range d {
		listDeps(buildContext, direct, i, basedir)
	}

	sortable := make([]string, len(direct))
	i := 0
	for k := range direct {
		sortable[i] = k
		i++
	}

	sort.Strings(sortable)

	for _, k := range sortable {
		t := direct[k].PType
		fmt.Printf("%s (Location: %s)\n", k, ptypeString(t))
	}

	return nil, nil
}

func listDeps(b *BuildCtxt, info map[string]*pinfo, name, path string) {
	found := findPkg(b, name, path)
	switch found.PType {
	case ptypeUnknown:
		info[name] = found
		break
	case ptypeGoroot, ptypeCgo:
		break
	default:
		info[name] = found
		for _, i := range walkDeps(b, found.Path, found.Name) {
			// Only walk the deps that are not already found to avoid
			// infinite recursion.
			if _, f := info[found.Name]; f == false {
				listDeps(b, info, i, found.Path)
			}
		}
	}
}

func displayTree(b *BuildCtxt, basedir, myName string, level int, core bool, l *list.List) {
	deps := walkDeps(b, basedir, myName)
	for _, name := range deps {
		found := findPkg(b, name, basedir)
		if found.PType == ptypeUnknown {
			msg := "glide get " + found.Name
			fmt.Printf("\t%s\t(%s)\n", found.Name, msg)
			continue
		}
		if !core && found.PType == ptypeGoroot || found.PType == ptypeCgo {
			continue
		}
		fmt.Print(strings.Repeat("\t", level))

		f := findInList(found.Name, l)
		if f == true {
			fmt.Printf("(Recursion) %s   (%s)\n", found.Name, found.Path)
		} else {
			// Every branch in the tree is a copy to handle all the branches
			cl := copyList(l)
			cl.PushBack(found.Name)
			fmt.Printf("%s   (%s)\n", found.Name, found.Path)
			displayTree(b, found.Path, found.Name, level+1, core, cl)
		}
	}
}

type ptype int8

const (
	ptypeUnknown ptype = iota
	ptypeLocal
	ptypeVendor
	ptypeGopath
	ptypeGoroot
	ptypeCgo
)

func ptypeString(t ptype) string {
	switch t {
	case ptypeLocal:
		return "local"
	case ptypeVendor:
		return "vendored"
	case ptypeGopath:
		return "gopath"
	case ptypeGoroot:
		return "core"
	case ptypeCgo:
		return "cgo"
	default:
		return "missing"
	}
}

type pinfo struct {
	Name, Path string
	PType      ptype
	Vendored   bool
}

func findPkg(b *BuildCtxt, name, cwd string) *pinfo {
	var fi os.FileInfo
	var err error
	var p string

	info := &pinfo{
		Name: name,
	}

	// Recurse backward to scan other vendor/ directories
	// If the cwd isn't an absolute path walking upwards looking for vendor/
	// folders can get into an infinate loop.
	abs, err := filepath.Abs(cwd)
	if err != nil {
		abs = cwd
	}
	if abs != "." {
		for wd := abs; wd != "/"; wd = filepath.Dir(wd) {
			p = filepath.Join(wd, "vendor", name)
			if fi, err = os.Stat(p); err == nil && (fi.IsDir() || isLink(fi)) {
				info.Path = p
				info.PType = ptypeVendor
				info.Vendored = true
				return info
			}
		}
	}
	// Check $GOPATH
	for _, r := range strings.Split(b.GOPATH, ":") {
		p = filepath.Join(r, "src", name)
		if fi, err = os.Stat(p); err == nil && (fi.IsDir() || isLink(fi)) {
			info.Path = p
			info.PType = ptypeGopath
			return info
		}
	}

	// Check $GOROOT
	for _, r := range strings.Split(b.GOROOT, ":") {
		p = filepath.Join(r, "src", name)
		if fi, err = os.Stat(p); err == nil && (fi.IsDir() || isLink(fi)) {
			info.Path = p
			info.PType = ptypeGoroot
			return info
		}
	}

	// Finally, if this is "C", we're dealing with cgo
	if name == "C" {
		info.PType = ptypeCgo
	}

	return info
}

func isLink(fi os.FileInfo) bool {
	return fi.Mode()&os.ModeSymlink == os.ModeSymlink
}

func walkDeps(b *BuildCtxt, base, myName string) []string {
	externalDeps := []string{}
	filepath.Walk(base, func(path string, fi os.FileInfo, err error) error {
		if excludeSubtree(path, fi) {
			if fi.IsDir() {
				return filepath.SkipDir
			}
			return nil
		}

		pkg, err := b.ImportDir(path, 0)
		if err != nil {
			return err
		}

		if pkg.Goroot {
			return nil
		}

		for _, imp := range pkg.Imports {
			//if strings.HasPrefix(imp, myName) {
			////Info("Skipping %s because it is a subpackage of %s", imp, myName)
			//continue
			//}
			if imp == myName {
				continue
			}
			externalDeps = append(externalDeps, imp)
		}

		return nil
	})
	return externalDeps
}

func excludeSubtree(path string, fi os.FileInfo) bool {
	top := filepath.Base(path)

	if !fi.IsDir() && !isLink(fi) {
		return true
	}

	// Provisionally, we'll skip vendor. We definitely
	// should skip testdata.
	if top == "vendor" || top == "testdata" {
		return true
	}

	// Skip anything that starts with _
	if strings.HasPrefix(top, "_") || (strings.HasPrefix(top, ".") && top != ".") {
		return true
	}
	return false
}

func copyList(l *list.List) *list.List {
	n := list.New()
	for e := l.Front(); e != nil; e = e.Next() {
		n.PushBack(e.Value.(string))
	}
	return n
}

func findInList(n string, l *list.List) bool {
	for e := l.Front(); e != nil; e = e.Next() {
		if e.Value.(string) == n {
			return true
		}
	}

	return false
}
