// Copyright 2020 The Fuchsia 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 main

import (
	"bytes"
	"errors"
	"fmt"
	"io/ioutil"
	"os"
	"path/filepath"
	"regexp"
	"sort"
	"strings"
	"sync"
)

// A library is a FIDL library represented by its name (as spelled in its
// "library" declaration, not necessarily matching directory or file names).
type library string

// A libraryMap stores information derived about a group of libraries.
type libraryMap map[library]libraryInfo

type libraryInfo struct {
	// Directory containing the library.
	dir string
	// FIDL files that make up the library (relative to dir, or absolute).
	files []string
	// Direct dependencies (imported by "using" declarations in files).
	deps []library
}

// A libraryCache is a thread-safe, append-only libraryMap.
type libraryCache struct {
	sync.RWMutex
	libs libraryMap
}

func (c *libraryCache) get(lib library) (libraryInfo, bool) {
	c.RLock()
	defer c.RUnlock()
	info, ok := c.libs[lib]
	return info, ok
}

func (c *libraryCache) storeNew(libs libraryMap) {
	// Avoid write contention by skipping the operation if all the libraries in
	// libs are already in the cache.
	if !c.hasNew(libs) {
		return
	}
	c.Lock()
	defer c.Unlock()
	for lib, info := range libs {
		if _, ok := c.libs[lib]; !ok {
			c.libs[lib] = info
		}
	}
}

func (c *libraryCache) hasNew(libs libraryMap) bool {
	c.RLock()
	defer c.RUnlock()
	for lib := range libs {
		if _, ok := c.libs[lib]; !ok {
			return true
		}
	}
	return false
}

// libraryAnalyzer analyzes FIDL files to infer library dependencies. It caches
// information to speed up future analyses.
type libraryAnalyzer struct {
	// Paths in which to search for FIDL library files. Given library foo.bar,
	// the analyzer will check P/foo.bar and P/foo-bar for each path P in paths.
	// If one of these exists, it reads all descendent .fidl files.
	paths []string
	// Global cache of library information.
	cache libraryCache
}

func newLibraryAnalyzer(paths []string) *libraryAnalyzer {
	return &libraryAnalyzer{
		paths: paths,
		cache: libraryCache{
			libs: make(libraryMap),
		},
	}
}

const existingLibraryNotice = "" +
	"NOTE: Your file will be compiled with the others in this library. " +
	"If you don't want this behavior, choose a different library name."

// analyze analyzes content, returning a libraryMap that includes content's
// library together with all its transitive dependencies, and annotations on the
// "library" and "using" declarations indicating their inferred location. It
// assumes that filename is a FIDL file containing content. If any library
// cannot be located in a.paths, it is silently ignored.
func (a *libraryAnalyzer) analyze(filename, content string) (libraryMap, []Annotation) {
	result := make(libraryMap)

	// Start with a stack containing the root library (if it's a platform source
	// library, meaning we can expect to find it in the tree) and its imports.
	var stack []library
	rootLibraryMatch, rootLibraryOk := parseLibraryMatch(content)
	if rootLibraryOk && rootLibraryMatch.lib.isPlatform() {
		stack = append(stack, rootLibraryMatch.lib)
	}
	rootImports := parsePlatformImportsMatch(content)
	for _, m := range rootImports {
		stack = append(stack, m.lib)
	}

	// Explore all dependencies via depth-first search.
	for len(stack) != 0 {
		// Pop a library and check if it needs processing.
		var lib library
		lib, stack = stack[len(stack)-1], stack[:len(stack)-1]
		if _, ok := result[lib]; ok {
			continue
		}

		// Check the analyzer's cache.
		if info, ok := a.cache.get(lib); ok {
			result[lib] = info
			stack = append(stack, info.deps...)
			continue
		}

		// Find the library's files and dependencies.
		var info libraryInfo
		for _, path := range a.paths {
			for _, dir := range lib.possibleDirs() {
				if !info.empty() {
					break
				}
				info.dir = filepath.Join(path, dir)
				// Keep track of already-seen imports to ensure that info.deps
				// has no duplicates (there won't be duplicates in a valid FIDL
				// file, but separate files might import the same library).
				seen := map[library]struct{}{}
				// Visit all .fidl files, including in subdirectories:
				filepath.Walk(info.dir, func(file string, fi os.FileInfo, err error) error {
					if err != nil || fi.IsDir() || filepath.Ext(file) != ".fidl" {
						return err
					}
					rel, err := filepath.Rel(info.dir, file)
					if err != nil {
						return err
					}
					b, err := ioutil.ReadFile(file)
					if err != nil {
						return err
					}
					declaredLib, ok := parseLibrary(b)
					if !ok || declaredLib != lib {
						return nil
					}
					info.files = append(info.files, rel)
					for _, dep := range parsePlatformImports(b) {
						if _, ok := seen[dep]; ok {
							continue
						}
						seen[dep] = struct{}{}
						info.deps = append(info.deps, dep)
						stack = append(stack, dep)
					}
					return nil
				})
			}
		}
		if !info.empty() {
			result[lib] = info
		}
	}

	// Cache reusable results first, before adding request-specific information.
	a.cache.storeNew(result)

	// The following handles two cases:
	//   1. (More common) The user typed something like `library foo;`. This
	//      is a new library outside the source tree, consisting of one file.
	//   2. The user typed something like `library fuchsia.io;`. This behaves as
	//      if they were adding a new file to the fuchsia.io library, alongside
	//      the other ones in the source tree.
	rootLib := rootLibraryMatch.lib
	if !rootLibraryOk {
		// The name doesn't really matter. We just need an entry in the map.
		rootLib = "fidlbolt"
	}
	var anns []Annotation
	rootInfo := libraryInfo{files: []string{filename}}
	for _, m := range rootImports {
		rootInfo.deps = append(rootInfo.deps, m.lib)
		if info, ok := result[m.lib]; ok {
			text := fmt.Sprintf("Found %s in %s", m.lib, info.userVisibleDir())
			anns = append(anns, m.annotation(Info, text))
		}
	}
	if info, ok := result[rootLib]; ok {
		rootInfo = mergeInfo(rootInfo, info)
		if rootLibraryOk {
			text := fmt.Sprintf("Found %s in %s\n\n%s",
				rootLib, info.userVisibleDir(), existingLibraryNotice)
			anns = append(anns, rootLibraryMatch.annotation(Info, text))
		}
	}
	result[rootLib] = rootInfo

	return result, anns
}

// fidlcFileArgs returns a list of arguments to pass to fidlc to compile the
// libraries in m. This is a fairly expensive operation. It returns an error if
// there is an import cycle.
func (m libraryMap) fidlcFileArgs() ([]string, error) {
	sorted, err := m.topologicalSort()
	if err != nil {
		return nil, err
	}

	// Iterate in reverse order so that dependencies come before dependents.
	var args []string
	for i := len(sorted) - 1; i >= 0; i-- {
		lib := sorted[i]
		args = append(args, "--files")
		info := m[lib]
		for _, file := range info.files {
			// When the user declares their file as belong to an existing
			// library, their file will be an absolute path in a temp directory.
			// Otherwise, all files are relative to info.dir.
			if filepath.IsAbs(file) {
				args = append(args, file)
			} else {
				args = append(args, filepath.Join(info.dir, file))
			}
		}
	}
	return args, nil
}

const jsonDepIndentSize = 4

// jsonDependencyGraph returns a JSON object encoded as a string representing
// the dependency graph of m. Each key is a library name, and each value is
// another object whose keys are its direct dependencies.
func (m libraryMap) jsonDependencyGraph() (string, error) {
	// Make sure there are no cycles, otherwise this will never terminate.
	if _, err := m.topologicalSort(); err != nil {
		return "", err
	}

	sources := map[library]struct{}{}
	for lib := range m {
		sources[lib] = struct{}{}
	}
	for _, info := range m {
		for _, dep := range info.deps {
			delete(sources, dep)
		}
	}
	var start []string
	for lib := range sources {
		start = append(start, string(lib))
	}
	sort.Strings(start)

	var b strings.Builder
	indent := 0
	var gen func(libs []string)
	gen = func(libs []string) {
		b.WriteString("{\n")
		indent++
		for i, lib := range libs {
			b.WriteString(strings.Repeat(" ", indent*jsonDepIndentSize))
			b.WriteString(fmt.Sprintf(`"%s": `, lib))
			deps := m[library(lib)].deps
			if len(deps) == 0 {
				b.WriteString("{}")
			} else {
				var next []string
				for _, dep := range deps {
					next = append(next, string(dep))
				}
				sort.Strings(next)
				gen(next)
			}
			if i == len(libs)-1 {
				b.WriteString("\n")
			} else {
				b.WriteString(",\n")
			}
		}
		indent--
		b.WriteString(strings.Repeat(" ", indent*jsonDepIndentSize))
		b.WriteString("}")
	}
	gen(start)
	return b.String(), nil
}

// topologicalSort runs topological sort on m, whose deps fields define a
// directed graph in adjacency list form. In the resulting list, libraries only
// depend on other libraries later in the list, not on earlier ones. Returns
// an error if there is a cycle.
func (m libraryMap) topologicalSort() ([]library, error) {
	var sorted []library
	incoming := map[library]int{}
	for u := range m {
		incoming[u] = 0
	}
	for _, info := range m {
		for _, v := range info.deps {
			incoming[v]++
		}
	}
	var src []library
	for u, deg := range incoming {
		if deg == 0 {
			src = append(src, u)
		}
	}
	for len(src) != 0 {
		var u library
		u, src = src[len(src)-1], src[:len(src)-1]
		sorted = append(sorted, u)
		for _, v := range m[u].deps {
			incoming[v]--
			if incoming[v] == 0 {
				src = append(src, v)
			}
		}
	}
	for _, deg := range incoming {
		if deg != 0 {
			return nil, errors.New("detected an import cycle")
		}
	}
	return sorted, nil
}

// possibleDirs returns directory names that lib's files might be found in.
func (lib library) possibleDirs() []string {
	return []string{string(lib), strings.ReplaceAll(string(lib), ".", "-")}
}

// isPlatform returns true if lib adheres to the naming scheme for platform
// source libraries (enforced by the FIDL linter).
func (lib library) isPlatform() bool {
	s := string(lib)
	return strings.HasPrefix(s, "fidl.") ||
		strings.HasPrefix(s, "fuchsia.") ||
		strings.HasPrefix(s, "test.")
}

// empty returns true if i represents an empty library (has no files).
func (i *libraryInfo) empty() bool {
	return len(i.files) == 0
}

// userVisibleDir returns a representation of i.dir to show to the user.
func (i *libraryInfo) userVisibleDir() string {
	dir := filepath.ToSlash(i.dir)
	if i := strings.Index(dir, "/fuchsia/"); i != -1 {
		return dir[i+1:]
	}
	return dir
}

// mergeInfo returns a combination of the information in info and other. It
// assumes that only one of them has dir set.
func mergeInfo(info, other libraryInfo) libraryInfo {
	if info.dir != "" && other.dir != "" {
		panic("mergeInfo called with incompatible dirs")
	}
	if info.dir == "" {
		info.dir = other.dir
	}
	info.files = append(info.files, other.files...)
	deps := map[library]struct{}{}
	for _, lib := range info.deps {
		deps[lib] = struct{}{}
	}
	for _, lib := range other.deps {
		if _, ok := deps[lib]; !ok {
			info.deps = append(info.deps, lib)
		}
	}
	return info
}

var (
	// https://fuchsia.dev/fuchsia-src/development/languages/fidl/reference/language.md#identifiers
	fidlIdentifierPattern = `[a-zA-Z](?:[a-zA-Z0-9_]*[a-zA-Z0-9])?`

	// Although "library" can be used anywhere (e.g. as a type name), this regex
	// is robust because the the library declaration must appear at the top of
	// the file (only comments and whitespace can precede it).
	libraryRegexp = regexp.MustCompile(`` +
		`^(?:\s*//[^\n]*\n)*\s*` +
		`library\s+(` +
		fidlIdentifierPattern +
		`(?:\.` + fidlIdentifierPattern + `)*` +
		`)\s*;`)

	// Although "using" can be used anywhere (e.g. as a type name), this regex
	// is robust because it only matches imports of platform libraries (ones
	// that start with fidl, fuchsia, or test). The only problem is it can match
	// commented imports, so we have to check for this after matching.
	platformImportRegexp = regexp.MustCompile(`` +
		`\busing\s+(` +
		`(?:fidl|fuchsia|test)` +
		`(?:\.` + fidlIdentifierPattern + `)+` +
		`)` +
		`(?:\s+as\s+` + fidlIdentifierPattern + `)?` +
		`\s*;`)
)

type libraryMatch struct {
	lib          library
	line, column int
}

func parseLibrary(fidl []byte) (library, bool) {
	m := libraryRegexp.FindSubmatch(fidl)
	if m == nil {
		return "", false
	}
	return library(m[1]), true
}

func parseLibraryMatch(fidl string) (libraryMatch, bool) {
	m := libraryRegexp.FindStringSubmatchIndex(fidl)
	if m == nil {
		return libraryMatch{}, false
	}
	return toLibraryMatch(fidl, m[2], m[3]), true
}

func parsePlatformImports(fidl []byte) []library {
	var libs []library
	for _, m := range platformImportRegexp.FindAllSubmatchIndex(fidl, -1) {
		// Make sure the line isn't commented. Technically this breaks if the
		// line contains a string const with "//" in it. This isn't a big deal
		// because imports are supposed to come before all other declarations.
		i := bytes.LastIndexByte(fidl[:m[2]], '\n')
		if i == -1 || !bytes.Contains(fidl[i:m[2]], []byte("//")) {
			libs = append(libs, library(fidl[m[2]:m[3]]))
		}
	}
	return libs
}

func parsePlatformImportsMatch(fidl string) []libraryMatch {
	var libs []libraryMatch
	for _, m := range platformImportRegexp.FindAllStringSubmatchIndex(fidl, -1) {
		// See the comment in parsePlatformImports.
		i := strings.LastIndexByte(fidl[:m[2]], '\n')
		if i == -1 || !strings.Contains(fidl[i:m[2]], "//") {
			libs = append(libs, toLibraryMatch(fidl, m[2], m[3]))
		}
	}
	return libs
}

func toLibraryMatch(fidl string, start, end int) libraryMatch {
	return libraryMatch{
		lib:    library(fidl[start:end]),
		line:   strings.Count(fidl[:start], "\n") + 1,
		column: start - strings.LastIndexByte(fidl[:start], '\n'),
	}
}

func (m *libraryMatch) annotation(kind AnnotationKind, text string) Annotation {
	return Annotation{
		Line:   m.line,
		Column: m.column,
		Kind:   kind,
		Text:   text,
	}
}
