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

import (
	"android/soong/android"
	"fmt"
	"reflect"
	"runtime"
	"sort"
	"strings"

	"github.com/google/blueprint/proptools"
)

var (
	// An allowlist of prop types that are surfaced from module props to rule
	// attributes. (nested) dictionaries are notably absent here, because while
	// Soong supports multi value typed and nested dictionaries, Bazel's rule
	// attr() API supports only single-level string_dicts.
	allowedPropTypes = map[string]bool{
		"int":         true, // e.g. 42
		"bool":        true, // e.g. True
		"string_list": true, // e.g. ["a", "b"]
		"string":      true, // e.g. "a"
	}
)

type rule struct {
	name  string
	attrs string
}

type RuleShim struct {
	// The rule class shims contained in a bzl file. e.g. ["cc_object", "cc_library", ..]
	rules []string

	// The generated string content of the bzl file.
	content string
}

// Create <module>.bzl containing Bazel rule shims for every module type available in Soong and
// user-specified Go plugins.
//
// This function reuses documentation generation APIs to ensure parity between modules-as-docs
// and modules-as-code, including the names and types of morule properties.
func CreateRuleShims(moduleTypeFactories map[string]android.ModuleFactory) map[string]RuleShim {
	ruleShims := map[string]RuleShim{}
	for pkg, rules := range generateRules(moduleTypeFactories) {
		shim := RuleShim{
			rules: make([]string, 0, len(rules)),
		}
		shim.content = "load(\"//build/bazel/queryview_rules:providers.bzl\", \"SoongModuleInfo\")\n"

		bzlFileName := strings.ReplaceAll(pkg, "android/soong/", "")
		bzlFileName = strings.ReplaceAll(bzlFileName, ".", "_")
		bzlFileName = strings.ReplaceAll(bzlFileName, "/", "_")

		for _, r := range rules {
			shim.content += fmt.Sprintf(moduleRuleShim, r.name, r.attrs)
			shim.rules = append(shim.rules, r.name)
		}
		sort.Strings(shim.rules)
		ruleShims[bzlFileName] = shim
	}
	return ruleShims
}

// Generate the content of soong_module.bzl with the rule shim load statements
// and mapping of module_type to rule shim map for every module type in Soong.
func generateSoongModuleBzl(bzlLoads map[string]RuleShim) string {
	var loadStmts string
	var moduleRuleMap string
	for _, bzlFileName := range android.SortedKeys(bzlLoads) {
		loadStmt := "load(\"//build/bazel/queryview_rules:"
		loadStmt += bzlFileName
		loadStmt += ".bzl\""
		ruleShim := bzlLoads[bzlFileName]
		for _, rule := range ruleShim.rules {
			loadStmt += fmt.Sprintf(", %q", rule)
			moduleRuleMap += "    \"" + rule + "\": " + rule + ",\n"
		}
		loadStmt += ")\n"
		loadStmts += loadStmt
	}

	return fmt.Sprintf(soongModuleBzl, loadStmts, moduleRuleMap)
}

func generateRules(moduleTypeFactories map[string]android.ModuleFactory) map[string][]rule {
	// TODO: add shims for bootstrap/blueprint go modules types

	rules := make(map[string][]rule)
	// TODO: allow registration of a bzl rule when registring a factory
	for _, moduleType := range android.SortedKeys(moduleTypeFactories) {
		factory := moduleTypeFactories[moduleType]
		factoryName := runtime.FuncForPC(reflect.ValueOf(factory).Pointer()).Name()
		pkg := strings.Split(factoryName, ".")[0]
		attrs := `{
        "soong_module_name": attr.string(mandatory = True),
        "soong_module_variant": attr.string(),
        "soong_module_deps": attr.label_list(providers = [SoongModuleInfo]),
`
		attrs += getAttributes(factory)
		attrs += "    },"

		r := rule{
			name:  canonicalizeModuleType(moduleType),
			attrs: attrs,
		}

		rules[pkg] = append(rules[pkg], r)
	}
	return rules
}

type property struct {
	name             string
	starlarkAttrType string
	properties       []property
}

const (
	attributeIndent = "        "
)

func (p *property) attributeString() string {
	if !shouldGenerateAttribute(p.name) {
		return ""
	}

	if _, ok := allowedPropTypes[p.starlarkAttrType]; !ok {
		// a struct -- let's just comment out sub-props
		s := fmt.Sprintf(attributeIndent+"# %s start\n", p.name)
		for _, nestedP := range p.properties {
			s += "# " + nestedP.attributeString()
		}
		s += fmt.Sprintf(attributeIndent+"# %s end\n", p.name)
		return s
	}
	return fmt.Sprintf(attributeIndent+"%q: attr.%s(),\n", p.name, p.starlarkAttrType)
}

func extractPropertyDescriptionsFromStruct(structType reflect.Type) []property {
	properties := make([]property, 0)
	for i := 0; i < structType.NumField(); i++ {
		field := structType.Field(i)
		if shouldSkipStructField(field) {
			continue
		}
		subProps := extractPropertyDescriptions(field.Name, field.Type)
		// if the struct is embedded (anonymous), flatten the properties into the containing struct
		if field.Anonymous {
			for _, prop := range subProps {
				properties = append(properties, prop.properties...)
			}
		} else {
			properties = append(properties, subProps...)
		}
	}
	return properties
}

func extractPropertyDescriptions(name string, t reflect.Type) []property {
	name = proptools.PropertyNameForField(name)

	// TODO: handle android:paths tags, they should be changed to label types

	starlarkAttrType := fmt.Sprintf("%s", t.Name())
	props := make([]property, 0)

	switch t.Kind() {
	case reflect.Bool, reflect.String:
		// do nothing
	case reflect.Uint, reflect.Int, reflect.Int64:
		starlarkAttrType = "int"
	case reflect.Slice:
		if t.Elem().Kind() != reflect.String {
			// TODO: handle lists of non-strings (currently only list of Dist)
			return []property{}
		}
		starlarkAttrType = "string_list"
	case reflect.Struct:
		props = extractPropertyDescriptionsFromStruct(t)
	case reflect.Ptr:
		return extractPropertyDescriptions(name, t.Elem())
	case reflect.Interface:
		// Interfaces are used for for arch, multilib and target properties, which are handled at runtime.
		// These will need to be handled in a bazel-specific version of the arch mutator.
		return []property{}
	}

	prop := property{
		name:             name,
		starlarkAttrType: starlarkAttrType,
		properties:       props,
	}

	return []property{prop}
}

func getPropertyDescriptions(props []interface{}) []property {
	// there may be duplicate properties, e.g. from defaults libraries
	propertiesByName := make(map[string]property)
	for _, p := range props {
		for _, prop := range extractPropertyDescriptionsFromStruct(reflect.ValueOf(p).Elem().Type()) {
			propertiesByName[prop.name] = prop
		}
	}

	properties := make([]property, 0, len(propertiesByName))
	for _, key := range android.SortedKeys(propertiesByName) {
		properties = append(properties, propertiesByName[key])
	}

	return properties
}

func getAttributes(factory android.ModuleFactory) string {
	attrs := ""
	for _, p := range getPropertyDescriptions(factory().GetProperties()) {
		attrs += p.attributeString()
	}
	return attrs
}
