// 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 (
	"context"
	"encoding/json"
	"fmt"
	"io/ioutil"
	"os"
	"strings"
)

// A server handles fidlbolt requests.
type server struct {
	// Deployment information, or nil.
	deployment *deployment
	// External programs used by fidlbolt.
	fidlFormat, fidlLint, fidlc, fidlgenLlcpp, fidlgenHlcpp, fidlgenRust,
	fidlgenGo, fidlgenDart, clangFormat, rustfmt program
	// External files used by fidlbolt.
	rustfmtToml string
	// Cache of FIDL library information.
	libraryAnalyzer *libraryAnalyzer
}

// newServer returns a new fidlbolt server. It takes three lists of paths: bin,
// for locating binaries, etc, for locating config files, and fidl, for locating
// FIDL libraries. Returns an error if a required file could not be located.
func newServer(bin, etc, fidl []string) (*server, error) {
	var s server
	var err error
	if deploymentFile, err := findFile("fidlbolt_deployment.json", etc); err == nil {
		deploymentBytes, err := ioutil.ReadFile(deploymentFile)
		if err != nil {
			return nil, fmt.Errorf("failed to read etc/fidlbolt_deployment.json: %s", err)
		}
		s.deployment = new(deployment)
		if err = json.Unmarshal(deploymentBytes, s.deployment); err != nil {
			return nil, fmt.Errorf("failed to parse etc/fidlbolt_deployment.json: %s", err)
		}
	}
	s.fidlFormat, err = findProgram("fidl-format", bin)
	if err != nil {
		return nil, err
	}
	s.fidlLint, err = findProgram("fidl-lint", bin)
	if err != nil {
		return nil, err
	}
	s.fidlc, err = findProgram("fidlc", bin)
	if err != nil {
		return nil, err
	}
	s.fidlgenLlcpp, err = findProgram("fidlgen_llcpp", bin)
	if err != nil {
		return nil, err
	}
	s.fidlgenHlcpp, err = findProgram("fidlgen_hlcpp", bin)
	if err != nil {
		return nil, err
	}
	s.fidlgenRust, err = findProgram("fidlgen_rust", bin)
	if err != nil {
		return nil, err
	}
	s.fidlgenGo, err = findProgram("fidlgen_go", bin)
	if err != nil {
		return nil, err
	}
	s.fidlgenDart, err = findProgram("fidlgen_dart", bin)
	if err != nil {
		return nil, err
	}
	s.clangFormat, err = findProgram("clang-format", bin)
	if err != nil {
		return nil, err
	}
	s.rustfmt, err = findProgram("rustfmt", bin)
	if err != nil {
		return nil, err
	}
	s.rustfmtToml, err = findFile("rustfmt.toml", etc)
	if err != nil {
		return nil, err
	}
	s.libraryAnalyzer = newLibraryAnalyzer(fidl)
	return &s, nil
}

// A request provides input to be converted to an output mode.
type request struct {
	// Content to be converted.
	Content string `json:"content"`
	// The mode of Content.
	InputMode mode `json:"inputMode"`
	// The desired output mode.
	OutputMode mode `json:"outputMode"`
	// Options for configuring the conversion.
	Options options `json:"options"`
}

// A response contains the result of converting to an output mode.
type response struct {
	// True if conversion was successful.
	Ok bool `json:"ok"`
	// If Ok is true, Content contains the conversion result (in the requested
	// output mode). Otherwise, it contains an error message.
	Content string `json:"content"`
	// List of annotations to apply to on the input.
	Annotations []annotation `json:"annotations"`
	// Information about the deployment that served this response.
	Deployment *deployment `json:"deployment,omitempty"`
}

// A deployment describes the provenance of all resources used to service a
// request, including the fidlbolt server itself, external binaries, FIDL
// libaries, configuration files, etc.
type deployment struct {
	// This repository.
	// https://fuchsia.googlesource.com/fidlbolt
	Fidlbolt commit `json:"fidlbolt"`
	// Fuchsia provides most resources used by fidlbolt.
	// https://fuchsia.googlesource.com/fuchsia
	Fuchsia commit `json:"fuchsia"`
	// Topaz provides the fidlgen_dart binary.
	// https://fuchsia.googlesource.com/topaz
	Topaz commit `json:"topaz"`
	// ClangFormat provides the clang-format binary.
	// https://llvm.googlesource.com/a/llvm-project
	ClangFormat version `json:"clang-format"`
	// Rustfmt provides the rustfmt binary.
	// https://github.com/rust-lang/rustfmt
	Rustfmt version `json:"rustfmt"`
}

// A commit designates a commit in a source code repository.
type commit struct {
	// Full hash of the commit.
	Hash string `json:"hash"`
	// Unix timestamp of the commit, in seconds.
	Timestamp uint64 `json:"timestamp"`
}

// A version designates a software version by a string like "1.2.3".
type version struct {
	Version string `json:"version"`
}

// options are used to configure mode conversions.
type options struct {
	// File to generate (header, source, etc.).
	File string `json:"file"`
	// Lint in addition to formatting.
	Lint bool `json:"lint"`
	// Number of byte columns.
	Columns int `json:"columns"`
	// Byte grouping size.
	Group int `json:"group"`
	// Use capital letters for hex values.
	Capital bool `json:"capital"`
	// Show byte offsets at the start of each line.
	Offsets bool `json:"offsets"`
	// Show ASCII characters at the end of lines like xxd.
	ASCII bool `json:"ascii"`
}

// An annotation is a message targeted at a specific location of a file.
type annotation struct {
	// One-based line number.
	Line int `json:"line"`
	// One-based column number.
	Column int `json:"column"`
	// Kind of annotation.
	Kind annotationKind `json:"kind"`
	// Body of the annotation.
	Text string `json:"text"`
}

// annotationKind is a string enum for annotation.
type annotationKind string

// Enumeration of annotationKind values.
const (
	Info    annotationKind = "info"
	Warning annotationKind = "warning"
	Error   annotationKind = "error"
)

// A mode is an input or output format.
type mode string

// Enumeration of mode values.
const (
	Bytes     mode = "bytes"
	BytesPlus mode = "bytes+"
	C         mode = "c"
	Dart      mode = "dart"
	Diff      mode = "diff"
	FIDL      mode = "fidl"
	FIDLText  mode = "fidltext"
	Go        mode = "go"
	HLCPP     mode = "hlcpp"
	JSON      mode = "json"
	LLCPP     mode = "llcpp"
	Rust      mode = "rust"
)

type modeSet = map[mode]struct{}

var inputModes = modeSet{
	FIDL:     {},
	FIDLText: {},
	Bytes:    {},
}

var outputModes = map[mode]modeSet{
	FIDL: {
		FIDL:  {},
		JSON:  {},
		C:     {},
		LLCPP: {},
		HLCPP: {},
		Rust:  {},
		Go:    {},
		Dart:  {},
	},
	FIDLText: {
		FIDLText:  {},
		Bytes:     {},
		BytesPlus: {},
	},
	Bytes: {
		Bytes:     {},
		Diff:      {},
		FIDLText:  {},
		BytesPlus: {},
	},
}

// validate validates a request. Once validated, any errors in processing the
// request are considered internal server errors.
func (r *request) validate() error {
	if err := r.InputMode.validate(inputModes); err != nil {
		return err
	}
	if err := r.OutputMode.validate(outputModes[r.InputMode]); err != nil {
		return err
	}

	switch r.OutputMode {
	case JSON:
		switch r.Options.File {
		case "ir", "schema", "deps":
		default:
			return fmt.Errorf("invalid JSON IR file option: %q", r.Options.File)
		}
	case HLCPP:
		switch r.Options.File {
		case "header", "source", "tables":
		default:
			return fmt.Errorf("invalid HLCPP file option: %q", r.Options.File)
		}
	case LLCPP:
		switch r.Options.File {
		case "header", "source", "tables", "test":
		default:
			return fmt.Errorf("invalid LLCPP file option: %q", r.Options.File)
		}
	case C:
		switch r.Options.File {
		case "header", "client", "server", "tables":
		default:
			return fmt.Errorf("invalid C file option: %q", r.Options.File)
		}
	case Dart:
		switch r.Options.File {
		case "library", "test":
		default:
			return fmt.Errorf("invalid Dart file option: %q", r.Options.File)
		}
	default:
		if r.Options.File != "" {
			return fmt.Errorf("unexpected file option: %q", r.Options.File)
		}
	}

	if r.OutputMode == Bytes {
		if r.Options.Columns <= 0 {
			return fmt.Errorf("invalid columns: %d", r.Options.Columns)
		}
		if r.Options.Group <= 0 {
			return fmt.Errorf("invalid group: %d", r.Options.Group)
		}
	}

	return nil
}

func (m mode) validate(allowed modeSet) error {
	if _, ok := allowed[m]; !ok {
		return fmt.Errorf("invalid mode: %q", m)
	}
	return nil
}

// serve processes a request and serves a response. It returns an error if the
// request could not be processed for some reason (e.g., an IO failure).
func (s *server) serve(ctx context.Context, r *request) (response, error) {
	res, err := s.handle(ctx, r)
	if err != nil {
		return response{}, err
	}
	res.Deployment = s.deployment
	return res, nil
}

func (s *server) handle(ctx context.Context, r *request) (response, error) {
	switch r.InputMode {
	case FIDL:
		return s.handleFIDL(ctx, r)
	case FIDLText:
		return s.handleFIDLText(ctx, r)
	case Bytes:
		return s.handleBytes(ctx, r)
	}
	return response{}, fmt.Errorf("invalid input mode: %q", r.InputMode)
}

func (s *server) handleFIDL(ctx context.Context, r *request) (response, error) {
	temp, err := newTempDir()
	if err != nil {
		return response{}, err
	}
	defer os.RemoveAll(temp.path)
	fidl, err := temp.createFile("fidlbolt.fidl", r.Content)
	if err != nil {
		return response{}, err
	}
	libs, anns := s.libraryAnalyzer.analyze(fidl, r.Content)
	res, err := s.handleFIDLWithTemp(ctx, r, temp, fidl, libs)
	if err != nil {
		return res, err
	}
	res.Annotations = append(res.Annotations, anns...)
	// Remove all occurrences of the temp path to avoid exposing it to the user.
	// This is mostly needed for error output, but it is also needed e.g. for
	// the JSON IR, which includes source paths.
	res.Content = strings.ReplaceAll(res.Content, temp.path+"/", "")
	res.Content = strings.ReplaceAll(res.Content, temp.path, "")
	return res, nil
}

const jsonDepIndentSize = 4

func (s *server) handleFIDLWithTemp(ctx context.Context, r *request, temp tempDir, fidl string, libs libraryMap) (response, error) {
	// Run fidlc, automatically appending the correct --files arguments.
	fidlc := func(args ...string) (response, error) {
		fileArgs, err := libs.fidlcFileArgs()
		if err != nil {
			msg := fmt.Sprintf("%s:1:1: error: %s", fidl, err)
			return response{Ok: false, Content: msg}, nil
		}
		args = append(args, "--experimental", "old_syntax_only")
		run, err := s.fidlc.run(ctx, append(args, fileArgs...)...)
		if err != nil {
			return response{}, err
		}
		res := response{
			Ok:          run.success,
			Annotations: parseFidlAnnotations(run.stderr),
		}
		if run.success {
			res.Content = run.stdout
		} else {
			res.Content = run.stderr
		}
		return res, nil
	}

	switch r.OutputMode {
	case C, LLCPP, HLCPP:
		if r.Options.File == "tables" {
			return fidlc("--tables", "/dev/stdout")
		}
	}

	switch r.OutputMode {
	case FIDL:
		prog := s.fidlFormat
		if r.Options.Lint {
			prog = s.fidlLint
		}
		run, err := prog.run(ctx, fidl)
		if err != nil {
			return response{}, err
		}
		res := response{
			Ok:          run.success,
			Annotations: parseFidlAnnotations(run.stderr),
		}
		if run.success {
			if r.Options.Lint {
				res.Content = "// Lint passed!"
			} else {
				res.Content = run.stdout
			}
		} else {
			res.Content = run.stderr
		}
		return res, nil
	case JSON:
		switch r.Options.File {
		case "ir":
			return fidlc("--json", "/dev/stdout")
		case "schema":
			run, err := s.fidlc.runInfallible(ctx, "--json-schema")
			if err != nil {
				return response{}, err
			}
			return response{Ok: true, Content: run.stdout}, nil
		case "deps":
			graph, err := libs.dependencyGraph()
			if err != nil {
				msg := fmt.Sprintf("%s:1:1: error: %s", fidl, err)
				return response{Ok: false, Content: msg}, nil
			}
			b, err := json.MarshalIndent(graph, "", strings.Repeat(" ", jsonDepIndentSize))
			if err != nil {
				msg := fmt.Sprintf("%s:1:1: error: %s", fidl, err)
				return response{Ok: false, Content: msg}, nil
			}
			return response{Ok: true, Content: string(b)}, nil
		default:
			return response{}, fmt.Errorf("invalid file: %q", r.Options.File)
		}
	case C:
		switch r.Options.File {
		case "header":
			return fidlc("--deprecated-fuchsia-only-c-header", "/dev/stdout")
		case "client":
			return fidlc("--deprecated-fuchsia-only-c-client", "/dev/stdout")
		case "server":
			return fidlc("--deprecated-fuchsia-only-c-server", "/dev/stdout")
		default:
			return response{}, fmt.Errorf("invalid file: %q", r.Options.File)
		}
	}

	jsonIR := fidl + ".json"
	res, err := fidlc("--json", jsonIR)
	if err != nil {
		return response{}, err
	}
	if !res.Ok {
		return res, nil
	}
	res.Content, err = s.handleFIDLWithIR(ctx, r, temp, jsonIR)
	if err != nil {
		return response{}, err
	}
	return res, nil
}

func (s *server) handleFIDLWithIR(ctx context.Context, r *request, temp tempDir, jsonIR string) (string, error) {
	switch r.OutputMode {
	case HLCPP:
		if _, err := s.fidlgenHlcpp.runInfallible(ctx,
			"-json", jsonIR,
			"-include-base", temp.path,
			"-output-base", temp.join("impl"),
			"-clang-format-path", s.clangFormat.path,
		); err != nil {
			return "", err
		}
		switch r.Options.File {
		case "header":
			return temp.readFile("impl.h")
		case "source":
			return temp.readFile("impl.cc")
		default:
			return "", fmt.Errorf("invalid file: %q", r.Options.File)
		}
	case LLCPP:
		if _, err := s.fidlgenLlcpp.runInfallible(ctx,
			"-json", jsonIR,
			"-header", temp.join("impl.h"),
			"-source", temp.join("impl.cc"),
			"-test-base", temp.join("test.h"),
			"-clang-format-path", s.clangFormat.path,
		); err != nil {
			return "", err
		}
		switch r.Options.File {
		case "header":
			return temp.readFile("impl.h")
		case "source":
			return temp.readFile("impl.cc")
		case "test":
			return temp.readFile("test.h")
		default:
			return "", fmt.Errorf("invalid file: %q", r.Options.File)
		}
	case Rust:
		if _, err := s.fidlgenRust.runInfallible(ctx,
			"-json", jsonIR,
			"-output-filename", temp.join("impl.rs"),
			"-rustfmt", s.rustfmt.path,
			"-rustfmt-config", s.rustfmtToml,
		); err != nil {
			return "", err
		}
		return temp.readFile("impl.rs")
	case Go:
		if _, err := s.fidlgenGo.runInfallible(ctx,
			"-json", jsonIR,
			"-output-impl", temp.join("impl.go"),
		); err != nil {
			return "", err
		}
		return temp.readFile("impl.go")
	case Dart:
		var name string
		switch r.Options.File {
		case "library":
			name = "async"
		case "test":
			name = "test"
		default:
			return "", fmt.Errorf("invalid file: %q", r.Options.File)
		}
		// TODO(fxbug.dev/70703): Pass -dartfmt.
		if _, err := s.fidlgenDart.runInfallible(ctx,
			"-json", jsonIR,
			"-output-"+name, temp.join("impl.dart"),
		); err != nil {
			return "", err
		}
		return temp.readFile("impl.dart")
	}
	return "", fmt.Errorf("invalid output mode: %q", r.OutputMode)
}

func (s *server) handleFIDLText(ctx context.Context, r *request) (response, error) {
	return response{Ok: false, Content: "Not implemented"}, nil
}

func (s *server) handleBytes(ctx context.Context, r *request) (response, error) {
	switch r.OutputMode {
	case Bytes:
		b, pos, err := parseBytes(r.Content)
		if err != nil {
			msg := fmt.Sprintf("%s: error: %s", pos, err)
			ann := annotation{
				Line:   pos.Line,
				Column: pos.Column,
				Kind:   Error,
				Text:   err.Error(),
			}
			return response{Ok: false, Content: msg, Annotations: []annotation{ann}}, nil
		}
		formatted, err := formatBytes(b, &r.Options)
		if err != nil {
			return response{}, err
		}
		return response{Ok: true, Content: formatted}, nil
	case Diff, FIDLText, BytesPlus:
		return response{Ok: false, Content: "Not implemented"}, nil
	}
	return response{}, fmt.Errorf("invalid output mode: %q", r.OutputMode)
}
