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

import (
	"android/soong/android"
	"github.com/google/blueprint"
)

var (
	pctx = android.NewPackageContext("android/soong/multitree")
)

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

var PrepareForTestWithApiSurface = android.FixtureRegisterWithContext(RegisterApiSurfaceBuildComponents)

func RegisterApiSurfaceBuildComponents(ctx android.RegistrationContext) {
	ctx.RegisterModuleType("api_surface", ApiSurfaceFactory)
}

type ApiSurface struct {
	android.ModuleBase
	ExportableModuleBase
	properties apiSurfaceProperties

	taggedOutputs map[string]android.Paths
}

type apiSurfaceProperties struct {
	Contributions []string
}

func ApiSurfaceFactory() android.Module {
	module := &ApiSurface{}
	module.AddProperties(&module.properties)
	android.InitAndroidModule(module)
	InitExportableModule(module)
	return module
}

func (surface *ApiSurface) DepsMutator(ctx android.BottomUpMutatorContext) {
	if surface.properties.Contributions != nil {
		ctx.AddVariationDependencies(nil, nil, surface.properties.Contributions...)
	}

}
func (surface *ApiSurface) GenerateAndroidBuildActions(ctx android.ModuleContext) {
	contributionFiles := make(map[string]android.Paths)
	var allOutputs android.Paths
	ctx.WalkDeps(func(child, parent android.Module) bool {
		if contribution, ok := child.(ApiContribution); ok {
			copied := contribution.CopyFilesWithTag(ctx)
			for tag, files := range copied {
				contributionFiles[child.Name()+"#"+tag] = files
			}
			for _, paths := range copied {
				allOutputs = append(allOutputs, paths...)
			}
			return false // no transitive dependencies
		}
		return false
	})

	// phony target
	ctx.Build(pctx, android.BuildParams{
		Rule:   blueprint.Phony,
		Output: android.PathForPhony(ctx, ctx.ModuleName()),
		Inputs: allOutputs,
	})

	surface.taggedOutputs = contributionFiles

	ctx.SetOutputFiles(allOutputs, "")
}

func (surface *ApiSurface) TaggedOutputs() map[string]android.Paths {
	return surface.taggedOutputs
}

func (surface *ApiSurface) Exportable() bool {
	return true
}

var _ Exportable = (*ApiSurface)(nil)

type ApiContribution interface {
	// copy files necessaryt to construct an API surface
	// For C, it will be map.txt and .h files
	// For Java, it will be api.txt
	CopyFilesWithTag(ctx android.ModuleContext) map[string]android.Paths // output paths

	// Generate Android.bp in out/ to use the exported .txt files
	// GenerateBuildFiles(ctx ModuleContext) Paths //output paths
}
