// Copyright 2018 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package cache

import (
	"context"
	"fmt"
	"go/ast"
	"go/parser"
	"go/scanner"
	"go/token"
	"go/types"
	"log"
	"sync"

	"golang.org/x/tools/go/packages"
	"golang.org/x/tools/internal/lsp/source"
)

type View struct {
	mu sync.Mutex // protects all mutable state of the view

	Config packages.Config

	files map[source.URI]*File

	analysisCache *source.AnalysisCache
}

// NewView creates a new View, given a root path and go/packages configuration.
// If config is nil, one is created with the directory set to the rootPath.
func NewView(config *packages.Config) *View {
	return &View{
		Config: *config,
		files:  make(map[source.URI]*File),
	}
}

func (v *View) FileSet() *token.FileSet {
	return v.Config.Fset
}

// SetContent sets the overlay contents for a file. A nil content value will
// remove the file from the active set and revert it to its on-disk contents.
func (v *View) SetContent(ctx context.Context, uri source.URI, content []byte) (source.View, error) {
	v.mu.Lock()
	defer v.mu.Unlock()

	f := v.getFile(uri)
	f.content = content

	// Resetting the contents invalidates the ast, token, and pkg fields.
	f.ast = nil
	f.token = nil
	f.pkg = nil

	// We might need to update the overlay.
	switch {
	case f.active && content == nil:
		// The file was active, so we need to forget its content.
		f.active = false
		if filename, err := f.URI.Filename(); err == nil {
			delete(f.view.Config.Overlay, filename)
		}
		f.content = nil
	case content != nil:
		// This is an active overlay, so we update the map.
		f.active = true
		if filename, err := f.URI.Filename(); err == nil {
			f.view.Config.Overlay[filename] = f.content
		}
	}

	// TODO(rstambler): We should really return a new, updated view.
	return v, nil
}

// GetFile returns a File for the given URI. It will always succeed because it
// adds the file to the managed set if needed.
func (v *View) GetFile(ctx context.Context, uri source.URI) (source.File, error) {
	v.mu.Lock()
	f := v.getFile(uri)
	v.mu.Unlock()
	return f, nil
}

// getFile is the unlocked internal implementation of GetFile.
func (v *View) getFile(uri source.URI) *File {
	f, found := v.files[uri]
	if !found {
		f = &File{
			URI:  uri,
			view: v,
		}
		v.files[uri] = f
	}
	return f
}

func (v *View) parse(uri source.URI) error {
	path, err := uri.Filename()
	if err != nil {
		return err
	}
	pkgs, err := packages.Load(&v.Config, fmt.Sprintf("file=%s", path))
	if len(pkgs) == 0 {
		if err == nil {
			err = fmt.Errorf("no packages found for %s", path)
		}
		return err
	}
	for _, pkg := range pkgs {
		imp := &importer{
			entries:         make(map[string]*entry),
			packages:        make(map[string]*packages.Package),
			v:               v,
			topLevelPkgPath: pkg.PkgPath,
		}

		// TODO(rstambler): Get real TypeSizes from go/packages.
		pkg.TypesSizes = &types.StdSizes{}

		if err := imp.addImports(pkg); err != nil {
			return err
		}

		// TODO(rstambler): Get real TypeSizes from go/packages.
		pkg.TypesSizes = &types.StdSizes{}

		imp.importPackage(pkg.PkgPath)
	}
	return nil
}

type importer struct {
	mu              sync.Mutex
	entries         map[string]*entry
	packages        map[string]*packages.Package
	topLevelPkgPath string

	v *View
}

type entry struct {
	pkg   *types.Package
	err   error
	ready chan struct{}
}

func (imp *importer) addImports(pkg *packages.Package) error {
	imp.packages[pkg.PkgPath] = pkg
	for _, i := range pkg.Imports {
		if i.PkgPath == pkg.PkgPath {
			return fmt.Errorf("import cycle: [%v]", pkg.PkgPath)
		}
		if err := imp.addImports(i); err != nil {
			return err
		}
	}
	return nil
}

func (imp *importer) Import(path string) (*types.Package, error) {
	if path == imp.topLevelPkgPath {
		return nil, fmt.Errorf("import cycle: [%v]", path)
	}
	imp.mu.Lock()
	e, ok := imp.entries[path]
	if ok {
		// cache hit
		imp.mu.Unlock()
		// wait for entry to become ready
		<-e.ready
	} else {
		// cache miss
		e = &entry{ready: make(chan struct{})}
		imp.entries[path] = e
		imp.mu.Unlock()

		// This goroutine becomes responsible for populating
		// the entry and broadcasting its readiness.
		e.pkg, e.err = imp.importPackage(path)
		close(e.ready)
	}
	return e.pkg, e.err
}

func (imp *importer) importPackage(pkgPath string) (*types.Package, error) {
	imp.mu.Lock()
	pkg, ok := imp.packages[pkgPath]
	imp.mu.Unlock()
	if !ok {
		return nil, fmt.Errorf("no metadata for %v", pkgPath)
	}
	pkg.Fset = imp.v.Config.Fset
	pkg.Syntax = make([]*ast.File, len(pkg.GoFiles))
	for i, filename := range pkg.GoFiles {
		var src interface{}
		overlay, ok := imp.v.Config.Overlay[filename]
		if ok {
			src = overlay
		}
		file, err := parser.ParseFile(imp.v.Config.Fset, filename, src, parser.AllErrors|parser.ParseComments)
		if file == nil {
			return nil, err
		}
		if err != nil {
			switch err := err.(type) {
			case *scanner.Error:
				pkg.Errors = append(pkg.Errors, packages.Error{
					Pos:  err.Pos.String(),
					Msg:  err.Msg,
					Kind: packages.ParseError,
				})
			case scanner.ErrorList:
				// The first parser error is likely the root cause of the problem.
				if err.Len() > 0 {
					pkg.Errors = append(pkg.Errors, packages.Error{
						Pos:  err[0].Pos.String(),
						Msg:  err[0].Msg,
						Kind: packages.ParseError,
					})
				}
			}
		}
		pkg.Syntax[i] = file
	}
	cfg := &types.Config{
		Error: func(err error) {
			if err, ok := err.(types.Error); ok {
				pkg.Errors = append(pkg.Errors, packages.Error{
					Pos:  imp.v.Config.Fset.Position(err.Pos).String(),
					Msg:  err.Msg,
					Kind: packages.TypeError,
				})
			}
		},
		Importer: imp,
	}
	pkg.Types = types.NewPackage(pkg.PkgPath, pkg.Name)
	pkg.TypesInfo = &types.Info{
		Types:      make(map[ast.Expr]types.TypeAndValue),
		Defs:       make(map[*ast.Ident]types.Object),
		Uses:       make(map[*ast.Ident]types.Object),
		Implicits:  make(map[ast.Node]types.Object),
		Selections: make(map[*ast.SelectorExpr]*types.Selection),
		Scopes:     make(map[ast.Node]*types.Scope),
	}
	check := types.NewChecker(cfg, imp.v.Config.Fset, pkg.Types, pkg.TypesInfo)
	check.Files(pkg.Syntax)

	// Add every file in this package to our cache.
	for _, file := range pkg.Syntax {
		// TODO: If a file is in multiple packages, which package do we store?
		if !file.Pos().IsValid() {
			log.Printf("invalid position for file %v", file.Name)
			continue
		}
		tok := imp.v.Config.Fset.File(file.Pos())
		if tok == nil {
			log.Printf("no token.File for %v", file.Name)
			continue
		}
		fURI := source.ToURI(tok.Name())
		f := imp.v.getFile(fURI)
		f.token = tok
		f.ast = file
		f.pkg = pkg
	}
	return pkg.Types, nil
}

func (v *View) GetAnalysisCache() *source.AnalysisCache {
	if v.analysisCache == nil {
		v.analysisCache = source.NewAnalysisCache()
	}
	return v.analysisCache
}
