// Copyright 2020 Google Inc. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package rust

import (
	"encoding/json"
	"fmt"

	"android/soong/android"
	"android/soong/rust/config"
)

// This singleton collects Rust crate definitions and generates a JSON file
// (${OUT_DIR}/soong/rust-project.json) which can be use by external tools,
// such as rust-analyzer. It does so when either make, mm, mma, mmm or mmma is
// called.  This singleton is enabled only if SOONG_GEN_RUST_PROJECT is set.
// For example,
//
//   $ SOONG_GEN_RUST_PROJECT=1 m nothing

const (
	// Environment variables used to control the behavior of this singleton.
	envVariableCollectRustDeps = "SOONG_GEN_RUST_PROJECT"
	rustProjectJsonFileName    = "rust-project.json"
)

// The format of rust-project.json is not yet finalized. A current description is available at:
// https://github.com/rust-analyzer/rust-analyzer/blob/master/docs/user/manual.adoc#non-cargo-based-projects
type rustProjectDep struct {
	// The Crate attribute is the index of the dependency in the Crates array in rustProjectJson.
	Crate int    `json:"crate"`
	Name  string `json:"name"`
}

type rustProjectCrate struct {
	DisplayName    string            `json:"display_name"`
	RootModule     string            `json:"root_module"`
	Edition        string            `json:"edition,omitempty"`
	Deps           []rustProjectDep  `json:"deps"`
	Cfg            []string          `json:"cfg"`
	Env            map[string]string `json:"env"`
	ProcMacro      bool              `json:"is_proc_macro"`
	ProcMacroDylib *string           `json:"proc_macro_dylib_path"`
}

type rustProjectJson struct {
	Sysroot string             `json:"sysroot"`
	Crates  []rustProjectCrate `json:"crates"`
}

// crateInfo is used during the processing to keep track of the known crates.
type crateInfo struct {
	Idx    int            // Index of the crate in rustProjectJson.Crates slice.
	Deps   map[string]int // The keys are the module names and not the crate names.
	Device bool           // True if the crate at idx was a device crate
}

type projectGeneratorSingleton struct {
	project     rustProjectJson
	knownCrates map[string]crateInfo // Keys are module names.
}

func rustProjectGeneratorSingleton() android.Singleton {
	return &projectGeneratorSingleton{}
}

func init() {
	android.RegisterParallelSingletonType("rust_project_generator", rustProjectGeneratorSingleton)
}

// mergeDependencies visits all the dependencies for module and updates crate and deps
// with any new dependency.
func (singleton *projectGeneratorSingleton) mergeDependencies(ctx android.SingletonContext,
	module *Module, crate *rustProjectCrate, deps map[string]int) {

	ctx.VisitDirectDeps(module, func(child android.Module) {
		// Skip intra-module dependencies (i.e., generated-source library depending on the source variant).
		if module.Name() == child.Name() {
			return
		}
		// Skip unsupported modules.
		rChild, ok := isModuleSupported(ctx, child)
		if !ok {
			return
		}
		// For unknown dependency, add it first.
		var childId int
		cInfo, known := singleton.knownCrates[rChild.Name()]
		if !known {
			childId, ok = singleton.addCrate(ctx, rChild)
			if !ok {
				return
			}
		} else {
			childId = cInfo.Idx
		}
		// Is this dependency known already?
		if _, ok = deps[child.Name()]; ok {
			return
		}
		crate.Deps = append(crate.Deps, rustProjectDep{Crate: childId, Name: rChild.CrateName()})
		deps[child.Name()] = childId
	})
}

// isModuleSupported returns the RustModule if the module
// should be considered for inclusion in rust-project.json.
func isModuleSupported(ctx android.SingletonContext, module android.Module) (*Module, bool) {
	rModule, ok := module.(*Module)
	if !ok {
		return nil, false
	}
	if !rModule.Enabled(ctx) {
		return nil, false
	}
	return rModule, true
}

// addCrate adds a crate to singleton.project.Crates ensuring that required
// dependencies are also added. It returns the index of the new crate in
// singleton.project.Crates
func (singleton *projectGeneratorSingleton) addCrate(ctx android.SingletonContext, rModule *Module) (int, bool) {
	deps := make(map[string]int)
	rootModule, err := rModule.compiler.checkedCrateRootPath()
	if err != nil {
		return 0, false
	}

	var procMacroDylib *string = nil
	if procDec, procMacro := rModule.compiler.(*procMacroDecorator); procMacro {
		procMacroDylib = new(string)
		*procMacroDylib = procDec.baseCompiler.unstrippedOutputFilePath().String()
	}

	crate := rustProjectCrate{
		DisplayName:    rModule.Name(),
		RootModule:     rootModule.String(),
		Edition:        rModule.compiler.edition(),
		Deps:           make([]rustProjectDep, 0),
		Cfg:            make([]string, 0),
		Env:            make(map[string]string),
		ProcMacro:      procMacroDylib != nil,
		ProcMacroDylib: procMacroDylib,
	}

	if rModule.compiler.cargoOutDir().Valid() {
		crate.Env["OUT_DIR"] = rModule.compiler.cargoOutDir().String()
	}

	for _, feature := range rModule.compiler.features(ctx, rModule) {
		crate.Cfg = append(crate.Cfg, "feature=\""+feature+"\"")
	}

	singleton.mergeDependencies(ctx, rModule, &crate, deps)

	var idx int
	if cInfo, ok := singleton.knownCrates[rModule.Name()]; ok {
		idx = cInfo.Idx
		singleton.project.Crates[idx] = crate
	} else {
		idx = len(singleton.project.Crates)
		singleton.project.Crates = append(singleton.project.Crates, crate)
	}
	singleton.knownCrates[rModule.Name()] = crateInfo{Idx: idx, Deps: deps, Device: rModule.Device()}
	return idx, true
}

// appendCrateAndDependencies creates a rustProjectCrate for the module argument and appends it to singleton.project.
// It visits the dependencies of the module depth-first so the dependency ID can be added to the current module. If the
// current module is already in singleton.knownCrates, its dependencies are merged.
func (singleton *projectGeneratorSingleton) appendCrateAndDependencies(ctx android.SingletonContext, module android.Module) {
	rModule, ok := isModuleSupported(ctx, module)
	if !ok {
		return
	}
	// If we have seen this crate already; merge any new dependencies.
	if cInfo, ok := singleton.knownCrates[module.Name()]; ok {
		// If we have a new device variant, override the old one
		if !cInfo.Device && rModule.Device() {
			singleton.addCrate(ctx, rModule)
			return
		}
		crate := singleton.project.Crates[cInfo.Idx]
		singleton.mergeDependencies(ctx, rModule, &crate, cInfo.Deps)
		singleton.project.Crates[cInfo.Idx] = crate
		return
	}
	singleton.addCrate(ctx, rModule)
}

func (singleton *projectGeneratorSingleton) GenerateBuildActions(ctx android.SingletonContext) {
	if !ctx.Config().IsEnvTrue(envVariableCollectRustDeps) {
		return
	}

	singleton.project.Sysroot = config.RustPath(ctx)

	singleton.knownCrates = make(map[string]crateInfo)
	ctx.VisitAllModules(func(module android.Module) {
		singleton.appendCrateAndDependencies(ctx, module)
	})

	path := android.PathForOutput(ctx, rustProjectJsonFileName)
	err := createJsonFile(singleton.project, path)
	if err != nil {
		ctx.Errorf(err.Error())
	}
}

func createJsonFile(project rustProjectJson, rustProjectPath android.WritablePath) error {
	buf, err := json.MarshalIndent(project, "", "  ")
	if err != nil {
		return fmt.Errorf("JSON marshal of rustProjectJson failed: %s", err)
	}
	err = android.WriteFileToOutputDir(rustProjectPath, buf, 0666)
	if err != nil {
		return fmt.Errorf("Writing rust-project to %s failed: %s", rustProjectPath.String(), err)
	}
	return nil
}
