// 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 analysis

import (
	"bytes"
	"encoding/json"
	"fmt"
	"io/ioutil"
	"log"
	"os/exec"
	"strconv"
	"strings"

	"fidl-lsp/third_party/fidlgen"

	"fidl-lsp/state"
)

type compileResult struct {
	lib   *Library
	diags map[state.FileID][]Diagnostic
}

// Compile the FIDL library that includes the file at `path`.
// Returns either a compileResult containing the name of the library along with
// any diagnostics returned by fidlc and fidl-lint, or an error if compilation
// fails.
func (a *Analyzer) compile(fs *state.FileSystem, path state.FileID) (compileResult, error) {
	var jsonPath string
	file, err := fs.File(path)
	if err != nil {
		return compileResult{}, fmt.Errorf("could not find file `%s`", path)
	}

	libraryName, err := state.LibraryOfFile(file)
	if err != nil {
		return compileResult{}, fmt.Errorf("could not find library name of file `%s`: %s", path, err)
	}
	jsonPath = a.pathToJSON(libraryName)

	args := append([]string{"--format=json"}, "--json", jsonPath)
	files, err := a.FindDeps(fs, path)
	if err != nil {
		return compileResult{}, fmt.Errorf("could not find dependencies of file `%s`: %s", path, err)
	}
	args = append(args, files...)

	cmd := exec.Command(a.cfg.FidlcPath, args...)
	var stderr bytes.Buffer
	cmd.Stderr = &stderr
	if err := cmd.Run(); err == nil {
		// If fidlc compiled successfully, update a.libs with the compiled JSON IR
		if err := a.importLibraryWithFile(jsonPath, path); err != nil {
			return compileResult{}, fmt.Errorf("error on adding compiled JSON: %s", err)
		}
	} else {
		// TODO: there is no platform-independent way in Go to check an error
		// status code, but if we can, we should somehow determine if fidlc
		// exited with status code 1 (failure due to FIDL errors) or something
		// else (internal error or command otherwise failed).
		// If it's status code 1, we should continue, but anything else, we
		// should return an error from `compile` to signal failure.
	}

	diags := make(map[state.FileID][]Diagnostic)
	lib, ok := a.getLibraryWithFile(libraryName, path)
	if !ok {
		log.Printf("could not find library `%s` with file `%s`\n", libraryName.FullyQualifiedName(), path)
	} else {
		for fileName := range lib.files {
			fileID, err := a.inputFileToFileID(fileName)
			if err == nil {
				diags[fileID] = []Diagnostic{}
			}
		}
	}
	if errorsAndWarnings, err := a.fidlcDiagsFromStderr(stderr.Bytes()); err == nil {
		for fileID, fileDiags := range errorsAndWarnings {
			if _, ok := diags[fileID]; !ok {
				diags[fileID] = []Diagnostic{}
			}
			diags[fileID] = append(diags[fileID], fileDiags...)
		}
	}
	if lints, err := a.runFidlLint(a.inputFilesFIDL[path]); err == nil {
		for fileID, fileDiags := range lints {
			if _, ok := diags[fileID]; !ok {
				diags[fileID] = []Diagnostic{}
			}
			diags[fileID] = append(diags[fileID], fileDiags...)
		}
	}

	return compileResult{
		lib:   lib,
		diags: diags,
	}, nil
}

// compileLibrary essentially does the same thing as importLibrary but for a
// library that is already stored in a.libs, but the JSON IR for which has not
// been imported.
func (a *Analyzer) compileLibrary(lib *Library) error {
	data, err := ioutil.ReadFile(lib.json)
	if err != nil {
		return err
	}
	var jsonIR FidlLibrary
	if err := json.Unmarshal(data, &jsonIR); err != nil {
		return err
	}
	lib.ir = &jsonIR

	// Construct symbol map from JSON IR for the file's library
	symbols, err := a.genSymbolMap(jsonIR)
	if err != nil {
		return fmt.Errorf("unable to generate symbol map from library %s: %s", jsonIR.Name, err)
	}
	lib.symbols = symbols

	return nil
}

// importLibraryWithFile reads in the JSON IR at absolute filepath `jsonPath`.
func (a *Analyzer) importLibraryWithFile(jsonPath string, path state.FileID) error {
	data, err := ioutil.ReadFile(jsonPath)
	if err != nil {
		return err
	}
	var jsonIR FidlLibrary
	if err := json.Unmarshal(data, &jsonIR); err != nil {
		return err
	}
	// TODO: import more things? files + deps?
	libName := fidlgen.MustReadLibraryName(jsonIR.Name)
	lib, ok := a.getLibraryWithFile(libName, path)
	if !ok {
		lib = &Library{}
		a.libs = append(a.libs, lib)
	}
	lib.ir = &jsonIR
	lib.json = jsonPath

	// Construct symbol map from JSON IR for the file's library
	symbols, err := a.genSymbolMap(jsonIR)
	if err != nil {
		return fmt.Errorf("unable to generate symbol map from library %s: %s", jsonIR.Name, err)
	}
	lib.symbols = symbols

	return nil
}

type symbolMap map[string]*symbolInfo

func (a *Analyzer) genSymbolMap(l FidlLibrary) (symbolMap, error) {
	sm := make(symbolMap)

	for _, d := range l.BitsDecls {
		sm[d.Name] = &symbolInfo{
			name:       d.Name,
			definition: a.fidlLocToStateLoc(d.Loc),
			typeInfo: Type{
				FromTypeAlias: d.FromTypeAlias.TypeAlias(),
				Kind:          IdentifierType,
				Identifier: &IdentifierTypeInfo{
					IsDecl: true,
					Name:   d.Name,
					Kind:   BitsKind,
					Bits: &BitsTypeInfo{
						Type: d.Type.Type(),
					},
				},
				Attrs: d.Attrs,
			},
		}
		a.addMembersToSymbolMap(sm, d.Name, d.Members)
	}
	for _, d := range l.ConstDecls {
		sm[d.Name] = &symbolInfo{
			name:       d.Name,
			definition: a.fidlLocToStateLoc(d.Loc),
			typeInfo: Type{
				FromTypeAlias: d.FromTypeAlias.TypeAlias(),
				Kind:          IdentifierType,
				Identifier: &IdentifierTypeInfo{
					IsDecl: true,
					Name:   d.Name,
					Kind:   ConstKind,
					Const: &ConstTypeInfo{
						Type:  d.Type.Type(),
						Value: d.Value.Value,
					},
				},
				Attrs: d.Attrs,
			},
		}
	}
	for _, d := range l.EnumDecls {
		sm[d.Name] = &symbolInfo{
			name:       d.Name,
			definition: a.fidlLocToStateLoc(d.Loc),
			typeInfo: Type{
				FromTypeAlias: d.FromTypeAlias.TypeAlias(),
				Kind:          IdentifierType,
				Identifier: &IdentifierTypeInfo{
					IsDecl: true,
					Name:   d.Name,
					Kind:   EnumKind,
					Enum: &EnumTypeInfo{
						Type: PrimitiveSubtype(d.Type),
					},
				},
				Attrs: d.Attrs,
			},
		}
		a.addMembersToSymbolMap(sm, d.Name, d.Members)
	}
	for _, d := range l.ProtocolDecls {
		sm[d.Name] = &symbolInfo{
			name:       d.Name,
			definition: a.fidlLocToStateLoc(d.Loc),
			typeInfo: Type{
				Kind: IdentifierType,
				Identifier: &IdentifierTypeInfo{
					IsDecl: true,
					Name:   d.Name,
					Kind:   ProtocolKind,
				},
				Attrs: d.Attrs,
			},
		}
		for _, m := range d.Methods {
			methodName := fmt.Sprintf("%s.%s", d.Name, m.Name)
			sm[methodName] = &symbolInfo{
				name:       m.Name,
				definition: a.fidlLocToStateLoc(m.Loc),
				typeInfo: Type{
					IsMethod: true,
					Attrs:    m.Attrs,
				},
			}
			if len(m.MaybeRequest) > 0 {
				a.addMembersToSymbolMap(sm, methodName, m.MaybeRequest)
			}
			if len(m.MaybeResponse) > 0 {
				a.addMembersToSymbolMap(sm, methodName, m.MaybeResponse)
			}
		}
	}
	for _, d := range l.ServiceDecls {
		sm[d.Name] = &symbolInfo{
			name:       d.Name,
			definition: a.fidlLocToStateLoc(d.Loc),
			typeInfo: Type{
				Kind: IdentifierType,
				Identifier: &IdentifierTypeInfo{
					IsDecl: true,
					Name:   d.Name,
					Kind:   ServiceKind,
				},
				Attrs: d.Attrs,
			},
		}
		a.addMembersToSymbolMap(sm, d.Name, d.Members)
	}
	for _, d := range l.StructDecls {
		// Skip anonymous structs, since we add them to the symbol map as method
		// parameter structs
		if d.Anonymous {
			continue
		}
		sm[d.Name] = &symbolInfo{
			name:       d.Name,
			definition: a.fidlLocToStateLoc(d.Loc),
			typeInfo: Type{
				Kind: IdentifierType,
				Identifier: &IdentifierTypeInfo{
					IsDecl: true,
					Name:   d.Name,
					Kind:   StructKind,
				},
				Attrs: d.Attrs,
			},
		}
		a.addMembersToSymbolMap(sm, d.Name, d.Members)
	}
	for _, d := range l.TableDecls {
		sm[d.Name] = &symbolInfo{
			name:       d.Name,
			definition: a.fidlLocToStateLoc(d.Loc),
			typeInfo: Type{
				Kind: IdentifierType,
				Identifier: &IdentifierTypeInfo{
					IsDecl: true,
					Name:   d.Name,
					Kind:   TableKind,
				},
				Attrs: d.Attrs,
			},
		}
		a.addMembersToSymbolMap(sm, d.Name, d.Members)
	}
	for _, d := range l.UnionDecls {
		sm[d.Name] = &symbolInfo{
			name:       d.Name,
			definition: a.fidlLocToStateLoc(d.Loc),
			typeInfo: Type{
				Kind: IdentifierType,
				Identifier: &IdentifierTypeInfo{
					IsDecl: true,
					Name:   d.Name,
					Kind:   UnionKind,
				},
				Attrs: d.Attrs,
			},
		}
		a.addMembersToSymbolMap(sm, d.Name, d.Members)
	}
	for _, d := range l.TypeAliasDecls {
		sm[d.Name] = &symbolInfo{
			name:       d.Name,
			definition: a.fidlLocToStateLoc(d.Loc),
			typeInfo: Type{
				Kind: IdentifierType,
				Identifier: &IdentifierTypeInfo{
					IsDecl: true,
					Name:   d.Name,
					Kind:   TypeAliasKind,
					TypeAlias: &TypeAliasTypeInfo{
						Type: d.TypeCtor.Type(),
					},
				},
				Attrs: d.Attrs,
			},
		}
	}

	return sm, nil
}

func (a *Analyzer) addMembersToSymbolMap(sm symbolMap, declName string, members []member) {
	for _, m := range members {
		memberName := fmt.Sprintf("%s.%s", declName, m.Name)
		sm[memberName] = &symbolInfo{
			name:       m.Name,
			definition: a.fidlLocToStateLoc(m.Loc),
			typeInfo:   m.Type.Type(),
		}
		sm[memberName].typeInfo.FromTypeAlias = m.FromTypeAlias.TypeAlias()
		sm[memberName].typeInfo.Attrs = m.Attrs
	}
}

func (a *Analyzer) fidlLocToStateLoc(loc location) state.Location {
	// If this JSON IR was compiled by the language server, the `Filename`s for
	// for all the symbols will be tmp input files from the Analyzer. We want
	// to point at the corresponding editor files for these tmp files.
	fileID, err := a.inputFileToFileID(loc.Filename)
	if err != nil {
		// We assume `Filename` is a filepath to a precompiled JSON IR, provided
		// in the CompiledLibraries on startup.
		//
		// The `Filename` in a decl's location is recorded relative to where
		// fidlc was invoked. All the locations in CompiledLibraries are
		// prepended with "../../" which can be replaced by the `BuildRootDir`.
		fileID = state.FileID(strings.Replace(loc.Filename, "../..", a.cfg.BuildRootDir, 1))
	}
	return state.Location{
		FileID: fileID,
		Range: state.Range{
			Start: state.Position{Line: loc.Line - 1, Character: loc.Column - 1},
			End:   state.Position{Line: loc.Line - 1, Character: loc.Column - 1 + loc.Length},
		},
	}
}

func (d declType) Type() Type {
	t := Type{Kind: d.Kind}

	switch d.Kind {
	default:
		// Sometimes this will be called with a zeroed declType, e.g. for bits
		// and enum members, which don't have types.
		return t
	case ArrayType:
		t.Array = &ArrayTypeInfo{
			ElementType:  d.ElementType.Type(),
			ElementCount: d.ElementCount,
		}
	case VectorType:
		t.Vector = &VectorTypeInfo{
			ElementType:  d.ElementType.Type(),
			ElementCount: d.MaybeElementCount,
			Nullable:     d.Nullable,
		}
	case StringType:
		t.String = &StringTypeInfo{
			ElementCount: d.MaybeElementCount,
			Nullable:     d.Nullable,
		}
	case HandleType:
		t.Handle = &HandleTypeInfo{
			Subtype:  HandleSubtype(d.Subtype),
			Rights:   d.Rights,
			Nullable: d.Nullable,
		}
	case RequestType:
		t.Request = &RequestTypeInfo{
			Subtype:  d.Subtype,
			Nullable: d.Nullable,
		}
	case PrimitiveType:
		t.Primitive = &PrimitiveTypeInfo{
			Subtype: PrimitiveSubtype(d.Subtype),
		}
	case IdentifierType:
		t.Identifier = &IdentifierTypeInfo{
			Identifier: d.Identifier,
			Nullable:   d.Nullable,
		}
	}

	return t
}

func (t typeCtor) Type() Type {
	switch t.Name {
	case string(ArrayType):
		ty := Type{
			Kind:  ArrayType,
			Array: &ArrayTypeInfo{},
		}
		if len(t.Args) > 0 {
			ty.Array.ElementType = t.Args[0].Type()
		}
		if t.Size != nil {
			if count, err := strconv.ParseUint(t.Size.Value, 10, 32); err == nil {
				ty.Array.ElementCount = uint(count)
			}
		}
		return ty

	case string(VectorType):
		ty := Type{
			Kind: VectorType,
			Vector: &VectorTypeInfo{
				Nullable: t.Nullable,
			},
		}
		if len(t.Args) > 0 {
			ty.Vector.ElementType = t.Args[0].Type()
		}
		if t.Size != nil {
			if count, err := strconv.ParseUint(t.Size.Value, 10, 32); err == nil {
				countUint := uint(count)
				ty.Vector.ElementCount = &countUint
			}
		}
		return ty

	case string(StringType):
		ty := Type{
			Kind: StringType,
			String: &StringTypeInfo{
				Nullable: t.Nullable,
			},
		}
		if t.Size != nil {
			if count, err := strconv.ParseUint(t.Size.Value, 10, 32); err == nil {
				countUint := uint(count)
				ty.String.ElementCount = &countUint
			}
		}
		return ty

	case string(HandleType):
		ty := Type{
			Kind: HandleType,
			Handle: &HandleTypeInfo{
				Nullable: t.Nullable,
			},
		}
		if t.HandleSubtype != nil {
			ty.Handle.Subtype = *t.HandleSubtype
		}
		return ty

	case string(RequestType):
		ty := Type{
			Kind: RequestType,
			Request: &RequestTypeInfo{
				Nullable: t.Nullable,
			},
		}
		if len(t.Args) > 0 {
			ty.Request.Subtype = t.Args[0].Name
		}
		return ty

	case string(Bool), Int8, Int16, Int32, Int64, Uint8, Uint16, Uint32, Uint64, Float32, Float64:
		return Type{
			Kind: PrimitiveType,
			Primitive: &PrimitiveTypeInfo{
				Subtype: PrimitiveSubtype(t.Name),
			},
		}

	default:
		// We assume it is the name of an identifier type.
		return Type{
			Kind: IdentifierType,
			Identifier: &IdentifierTypeInfo{
				Identifier: t.Name,
				Nullable:   t.Nullable,
			},
		}
	}
}

func (t typeCtor) TypeAlias() *string {
	if t.Name == "" {
		return nil
	}
	return &t.Name
}
