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

	fidlcommon "fidl-lsp/third_party/common"

	"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 := fidlcommon.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
}
