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

// This file contains the module implementation for android_app_set.

import (
	"strconv"
	"strings"

	"github.com/google/blueprint/proptools"

	"android/soong/android"
)

func init() {
	RegisterAppSetBuildComponents(android.InitRegistrationContext)
}

func RegisterAppSetBuildComponents(ctx android.RegistrationContext) {
	ctx.RegisterModuleType("android_app_set", AndroidAppSetFactory)
}

type AndroidAppSetProperties struct {
	// APK Set path
	Set *string

	// Specifies that this app should be installed to the priv-app directory,
	// where the system will grant it additional privileges not available to
	// normal apps.
	Privileged *bool

	// APKs in this set use prerelease SDK version
	Prerelease *bool

	// Names of modules to be overridden. Listed modules can only be other apps
	//	(in Make or Soong).
	Overrides []string

	// Path to the .prebuilt_info file of the prebuilt app.
	// In case of mainline modules, the .prebuilt_info file contains the build_id that was used
	// to generate the prebuilt.
	Prebuilt_info *string `android:"path"`
}

type AndroidAppSet struct {
	android.ModuleBase
	android.DefaultableModuleBase
	prebuilt android.Prebuilt

	properties    AndroidAppSetProperties
	packedOutput  android.WritablePath
	primaryOutput android.WritablePath
	apkcertsFile  android.ModuleOutPath
}

func (as *AndroidAppSet) Name() string {
	return as.prebuilt.Name(as.ModuleBase.Name())
}

func (as *AndroidAppSet) IsInstallable() bool {
	return true
}

func (as *AndroidAppSet) Prebuilt() *android.Prebuilt {
	return &as.prebuilt
}

func (as *AndroidAppSet) Privileged() bool {
	return Bool(as.properties.Privileged)
}

func (as *AndroidAppSet) OutputFile() android.Path {
	return as.primaryOutput
}

func (as *AndroidAppSet) PackedAdditionalOutputs() android.Path {
	return as.packedOutput
}

func (as *AndroidAppSet) APKCertsFile() android.Path {
	return as.apkcertsFile
}

var TargetCpuAbi = map[string]string{
	"arm":   "ARMEABI_V7A",
	"arm64": "ARM64_V8A",
	// TODO: use "RISCV64" when that is supported in bundles
	"riscv64": "ARM64_V8A",
	"x86":     "X86",
	"x86_64":  "X86_64",
}

func SupportedAbis(ctx android.ModuleContext, excludeNativeBridgeAbis bool) []string {
	abiName := func(targetIdx int, deviceArch string) string {
		if abi, found := TargetCpuAbi[deviceArch]; found {
			return abi
		}
		ctx.ModuleErrorf("Target %d has invalid Arch: %s", targetIdx, deviceArch)
		return "BAD_ABI"
	}

	var result []string
	for i, target := range ctx.Config().Targets[android.Android] {
		if target.NativeBridge == android.NativeBridgeEnabled && excludeNativeBridgeAbis {
			continue
		}
		result = append(result, abiName(i, target.Arch.ArchType.String()))
	}
	return result
}

type prebuiltInfoProps struct {
	baseModuleName string
	isPrebuilt     bool
	prebuiltInfo   *string
}

// Set prebuiltInfoProvider. This will be used by `apex_prebuiltinfo_singleton` to print out a metadata file
// with information about whether source or prebuilt of an apex was used during the build.
func providePrebuiltInfo(ctx android.ModuleContext, p prebuiltInfoProps) {
	info := android.PrebuiltInfo{
		Name:        p.baseModuleName,
		Is_prebuilt: p.isPrebuilt,
	}
	// If Prebuilt_info information is available in the soong module definition, add it to prebuilt_info.json.
	if p.prebuiltInfo != nil {
		prebuiltInfoFile := android.PathForModuleSrc(ctx, *p.prebuiltInfo)
		info.Prebuilt_info_file_path = prebuiltInfoFile.String()
	}
	android.SetProvider(ctx, android.PrebuiltInfoProvider, info)
}

func (as *AndroidAppSet) GenerateAndroidBuildActions(ctx android.ModuleContext) {
	as.packedOutput = android.PathForModuleOut(ctx, ctx.ModuleName()+".zip")
	as.primaryOutput = android.PathForModuleOut(ctx, as.BaseModuleName()+".apk")
	as.apkcertsFile = android.PathForModuleOut(ctx, "apkcerts.txt")
	// We are assuming here that the install file in the APK
	// set has `.apk` suffix. If it doesn't the build will fail.
	// APK sets containing APEX files are handled elsewhere.
	screenDensities := "all"
	if dpis := ctx.Config().ProductAAPTPrebuiltDPI(); len(dpis) > 0 {
		screenDensities = strings.ToUpper(strings.Join(dpis, ","))
	}
	// TODO(asmundak): handle locales.
	// TODO(asmundak): do we support device features
	ctx.Build(pctx,
		android.BuildParams{
			Rule:            extractMatchingApks,
			Description:     "Extract APKs from APK set",
			Output:          as.primaryOutput,
			ImplicitOutputs: android.WritablePaths{as.packedOutput, as.apkcertsFile},
			Inputs:          android.Paths{as.prebuilt.SingleSourcePath(ctx)},
			Args: map[string]string{
				"abis":              strings.Join(SupportedAbis(ctx, false), ","),
				"allow-prereleased": strconv.FormatBool(proptools.Bool(as.properties.Prerelease)),
				"screen-densities":  screenDensities,
				"sdk-version":       ctx.Config().PlatformSdkVersion().String(),
				"skip-sdk-check":    strconv.FormatBool(ctx.Config().IsEnvTrue("SOONG_SKIP_APPSET_SDK_CHECK")),
				"stem":              as.BaseModuleName(),
				"apkcerts":          as.apkcertsFile.String(),
				"partition":         as.PartitionTag(ctx.DeviceConfig()),
				"zip":               as.packedOutput.String(),
			},
		})

	var installDir android.InstallPath
	if as.Privileged() {
		installDir = android.PathForModuleInstall(ctx, "priv-app", as.BaseModuleName())
	} else {
		installDir = android.PathForModuleInstall(ctx, "app", as.BaseModuleName())
	}
	ctx.InstallFileWithExtraFilesZip(installDir, as.BaseModuleName()+".apk", as.primaryOutput, as.packedOutput)

	providePrebuiltInfo(ctx,
		prebuiltInfoProps{
			baseModuleName: as.BaseModuleName(),
			isPrebuilt:     true,
			prebuiltInfo:   as.properties.Prebuilt_info,
		},
	)

}

func (as *AndroidAppSet) InstallBypassMake() bool { return true }

// android_app_set extracts a set of APKs based on the target device
// configuration and installs this set as "split APKs".
// The extracted set always contains an APK whose name is
// _module_name_.apk and every split APK matching target device.
// The extraction of the density-specific splits depends on
// PRODUCT_AAPT_PREBUILT_DPI variable. If present (its value should
// be a list density names: LDPI, MDPI, HDPI, etc.), only listed
// splits will be extracted. Otherwise all density-specific splits
// will be extracted.
func AndroidAppSetFactory() android.Module {
	module := &AndroidAppSet{}
	module.AddProperties(&module.properties)
	InitJavaModule(module, android.DeviceSupported)
	android.InitSingleSourcePrebuiltModule(module, &module.properties, "Set")
	return module
}
