// Copyright 2021 Google LLC
//
// 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 mk2rbc

import (
	"bytes"
	"fmt"
	"io/ioutil"
	"os"
	"regexp"
	"strings"

	mkparser "android/soong/androidmk/parser"
)

type context struct {
	includeFileScope mkparser.Scope
	registrar        variableRegistrar
}

// Scans the makefile Soong uses to generate soong.variables file,
// collecting variable names and types from the lines that look like this:
//
//	$(call add_json_XXX,  <...>,             $(VAR))
func FindSoongVariables(mkFile string, includeFileScope mkparser.Scope, registrar variableRegistrar) error {
	ctx := context{includeFileScope, registrar}
	return ctx.doFind(mkFile)
}

func (ctx *context) doFind(mkFile string) error {
	mkContents, err := ioutil.ReadFile(mkFile)
	if err != nil {
		return err
	}
	parser := mkparser.NewParser(mkFile, bytes.NewBuffer(mkContents))
	nodes, errs := parser.Parse()
	if len(errs) > 0 {
		for _, e := range errs {
			fmt.Fprintln(os.Stderr, "ERROR:", e)
		}
		return fmt.Errorf("cannot parse %s", mkFile)
	}
	for _, node := range nodes {
		switch t := node.(type) {
		case *mkparser.Variable:
			ctx.handleVariable(t)
		case *mkparser.Directive:
			ctx.handleInclude(t)
		}
	}
	return nil
}

func (ctx context) NewSoongVariable(name, typeString string) {
	var valueType starlarkType
	switch typeString {
	case "bool":
		// TODO: We run into several issues later on if we type this as a bool:
		//    - We still assign bool-typed variables to strings
		//    - When emitting the final results as make code, some bool's false values have to
		//      be an empty string, and some have to be false in order to match the make variables.
		valueType = starlarkTypeString
	case "csv":
		// Only PLATFORM_VERSION_ALL_CODENAMES, and it's a list
		valueType = starlarkTypeList
	case "list":
		valueType = starlarkTypeList
	case "str":
		valueType = starlarkTypeString
	case "val":
		// Only PLATFORM_SDK_VERSION uses this, and it's integer
		valueType = starlarkTypeInt
	default:
		panic(fmt.Errorf("unknown Soong variable type %s", typeString))
	}

	ctx.registrar.NewVariable(name, VarClassSoong, valueType)
}

func (ctx context) handleInclude(t *mkparser.Directive) {
	if t.Name != "include" && t.Name != "-include" {
		return
	}
	includedPath := t.Args.Value(ctx.includeFileScope)
	err := ctx.doFind(includedPath)
	if err != nil && t.Name == "include" {
		fmt.Fprintf(os.Stderr, "cannot include %s: %s", includedPath, err)
	}
}

var callFuncRex = regexp.MustCompile("^call +add_json_(str|val|bool|csv|list) *,")

func (ctx context) handleVariable(t *mkparser.Variable) {
	// From the variable reference looking as follows:
	//  $(call json_add_TYPE,arg1,$(VAR))
	// we infer that the type of $(VAR) is TYPE
	// VAR can be a simple variable name, or another call
	// (e.g., $(call invert_bool, $(X)), from which we can infer
	// that the type of X is bool
	if prefix, v, ok := prefixedVariable(t.Name); ok && strings.HasPrefix(prefix, "call add_json") {
		if match := callFuncRex.FindStringSubmatch(prefix); match != nil {
			ctx.inferSoongVariableType(match[1], v)
			// NOTE(asmundak): sometimes arg1 (the name of the Soong variable defined
			// in this statement) may indicate that there is a Make counterpart. E.g, from
			//     $(call add_json_bool, DisablePreopt, $(call invert_bool,$(ENABLE_PREOPT)))
			// it may be inferred that there is a Make boolean variable DISABLE_PREOPT.
			// Unfortunately, Soong variable names have no 1:1 correspondence to Make variables,
			// for instance,
			//       $(call add_json_list, PatternsOnSystemOther, $(SYSTEM_OTHER_ODEX_FILTER))
			// does not mean that there is PATTERNS_ON_SYSTEM_OTHER
			// Our main interest lies in finding the variables whose values are lists, and
			// so far there are none that can be found this way, so it is not important.
		} else {
			panic(fmt.Errorf("cannot match the call: %s", prefix))
		}
	}
}

var (
	callInvertBoolRex = regexp.MustCompile("^call +invert_bool *, *$")
	callFilterBoolRex = regexp.MustCompile("^(filter|filter-out) +(true|false), *$")
)

func (ctx context) inferSoongVariableType(vType string, n *mkparser.MakeString) {
	if n.Const() {
		ctx.NewSoongVariable(n.Strings[0], vType)
		return
	}
	if prefix, v, ok := prefixedVariable(n); ok {
		if callInvertBoolRex.MatchString(prefix) || callFilterBoolRex.MatchString(prefix) {
			// It is $(call invert_bool, $(VAR)) or $(filter[-out] [false|true],$(VAR))
			ctx.inferSoongVariableType("bool", v)
		}
	}
}

// If MakeString is foo$(BAR), returns 'foo', BAR(as *MakeString) and true
func prefixedVariable(s *mkparser.MakeString) (string, *mkparser.MakeString, bool) {
	if len(s.Strings) != 2 || s.Strings[1] != "" {
		return "", nil, false
	}
	return s.Strings[0], s.Variables[0].Name, true
}
