// 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 (
	"fmt"
	"strings"

	mkparser "android/soong/androidmk/parser"
)

// A parsed node for which starlark code will be generated
// by calling emit().
type starlarkNode interface {
	emit(ctx *generationContext)
}

// Types used to keep processed makefile data:
type commentNode struct {
	text string
}

func (c *commentNode) emit(gctx *generationContext) {
	chunks := strings.Split(c.text, "\\\n")
	gctx.newLine()
	gctx.write(chunks[0]) // It has '#' at the beginning already.
	for _, chunk := range chunks[1:] {
		gctx.newLine()
		gctx.write("#", chunk)
	}
}

type moduleInfo struct {
	path            string // Converted Starlark file path
	originalPath    string // Makefile file path
	moduleLocalName string
	optional        bool
	missing         bool // a module may not exist if a module that depends on it is loaded dynamically
}

func (im moduleInfo) entryName() string {
	return im.moduleLocalName + "_init"
}

func (mi moduleInfo) name() string {
	return fmt.Sprintf("%q", MakePath2ModuleName(mi.originalPath))
}

type inheritedModule interface {
	name() string
	entryName() string
	emitSelect(gctx *generationContext)
	pathExpr() starlarkExpr
	needsLoadCheck() bool
}

type inheritedStaticModule struct {
	*moduleInfo
	loadAlways bool
}

func (im inheritedStaticModule) emitSelect(_ *generationContext) {
}

func (im inheritedStaticModule) pathExpr() starlarkExpr {
	return &stringLiteralExpr{im.path}
}

func (im inheritedStaticModule) needsLoadCheck() bool {
	return im.missing
}

type inheritedDynamicModule struct {
	path             interpolateExpr
	candidateModules []*moduleInfo
	loadAlways       bool
	location         ErrorLocation
	needsWarning     bool
}

func (i inheritedDynamicModule) name() string {
	return "_varmod"
}

func (i inheritedDynamicModule) entryName() string {
	return i.name() + "_init"
}

func (i inheritedDynamicModule) emitSelect(gctx *generationContext) {
	if i.needsWarning {
		gctx.newLine()
		gctx.writef("%s.mkwarning(%q, %q)", baseName, i.location, "Including a path with a non-constant prefix, please convert this to a simple literal to generate cleaner starlark. See https://source.android.com/setup/build/bazel/product_config/issues/includes for details.")
	}
	gctx.newLine()
	gctx.writef("_entry = {")
	gctx.indentLevel++
	for _, mi := range i.candidateModules {
		gctx.newLine()
		gctx.writef(`"%s": (%s, %s),`, mi.originalPath, mi.name(), mi.entryName())
	}
	gctx.indentLevel--
	gctx.newLine()
	gctx.write("}.get(")
	i.path.emit(gctx)
	gctx.write(")")
	gctx.newLine()
	gctx.writef("(%s, %s) = _entry if _entry else (None, None)", i.name(), i.entryName())
}

func (i inheritedDynamicModule) pathExpr() starlarkExpr {
	return &i.path
}

func (i inheritedDynamicModule) needsLoadCheck() bool {
	return true
}

type inheritNode struct {
	module     inheritedModule
	loadAlways bool
}

func (inn *inheritNode) emit(gctx *generationContext) {
	// Unconditional case:
	//    maybe check that loaded
	//    rblf.inherit(handle, <module>, module_init)
	// Conditional case:
	//    if <module>_init != None:
	//      same as above
	inn.module.emitSelect(gctx)
	name := inn.module.name()
	entry := inn.module.entryName()
	if inn.loadAlways {
		gctx.emitLoadCheck(inn.module)
		gctx.newLine()
		gctx.writef("%s(handle, %s, %s)", cfnInherit, name, entry)
		return
	}

	gctx.newLine()
	gctx.writef("if %s:", entry)
	gctx.indentLevel++
	gctx.newLine()
	gctx.writef("%s(handle, %s, %s)", cfnInherit, name, entry)
	gctx.indentLevel--
}

type includeNode struct {
	module     inheritedModule
	loadAlways bool
}

func (inn *includeNode) emit(gctx *generationContext) {
	inn.module.emitSelect(gctx)
	entry := inn.module.entryName()
	if inn.loadAlways {
		gctx.emitLoadCheck(inn.module)
		gctx.newLine()
		gctx.writef("%s(g, handle)", entry)
		return
	}

	gctx.newLine()
	gctx.writef("if %s != None:", entry)
	gctx.indentLevel++
	gctx.newLine()
	gctx.writef("%s(g, handle)", entry)
	gctx.indentLevel--
}

type assignmentFlavor int

const (
	// Assignment flavors
	asgnSet         assignmentFlavor = iota // := or =
	asgnMaybeSet    assignmentFlavor = iota // ?= and variable may be unset
	asgnAppend      assignmentFlavor = iota // += and variable has been set before
	asgnMaybeAppend assignmentFlavor = iota // += and variable may be unset
)

type assignmentNode struct {
	lhs      variable
	value    starlarkExpr
	mkValue  *mkparser.MakeString
	flavor   assignmentFlavor
	location ErrorLocation
	isTraced bool
	previous *assignmentNode
}

func (asgn *assignmentNode) emit(gctx *generationContext) {
	gctx.newLine()
	gctx.inAssignment = true
	asgn.lhs.emitSet(gctx, asgn)
	gctx.inAssignment = false

	if asgn.isTraced {
		gctx.newLine()
		gctx.tracedCount++
		gctx.writef(`print("%s.%d: %s := ", `, gctx.starScript.mkFile, gctx.tracedCount, asgn.lhs.name())
		asgn.lhs.emitGet(gctx, true)
		gctx.writef(")")
	}
}

type exprNode struct {
	expr starlarkExpr
}

func (exn *exprNode) emit(gctx *generationContext) {
	gctx.newLine()
	exn.expr.emit(gctx)
}

type ifNode struct {
	isElif bool // true if this is 'elif' statement
	expr   starlarkExpr
}

func (in *ifNode) emit(gctx *generationContext) {
	ifElif := "if "
	if in.isElif {
		ifElif = "elif "
	}

	gctx.newLine()
	gctx.write(ifElif)
	in.expr.emit(gctx)
	gctx.write(":")
}

type elseNode struct{}

func (br *elseNode) emit(gctx *generationContext) {
	gctx.newLine()
	gctx.write("else:")
}

// switchCase represents as single if/elseif/else branch. All the necessary
// info about flavor (if/elseif/else) is supposed to be kept in `gate`.
type switchCase struct {
	gate  starlarkNode
	nodes []starlarkNode
}

func (cb *switchCase) emit(gctx *generationContext) {
	cb.gate.emit(gctx)
	gctx.indentLevel++
	hasStatements := false
	for _, node := range cb.nodes {
		if _, ok := node.(*commentNode); !ok {
			hasStatements = true
		}
		node.emit(gctx)
	}
	if !hasStatements {
		gctx.emitPass()
	}
	gctx.indentLevel--
}

// A single complete if ... elseif ... else ... endif sequences
type switchNode struct {
	ssCases []*switchCase
}

func (ssw *switchNode) emit(gctx *generationContext) {
	for _, ssCase := range ssw.ssCases {
		ssCase.emit(gctx)
	}
}
