// Copyright 2015 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 types for compiling Android apps.

import (
	"strings"

	"github.com/google/blueprint/proptools"

	"android/soong/android"
)

func init() {
	android.RegisterModuleType("android_app", AndroidAppFactory)
	android.RegisterModuleType("android_test", AndroidTestFactory)
}

// AndroidManifest.xml merging
// package splits

type appProperties struct {
	// path to a certificate, or the name of a certificate in the default
	// certificate directory, or blank to use the default product certificate
	Certificate *string

	// paths to extra certificates to sign the apk with
	Additional_certificates []string

	// If set, create package-export.apk, which other packages can
	// use to get PRODUCT-agnostic resource data like IDs and type definitions.
	Export_package_resources *bool

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

	// list of resource labels to generate individual resource packages
	Package_splits []string
}

type AndroidApp struct {
	Library
	aapt

	certificate certificate

	appProperties appProperties

	extraLinkFlags []string
}

func (a *AndroidApp) ExportedProguardFlagFiles() android.Paths {
	return nil
}

func (a *AndroidApp) ExportedStaticPackages() android.Paths {
	return nil
}

var _ AndroidLibraryDependency = (*AndroidApp)(nil)

type certificate struct {
	pem, key android.Path
}

func (a *AndroidApp) DepsMutator(ctx android.BottomUpMutatorContext) {
	a.Module.deps(ctx)
	if !Bool(a.properties.No_framework_libs) && !Bool(a.properties.No_standard_libs) {
		a.aapt.deps(ctx, String(a.deviceProperties.Sdk_version))
	}
}

func (a *AndroidApp) GenerateAndroidBuildActions(ctx android.ModuleContext) {
	a.generateAndroidBuildActions(ctx)
}

func (a *AndroidApp) generateAndroidBuildActions(ctx android.ModuleContext) {
	linkFlags := append([]string(nil), a.extraLinkFlags...)

	hasProduct := false
	for _, f := range a.aaptProperties.Aaptflags {
		if strings.HasPrefix(f, "--product") {
			hasProduct = true
		}
	}

	// Product characteristics
	if !hasProduct && len(ctx.Config().ProductAAPTCharacteristics()) > 0 {
		linkFlags = append(linkFlags, "--product", ctx.Config().ProductAAPTCharacteristics())
	}

	// Product AAPT config
	for _, aaptConfig := range ctx.Config().ProductAAPTConfig() {
		linkFlags = append(linkFlags, "-c", aaptConfig)
	}

	// Product AAPT preferred config
	if len(ctx.Config().ProductAAPTPreferredConfig()) > 0 {
		linkFlags = append(linkFlags, "--preferred-density", ctx.Config().ProductAAPTPreferredConfig())
	}

	// TODO: LOCAL_PACKAGE_OVERRIDES
	//    $(addprefix --rename-manifest-package , $(PRIVATE_MANIFEST_PACKAGE_NAME)) \

	a.aapt.buildActions(ctx, String(a.deviceProperties.Sdk_version), linkFlags...)

	// apps manifests are handled by aapt, don't let Module see them
	a.properties.Manifest = nil

	var staticLibProguardFlagFiles android.Paths
	ctx.VisitDirectDeps(func(m android.Module) {
		if lib, ok := m.(AndroidLibraryDependency); ok && ctx.OtherModuleDependencyTag(m) == staticLibTag {
			staticLibProguardFlagFiles = append(staticLibProguardFlagFiles, lib.ExportedProguardFlagFiles()...)
		}
	})

	staticLibProguardFlagFiles = android.FirstUniquePaths(staticLibProguardFlagFiles)

	a.Module.extraProguardFlagFiles = append(a.Module.extraProguardFlagFiles, staticLibProguardFlagFiles...)
	a.Module.extraProguardFlagFiles = append(a.Module.extraProguardFlagFiles, a.proguardOptionsFile)

	if ctx.ModuleName() != "framework-res" {
		a.Module.compile(ctx, a.aaptSrcJar)
	}

	c := String(a.appProperties.Certificate)
	switch {
	case c == "":
		pem, key := ctx.Config().DefaultAppCertificate(ctx)
		a.certificate = certificate{pem, key}
	case strings.ContainsRune(c, '/'):
		a.certificate = certificate{
			android.PathForSource(ctx, c+".x509.pem"),
			android.PathForSource(ctx, c+".pk8"),
		}
	default:
		defaultDir := ctx.Config().DefaultAppCertificateDir(ctx)
		a.certificate = certificate{
			defaultDir.Join(ctx, c+".x509.pem"),
			defaultDir.Join(ctx, c+".pk8"),
		}
	}

	certificates := []certificate{a.certificate}
	for _, c := range a.appProperties.Additional_certificates {
		certificates = append(certificates, certificate{
			android.PathForSource(ctx, c+".x509.pem"),
			android.PathForSource(ctx, c+".pk8"),
		})
	}

	packageFile := android.PathForModuleOut(ctx, "package.apk")

	CreateAppPackage(ctx, packageFile, a.exportPackage, a.outputFile, certificates)

	a.outputFile = packageFile

	if ctx.ModuleName() == "framework-res" {
		// framework-res.apk is installed as system/framework/framework-res.apk
		ctx.InstallFile(android.PathForModuleInstall(ctx, "framework"), ctx.ModuleName()+".apk", a.outputFile)
	} else if Bool(a.appProperties.Privileged) {
		ctx.InstallFile(android.PathForModuleInstall(ctx, "priv-app"), ctx.ModuleName()+".apk", a.outputFile)
	} else {
		ctx.InstallFile(android.PathForModuleInstall(ctx, "app"), ctx.ModuleName()+".apk", a.outputFile)
	}
}

func AndroidAppFactory() android.Module {
	module := &AndroidApp{}

	module.Module.deviceProperties.Optimize.Enabled = proptools.BoolPtr(true)
	module.Module.deviceProperties.Optimize.Shrink = proptools.BoolPtr(true)

	module.Module.properties.Instrument = true

	module.AddProperties(
		&module.Module.properties,
		&module.Module.deviceProperties,
		&module.Module.protoProperties,
		&module.aaptProperties,
		&module.appProperties)

	android.InitAndroidArchModule(module, android.DeviceSupported, android.MultilibCommon)
	return module
}

type appTestProperties struct {
	Instrumentation_for *string
}

type AndroidTest struct {
	AndroidApp

	appTestProperties appTestProperties

	testProperties testProperties
}

func (a *AndroidTest) GenerateAndroidBuildActions(ctx android.ModuleContext) {
	if String(a.appTestProperties.Instrumentation_for) != "" {
		a.AndroidApp.extraLinkFlags = append(a.AndroidApp.extraLinkFlags,
			"--rename-instrumentation-target-package",
			String(a.appTestProperties.Instrumentation_for))
	}

	a.generateAndroidBuildActions(ctx)
}

func AndroidTestFactory() android.Module {
	module := &AndroidTest{}

	module.Module.deviceProperties.Optimize.Enabled = proptools.BoolPtr(true)

	module.AddProperties(
		&module.Module.properties,
		&module.Module.deviceProperties,
		&module.Module.protoProperties,
		&module.aaptProperties,
		&module.appProperties,
		&module.appTestProperties)

	android.InitAndroidArchModule(module, android.DeviceSupported, android.MultilibCommon)

	return module
}
