// Copyright 2022 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 (
	"encoding/json"
	"fmt"
	"io/ioutil"
	"os"
	"strings"

	"github.com/google/blueprint"
)

func init() {
	RegisterPluginSingletonBuildComponents(InitRegistrationContext)
}

func RegisterPluginSingletonBuildComponents(ctx RegistrationContext) {
	ctx.RegisterParallelSingletonType("plugins", pluginSingletonFactory)
}

// pluginSingleton is a singleton to handle allowlisting of the final Android-<product_name>.mk file
// output.
func pluginSingletonFactory() Singleton {
	return &pluginSingleton{}
}

type pluginSingleton struct{}

var allowedPluginsByName = map[string]bool{
	"aidl-soong-rules":                       true,
	"arm_compute_library_nn_driver":          true,
	"cuttlefish-soong-rules":                 true,
	"gki-soong-rules":                        true,
	"hidl-soong-rules":                       true,
	"kernel-config-soong-rules":              true,
	"soong-angle-codegen":                    true,
	"soong-api":                              true,
	"soong-art":                              true,
	"soong-ca-certificates":                  true,
	"soong-ca-certificates-apex":             true,
	"soong-clang":                            true,
	"soong-clang-prebuilts":                  true,
	"soong-csuite":                           true,
	"soong-fluoride":                         true,
	"soong-fs_config":                        true,
	"soong-icu":                              true,
	"soong-java-config-error_prone":          true,
	"soong-libchrome":                        true,
	"soong-llvm":                             true,
	"soong-robolectric":                      true,
	"soong-rust-prebuilts":                   true,
	"soong-selinux":                          true,
	"soong-wayland-protocol-codegen":         true,
	"treble_report_app":                      true,
	"treble_report_local":                    true,
	"treble_report_module":                   true,
	"vintf-compatibility-matrix-soong-rules": true,
	"xsdc-soong-rules":                       true,
}

const (
	internalPluginsPath = "vendor/google/build/soong/internal_plugins.json"
)

type pluginProvider interface {
	IsPluginFor(string) bool
}

func maybeAddInternalPluginsToAllowlist(ctx SingletonContext) {
	if path := ExistentPathForSource(ctx, internalPluginsPath); path.Valid() {
		ctx.AddNinjaFileDeps(path.String())
		absPath := absolutePath(path.String())
		var moreAllowed map[string]bool
		data, err := ioutil.ReadFile(absPath)
		if err != nil {
			ctx.Errorf("Failed to open internal plugins path %q %q", internalPluginsPath, err)
		}
		if err := json.Unmarshal(data, &moreAllowed); err != nil {
			fmt.Fprintf(os.Stderr, "Internal plugins file %q did not parse correctly: %q", data, err)
		}
		for k, v := range moreAllowed {
			allowedPluginsByName[k] = v
		}
	}
}

func (p *pluginSingleton) GenerateBuildActions(ctx SingletonContext) {
	for _, p := range ctx.DeviceConfig().BuildBrokenPluginValidation() {
		allowedPluginsByName[p] = true
	}
	maybeAddInternalPluginsToAllowlist(ctx)

	disallowedPlugins := map[string]bool{}
	ctx.VisitAllModulesBlueprint(func(module blueprint.Module) {
		if ctx.ModuleType(module) != "bootstrap_go_package" {
			return
		}

		p, ok := module.(pluginProvider)
		if !ok || !p.IsPluginFor("soong_build") {
			return
		}

		name := ctx.ModuleName(module)
		if _, ok := allowedPluginsByName[name]; ok {
			return
		}

		dir := ctx.ModuleDir(module)

		// allow use of plugins within Soong to not allowlist everything
		if strings.HasPrefix(dir, "build/soong") {
			return
		}

		// allow third party users outside of external to create new plugins, i.e. non-google paths
		// under vendor or hardware
		if !strings.HasPrefix(dir, "external/") && IsThirdPartyPath(dir) {
			return
		}
		disallowedPlugins[name] = true
	})
	if len(disallowedPlugins) > 0 {
		ctx.Errorf("New plugins are not supported; however %q were found. Please reach out to the build team or use BUILD_BROKEN_PLUGIN_VALIDATION (see Changes.md for more info).", SortedStringKeys(disallowedPlugins))
	}
}
