package dependency

import (
	"bytes"
	"io"
	"os"
	"path/filepath"
	"strings"
	"text/scanner"

	"github.com/Masterminds/glide/msg"
	"github.com/Masterminds/glide/util"
)

var osList []string
var archList []string

func init() {
	// The supported systems are listed in
	// https://github.com/golang/go/blob/master/src/go/build/syslist.go
	// The lists are not exported so we need to duplicate them here.
	osListString := "android darwin dragonfly freebsd linux nacl netbsd openbsd plan9 solaris windows"
	osList = strings.Split(osListString, " ")

	archListString := "386 amd64 amd64p32 arm armbe arm64 arm64be ppc64 ppc64le mips mipsle mips64 mips64le mips64p32 mips64p32le ppc s390 s390x sparc sparc64"
	archList = strings.Split(archListString, " ")
}

// IterativeScan attempts to obtain a list of imported dependencies from a
// package. This scanning is different from ImportDir as part of the go/build
// package. It looks over different permutations of the supported OS/Arch to
// try and find all imports. This is different from setting UseAllFiles to
// true on the build Context. It scopes down to just the supported OS/Arch.
//
// Note, there are cases where multiple packages are in the same directory. This
// usually happens with an example that has a main package and a +build tag
// of ignore. This is a bit of a hack. It causes UseAllFiles to have errors.
func IterativeScan(path string) ([]string, error) {

	// TODO(mattfarina): Add support for release tags.

	tgs, _ := readBuildTags(path)
	// Handle the case of scanning with no tags
	tgs = append(tgs, "")

	var pkgs []string
	for _, tt := range tgs {

		// split the tag combination to look at permutations.
		ts := strings.Split(tt, ",")
		var ttgs []string
		var arch string
		var ops string
		for _, ttt := range ts {
			dirty := false
			if strings.HasPrefix(ttt, "!") {
				dirty = true
				ttt = strings.TrimPrefix(ttt, "!")
			}
			if isSupportedOs(ttt) {
				if dirty {
					ops = getOsValue(ttt)
				} else {
					ops = ttt
				}
			} else if isSupportedArch(ttt) {
				if dirty {
					arch = getArchValue(ttt)
				} else {
					arch = ttt
				}
			} else {
				if !dirty {
					ttgs = append(ttgs, ttt)
				}
			}
		}

		// Handle the case where there are no tags but we need to iterate
		// on something.
		if len(ttgs) == 0 {
			ttgs = append(ttgs, "")
		}

		b, err := util.GetBuildContext()
		if err != nil {
			return []string{}, err
		}

		// Make sure use all files is off
		b.UseAllFiles = false

		// Set the OS and Arch for this pass
		b.GOARCH = arch
		b.GOOS = ops
		b.BuildTags = ttgs
		msg.Debug("Scanning with Arch(%s), OS(%s), and Build Tags(%v)", arch, ops, ttgs)

		pk, err := b.ImportDir(path, 0)

		// If there are no buildable souce with this permutation we skip it.
		if err != nil && strings.HasPrefix(err.Error(), "no buildable Go source files in") {
			continue
		} else if err != nil && strings.HasPrefix(err.Error(), "found packages archive ") {
			// A permutation may cause multiple packages to appear. For example,
			// an example file with an ignore build tag. If this happens we
			// ignore it.
			// TODO(mattfarina): Find a better way.
			msg.Debug("Found multiple packages while scanning %s: %s", path, err)
			continue
		} else if err != nil {
			msg.Debug("Problem parsing package at %s for %s %s", path, ops, arch)
			return []string{}, err
		}

		for _, dep := range pk.Imports {
			found := false
			for _, p := range pkgs {
				if p == dep {
					found = true
				}
			}
			if !found {
				pkgs = append(pkgs, dep)
			}
		}
	}

	return pkgs, nil
}

func readBuildTags(p string) ([]string, error) {
	_, err := os.Stat(p)
	if err != nil {
		return []string{}, err
	}

	d, err := os.Open(p)
	if err != nil {
		return []string{}, err
	}

	objects, err := d.Readdir(-1)
	if err != nil {
		return []string{}, err
	}

	var tags []string
	for _, obj := range objects {

		// only process Go files
		if strings.HasSuffix(obj.Name(), ".go") {
			fp := filepath.Join(p, obj.Name())

			co, err := readGoContents(fp)
			if err != nil {
				return []string{}, err
			}

			// Only look at places where we had a code comment.
			if len(co) > 0 {
				t := findTags(co)
				for _, tg := range t {
					found := false
					for _, tt := range tags {
						if tt == tg {
							found = true
						}
					}
					if !found {
						tags = append(tags, tg)
					}
				}
			}
		}
	}

	return tags, nil
}

// Read contents of a Go file up to the package declaration. This can be used
// to find the the build tags.
func readGoContents(fp string) ([]byte, error) {
	f, err := os.Open(fp)
	defer f.Close()
	if err != nil {
		return []byte{}, err
	}

	var s scanner.Scanner
	s.Init(f)
	var tok rune
	var pos scanner.Position
	for tok != scanner.EOF {
		tok = s.Scan()

		// Getting the token text will skip comments by default.
		tt := s.TokenText()
		// build tags will not be after the package declaration.
		if tt == "package" {
			pos = s.Position
			break
		}
	}

	buf := bytes.NewBufferString("")
	f.Seek(0, 0)
	_, err = io.CopyN(buf, f, int64(pos.Offset))
	if err != nil {
		return []byte{}, err
	}

	return buf.Bytes(), nil
}

// From a byte slice of a Go file find the tags.
func findTags(co []byte) []string {
	p := co
	var tgs []string
	for len(p) > 0 {
		line := p
		if i := bytes.IndexByte(line, '\n'); i >= 0 {
			line, p = line[:i], p[i+1:]
		} else {
			p = p[len(p):]
		}
		line = bytes.TrimSpace(line)
		// Only look at comment lines that are well formed in the Go style
		if bytes.HasPrefix(line, []byte("//")) {
			line = bytes.TrimSpace(line[len([]byte("//")):])
			if len(line) > 0 && line[0] == '+' {
				f := strings.Fields(string(line))

				// We've found a +build tag line.
				if f[0] == "+build" {
					for _, tg := range f[1:] {
						tgs = append(tgs, tg)
					}
				}
			}
		}
	}

	return tgs
}

// Get an OS value that's not the one passed in.
func getOsValue(n string) string {
	for _, o := range osList {
		if o != n {
			return o
		}
	}

	return n
}

func isSupportedOs(n string) bool {
	for _, o := range osList {
		if o == n {
			return true
		}
	}

	return false
}

// Get an Arch value that's not the one passed in.
func getArchValue(n string) string {
	for _, o := range archList {
		if o != n {
			return o
		}
	}

	return n
}

func isSupportedArch(n string) bool {
	for _, o := range archList {
		if o == n {
			return true
		}
	}

	return false
}
