// Copyright 2021 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 android

import (
	"fmt"
	"reflect"
	"strconv"
	"strings"
)

type SdkContext interface {
	// SdkVersion returns SdkSpec that corresponds to the sdk_version property of the current module
	SdkVersion(ctx EarlyModuleContext) SdkSpec
	// SystemModules returns the system_modules property of the current module, or an empty string if it is not set.
	SystemModules() string
	// MinSdkVersion returns ApiLevel that corresponds to the min_sdk_version property of the current module,
	// or from sdk_version if it is not set.
	MinSdkVersion(ctx EarlyModuleContext) ApiLevel
	// ReplaceMaxSdkVersionPlaceholder returns Apilevel to replace the maxSdkVersion property of permission and
	// uses-permission tags if it is set.
	ReplaceMaxSdkVersionPlaceholder(ctx EarlyModuleContext) ApiLevel
	// TargetSdkVersion returns the ApiLevel that corresponds to the target_sdk_version property of the current module,
	// or from sdk_version if it is not set.
	TargetSdkVersion(ctx EarlyModuleContext) ApiLevel
}

// SdkKind represents a particular category of an SDK spec like public, system, test, etc.
type SdkKind int

// These are generally ordered from the narrower sdk version to the wider sdk version,
// but not all entries have a strict subset/superset relationship.
// For example, SdkTest and SdkModule do not have a strict subset/superset relationship but both
// are supersets of SdkSystem.
// The general trend should be kept when an additional sdk kind is added.
const (
	SdkInvalid SdkKind = iota
	SdkNone
	SdkToolchain // API surface provided by ART to compile other API domains
	SdkCore
	SdkCorePlatform
	SdkIntraCore // API surface provided by one core module to another
	SdkPublic
	SdkSystem
	SdkTest
	SdkTestFrameworksCore
	SdkModule
	SdkSystemServer
	SdkPrivate
)

// String returns the string representation of this SdkKind
func (k SdkKind) String() string {
	switch k {
	case SdkPrivate:
		return "private"
	case SdkNone:
		return "none"
	case SdkPublic:
		return "public"
	case SdkSystem:
		return "system"
	case SdkTest:
		return "test"
	case SdkTestFrameworksCore:
		return "test_frameworks_core"
	case SdkCore:
		return "core"
	case SdkCorePlatform:
		return "core_platform"
	case SdkIntraCore:
		return "intracore"
	case SdkModule:
		return "module-lib"
	case SdkSystemServer:
		return "system-server"
	case SdkToolchain:
		return "toolchain"
	default:
		return "invalid"
	}
}

func ToSdkKind(s string) SdkKind {
	for kind := SdkNone; kind <= SdkPrivate; kind++ {
		if s == kind.String() {
			return kind
		}
	}
	return SdkInvalid
}

func (k SdkKind) DefaultJavaLibraryName() string {
	switch k {
	case SdkPublic:
		return "android_stubs_current"
	case SdkSystem:
		return "android_system_stubs_current"
	case SdkTest:
		return "android_test_stubs_current"
	case SdkTestFrameworksCore:
		return "android_test_frameworks_core_stubs_current"
	case SdkCore:
		return "core.current.stubs"
	case SdkModule:
		return "android_module_lib_stubs_current"
	case SdkSystemServer:
		return "android_system_server_stubs_current"
	default:
		panic(fmt.Errorf("APIs of API surface %v cannot be provided by a single Soong module\n", k))
	}
}

func (k SdkKind) DefaultExportableJavaLibraryName() string {
	switch k {
	case SdkPublic, SdkSystem, SdkTest, SdkModule, SdkSystemServer:
		return k.DefaultJavaLibraryName() + "_exportable"
	case SdkCore:
		return k.DefaultJavaLibraryName() + ".exportable"
	default:
		panic(fmt.Errorf("API surface %v does not provide exportable stubs", k))
	}
}

// SdkSpec represents the kind and the version of an SDK for a module to build against
type SdkSpec struct {
	Kind     SdkKind
	ApiLevel ApiLevel
	Raw      string
}

func (s SdkSpec) String() string {
	return fmt.Sprintf("%s_%s", s.Kind, s.ApiLevel)
}

// Valid checks if this SdkSpec is well-formed. Note however that true doesn't mean that the
// specified SDK actually exists.
func (s SdkSpec) Valid() bool {
	return s.Kind != SdkInvalid
}

// Specified checks if this SdkSpec is well-formed and is not "".
func (s SdkSpec) Specified() bool {
	return s.Valid() && s.Kind != SdkPrivate
}

// whether the API surface is managed and versioned, i.e. has .txt file that
// get frozen on SDK freeze and changes get reviewed by API council.
func (s SdkSpec) Stable() bool {
	if !s.Specified() {
		return false
	}
	switch s.Kind {
	case SdkNone:
		// there is nothing to manage and version in this case; de facto stable API.
		return true
	case SdkCore, SdkPublic, SdkSystem, SdkModule, SdkSystemServer:
		return true
	case SdkCorePlatform, SdkTest, SdkTestFrameworksCore, SdkPrivate:
		return false
	default:
		panic(fmt.Errorf("unknown SdkKind=%v", s.Kind))
	}
	return false
}

// PrebuiltSdkAvailableForUnbundledBuild tells whether this SdkSpec can have a prebuilt SDK
// that can be used for unbundled builds.
func (s SdkSpec) PrebuiltSdkAvailableForUnbundledBuild() bool {
	// "", "none", and "core_platform" are not available for unbundled build
	// as we don't/can't have prebuilt stub for the versions
	return s.Kind != SdkPrivate && s.Kind != SdkNone && s.Kind != SdkCorePlatform
}

func (s SdkSpec) ForVendorPartition(ctx EarlyModuleContext) SdkSpec {
	// If BOARD_CURRENT_API_LEVEL_FOR_VENDOR_MODULES has a numeric value,
	// use it instead of "current" for the vendor partition.
	currentSdkVersion := ctx.DeviceConfig().CurrentApiLevelForVendorModules()
	// b/314011075: special case for Java modules in vendor partition. They can no longer use
	// SDK 35 or later. Their maximum API level is limited to 34 (Android U). This is to
	// discourage the use of Java APIs in the vendor partition which hasn't been officially
	// supported since the Project Treble back in Android 10. We would like to eventually
	// evacuate all Java modules from the partition, but that shall be done progressively.
	// Note that the check for the availability of SDK 34 is to not break existing tests where
	// any of the frozen SDK version is unavailable.
	if isJava(ctx.Module()) && isSdkVersion34AvailableIn(ctx.Config()) {
		currentSdkVersion = "34"
	}

	if currentSdkVersion == "current" {
		return s
	}

	if s.Kind == SdkPublic || s.Kind == SdkSystem {
		if s.ApiLevel.IsCurrent() {
			if i, err := strconv.Atoi(currentSdkVersion); err == nil {
				apiLevel := uncheckedFinalApiLevel(i)
				return SdkSpec{s.Kind, apiLevel, s.Raw}
			}
			panic(fmt.Errorf("BOARD_CURRENT_API_LEVEL_FOR_VENDOR_MODULES must be either \"current\" or a number, but was %q", currentSdkVersion))
		}
	}
	return s
}

// UsePrebuilt determines whether prebuilt SDK should be used for this SdkSpec with the given context.
func (s SdkSpec) UsePrebuilt(ctx EarlyModuleContext) bool {
	switch s {
	case SdkSpecNone, SdkSpecCorePlatform, SdkSpecPrivate:
		return false
	}

	if s.ApiLevel.IsCurrent() {
		// "current" can be built from source and be from prebuilt SDK
		return ctx.Config().AlwaysUsePrebuiltSdks()
	} else if !s.ApiLevel.IsPreview() {
		// validation check
		if s.Kind != SdkPublic && s.Kind != SdkSystem && s.Kind != SdkTest &&
			s.Kind != SdkTestFrameworksCore && s.Kind != SdkModule && s.Kind != SdkSystemServer {
			panic(fmt.Errorf("prebuilt SDK is not not available for SdkKind=%q", s.Kind))
			return false
		}
		// numbered SDKs are always from prebuilt
		return true
	}
	return false
}

// EffectiveVersion converts an SdkSpec into the concrete ApiLevel that the module should use. For
// modules targeting an unreleased SDK (meaning it does not yet have a number) it returns
// FutureApiLevel(10000).
func (s SdkSpec) EffectiveVersion(ctx EarlyModuleContext) (ApiLevel, error) {
	if !s.Valid() {
		return s.ApiLevel, fmt.Errorf("invalid sdk version %q", s.Raw)
	}

	if ctx.DeviceSpecific() || ctx.SocSpecific() {
		s = s.ForVendorPartition(ctx)
	}
	return s.ApiLevel.EffectiveVersion(ctx)
}

// EffectiveVersionString converts an SdkSpec into the concrete version string that the module
// should use. For modules targeting an unreleased SDK (meaning it does not yet have a number)
// it returns the codename (P, Q, R, etc.)
func (s SdkSpec) EffectiveVersionString(ctx EarlyModuleContext) (string, error) {
	if !s.Valid() {
		return s.ApiLevel.String(), fmt.Errorf("invalid sdk version %q", s.Raw)
	}

	if ctx.DeviceSpecific() || ctx.SocSpecific() {
		s = s.ForVendorPartition(ctx)
	}
	return s.ApiLevel.EffectiveVersionString(ctx)
}

var (
	SdkSpecNone         = SdkSpec{SdkNone, NoneApiLevel, "(no version)"}
	SdkSpecPrivate      = SdkSpec{SdkPrivate, PrivateApiLevel, ""}
	SdkSpecCorePlatform = SdkSpec{SdkCorePlatform, FutureApiLevel, "core_platform"}
)

func SdkSpecFrom(ctx EarlyModuleContext, str string) SdkSpec {
	return SdkSpecFromWithConfig(ctx.Config(), str)
}

func SdkSpecFromWithConfig(config Config, str string) SdkSpec {
	switch str {
	// special cases first
	case "":
		return SdkSpecPrivate
	case "none":
		return SdkSpecNone
	case "core_platform":
		return SdkSpecCorePlatform
	default:
		// the syntax is [kind_]version
		sep := strings.LastIndex(str, "_")

		var kindString string
		if sep == 0 {
			return SdkSpec{SdkInvalid, NewInvalidApiLevel(str), str}
		} else if sep == -1 {
			kindString = ""
		} else {
			kindString = str[0:sep]
		}
		versionString := str[sep+1 : len(str)]

		var kind SdkKind
		switch kindString {
		case "":
			kind = SdkPublic
		case "core":
			kind = SdkCore
		case "system":
			kind = SdkSystem
		case "test":
			kind = SdkTest
		case "test_frameworks_core":
			kind = SdkTestFrameworksCore
		case "module":
			kind = SdkModule
		case "system_server":
			kind = SdkSystemServer
		default:
			return SdkSpec{SdkInvalid, NoneApiLevel, str}
		}

		apiLevel, err := ApiLevelFromUserWithConfig(config, versionString)
		if err != nil {
			return SdkSpec{SdkInvalid, NewInvalidApiLevel(versionString), str}
		}
		return SdkSpec{kind, apiLevel, str}
	}
}

// Checks if the use of this SDK `s` is valid for the given module context `ctx`.
func (s SdkSpec) ValidateSystemSdk(ctx EarlyModuleContext) bool {
	// Do some early checks. This check is currently only for Java modules. And our only concern
	// is the use of "system" SDKs.
	if !isJava(ctx.Module()) || s.Kind != SdkSystem || ctx.DeviceConfig().BuildBrokenDontCheckSystemSdk() {
		return true
	}

	inVendor := ctx.DeviceSpecific() || ctx.SocSpecific()
	inProduct := ctx.ProductSpecific()
	isProductUnbundled := ctx.Config().EnforceProductPartitionInterface()
	inApex := false
	if am, ok := ctx.Module().(ApexModule); ok {
		inApex = am.InAnyApex()
	}
	isUnbundled := inVendor || (inProduct && isProductUnbundled) || inApex

	// Bundled modules can use any SDK
	if !isUnbundled {
		return true
	}

	// Unbundled modules are allowed to use BOARD_SYSTEMSDK_VERSIONS
	supportedVersions := ctx.DeviceConfig().SystemSdkVersions()

	// b/314011075: special case for vendor modules. Java modules in the vendor partition can
	// not use SDK 35 or later. This is to discourage the use of Java APIs in the vendor
	// partition which hasn't been officially supported since the Project Treble back in Android
	// 10. We would like to eventually evacuate all Java modules from the partition, but that
	// shall be done progressively.
	if inVendor {
		// 28 was the API when BOARD_SYSTEMSDK_VERSIONS was introduced, so that's the oldest
		// we should allow.
		supportedVersions = []string{}
		for v := 28; v <= 34; v++ {
			supportedVersions = append(supportedVersions, strconv.Itoa(v))
		}
	}

	// APEXes in the system partition are still considered as part of the platform, thus can use
	// more SDKs from PLATFORM_SYSTEMSDK_VERSIONS
	if inApex && !inVendor {
		supportedVersions = ctx.DeviceConfig().PlatformSystemSdkVersions()
	}

	thisVer, err := s.EffectiveVersion(ctx)
	if err != nil {
		ctx.PropertyErrorf("sdk_version", "invalid sdk version %q", s.Raw)
		return false
	}

	thisVerString := strconv.Itoa(thisVer.FinalOrPreviewInt())
	if thisVer.IsPreview() {
		thisVerString = *ctx.Config().productVariables.Platform_sdk_version_or_codename
	}

	if !InList(thisVerString, supportedVersions) {
		ctx.PropertyErrorf("sdk_version", "incompatible sdk version %q. System SDK version should be one of %q",
			s.Raw, supportedVersions)
		return false
	}
	return true
}

func isJava(m Module) bool {
	moduleType := reflect.TypeOf(m).String()
	return strings.HasPrefix(moduleType, "*java.")
}

func isSdkVersion34AvailableIn(c Config) bool {
	return c.PlatformSdkVersion().FinalInt() >= 34
}

func init() {
	RegisterMakeVarsProvider(pctx, javaSdkMakeVars)
}

// Export the name of the soong modules representing the various Java API surfaces.
func javaSdkMakeVars(ctx MakeVarsContext) {
	ctx.Strict("ANDROID_PUBLIC_STUBS", SdkPublic.DefaultJavaLibraryName())
	ctx.Strict("ANDROID_PUBLIC_EXPORTABLE_STUBS", SdkPublic.DefaultExportableJavaLibraryName())
	ctx.Strict("ANDROID_SYSTEM_STUBS", SdkSystem.DefaultJavaLibraryName())
	ctx.Strict("ANDROID_TEST_STUBS", SdkTest.DefaultJavaLibraryName())
	ctx.Strict("ANDROID_MODULE_LIB_STUBS", SdkModule.DefaultJavaLibraryName())
	ctx.Strict("ANDROID_SYSTEM_SERVER_STUBS", SdkSystemServer.DefaultJavaLibraryName())
	ctx.Strict("ANDROID_CORE_STUBS", SdkCore.DefaultJavaLibraryName())
}
