// Copyright (C) 2016 The Android Open Source Project
//
// 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 art

// This file implements the "codegen" property to apply different properties based on the currently
// selected codegen arches, which defaults to all arches on the host and the primary and secondary
// arches on the device.

import (
	"sort"
	"strings"

	"android/soong/android"
)

type moduleType struct {
	library bool
	static  bool
	shared  bool
}

var (
	staticLibrary          = moduleType{true, true, false}
	sharedLibrary          = moduleType{true, false, true}
	staticAndSharedLibrary = moduleType{true, true, true}
	binary                 = moduleType{false, false, false}
)

func codegen(ctx android.LoadHookContext, c *codegenProperties, t moduleType) {
	var hostArches, deviceArches []string

	e := ctx.Config().Getenv("ART_HOST_CODEGEN_ARCHS")
	if e == "" {
		hostArches = supportedArches
	} else {
		hostArches = strings.Split(e, " ")
	}

	e = ctx.Config().Getenv("ART_TARGET_CODEGEN_ARCHS")
	if e == "" {
		deviceArches = defaultDeviceCodegenArches(ctx)
	} else {
		deviceArches = strings.Split(e, " ")
	}

	getCodegenArchProperties := func(archName string) *codegenArchProperties {
		var arch *codegenArchProperties
		switch archName {
		case "arm":
			arch = &c.Codegen.Arm
		case "arm64":
			arch = &c.Codegen.Arm64
		case "riscv64":
			arch = &c.Codegen.Riscv64
		case "x86":
			arch = &c.Codegen.X86
		case "x86_64":
			arch = &c.Codegen.X86_64
		default:
			ctx.ModuleErrorf("Unknown codegen architecture %q", archName)
		}
		return arch
	}

	appendCodegenSourceArchProperties := func(p *CodegenSourceArchProperties, archName string) {
		arch := getCodegenArchProperties(archName)
		p.Srcs = append(p.Srcs, arch.CodegenSourceArchProperties.Srcs...)
	}

	addCodegenSourceArchProperties := func(host bool, p *CodegenSourceArchProperties) {
		type sourceProps struct {
			Target struct {
				Android *CodegenSourceArchProperties
				Host    *CodegenSourceArchProperties
			}
		}

		sp := &sourceProps{}
		if host {
			sp.Target.Host = p
		} else {
			sp.Target.Android = p
		}
		ctx.AppendProperties(sp)
	}

	addCodegenArchProperties := func(host bool, archName string) {
		type commonProps struct {
			Target struct {
				Android *CodegenCommonArchProperties
				Host    *CodegenCommonArchProperties
			}
		}

		type libraryProps struct {
			Target struct {
				Android *CodegenLibraryArchProperties
				Host    *CodegenLibraryArchProperties
			}
		}

		type sharedLibraryProps struct {
			Target struct {
				Android *CodegenLibraryArchSharedProperties
				Host    *CodegenLibraryArchSharedProperties
			}
		}

		type staticLibraryProps struct {
			Target struct {
				Android *CodegenLibraryArchStaticProperties
				Host    *CodegenLibraryArchStaticProperties
			}
		}

		arch := getCodegenArchProperties(archName)

		cp := &commonProps{}
		lp := &libraryProps{}
		sharedLP := &sharedLibraryProps{}
		staticLP := &staticLibraryProps{}
		if host {
			cp.Target.Host = &arch.CodegenCommonArchProperties
			lp.Target.Host = &arch.CodegenLibraryArchProperties
			sharedLP.Target.Host = &arch.CodegenLibraryArchSharedProperties
			staticLP.Target.Host = &arch.CodegenLibraryArchStaticProperties
		} else {
			cp.Target.Android = &arch.CodegenCommonArchProperties
			lp.Target.Android = &arch.CodegenLibraryArchProperties
			sharedLP.Target.Android = &arch.CodegenLibraryArchSharedProperties
			staticLP.Target.Android = &arch.CodegenLibraryArchStaticProperties
		}

		ctx.AppendProperties(cp)
		if t.library {
			ctx.AppendProperties(lp)
			if t.static {
				ctx.AppendProperties(staticLP)
			}
			if t.shared {
				ctx.AppendProperties(sharedLP)
			}
		}
	}

	addCodegenProperties := func(host bool, arches []string) {
		sourceProps := &CodegenSourceArchProperties{}
		for _, arch := range arches {
			appendCodegenSourceArchProperties(sourceProps, arch)
			addCodegenArchProperties(host, arch)
		}
		sourceProps.Srcs = android.FirstUniqueStrings(sourceProps.Srcs)
		addCodegenSourceArchProperties(host, sourceProps)
	}

	addCodegenProperties(false /* host */, deviceArches)
	addCodegenProperties(true /* host */, hostArches)
}

// These properties are allowed to contain the same source file name in different architectures.
// They we will be deduplicated automatically.
type CodegenSourceArchProperties struct {
	Srcs []string
}

type CodegenCommonArchProperties struct {
	Cflags   []string
	Cppflags []string
}

type CodegenLibraryArchProperties struct {
	Static_libs               []string
	Export_static_lib_headers []string
}

type CodegenLibraryArchStaticProperties struct {
	Static struct {
		Whole_static_libs []string
	}
}
type CodegenLibraryArchSharedProperties struct {
	Shared struct {
		Shared_libs               []string
		Export_shared_lib_headers []string
	}
}

type codegenArchProperties struct {
	CodegenSourceArchProperties
	CodegenCommonArchProperties
	CodegenLibraryArchProperties
	CodegenLibraryArchStaticProperties
	CodegenLibraryArchSharedProperties
}

type codegenProperties struct {
	Codegen struct {
		Arm, Arm64, Riscv64, X86, X86_64 codegenArchProperties
	}
}

func defaultDeviceCodegenArches(ctx android.LoadHookContext) []string {
	arches := make(map[string]bool)
	for _, a := range ctx.DeviceConfig().Arches() {
		s := a.ArchType.String()
		arches[s] = true
		if s == "arm64" {
			arches["arm"] = true
		} else if s == "riscv64" {
			arches["riscv64"] = true
		} else if s == "x86_64" {
			arches["x86"] = true
		}
	}
	ret := make([]string, 0, len(arches))
	for a := range arches {
		ret = append(ret, a)
	}
	sort.Strings(ret)
	return ret
}

func installCodegenCustomizer(module android.Module, t moduleType) {
	c := &codegenProperties{}
	android.AddLoadHook(module, func(ctx android.LoadHookContext) { codegen(ctx, c, t) })
	module.AddProperties(c)
}
