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

import (
	"fmt"
	"path/filepath"
	"strings"

	"github.com/google/blueprint/proptools"
)

func init() {
	RegisterGenNoticeBuildComponents(InitRegistrationContext)
}

// Register the gen_notice module type.
func RegisterGenNoticeBuildComponents(ctx RegistrationContext) {
	ctx.RegisterParallelSingletonType("gen_notice_build_rules", GenNoticeBuildRulesFactory)
	ctx.RegisterModuleType("gen_notice", GenNoticeFactory)
}

type genNoticeBuildRules struct{}

func (s *genNoticeBuildRules) GenerateBuildActions(ctx SingletonContext) {
	ctx.VisitAllModules(func(m Module) {
		gm, ok := m.(*genNoticeModule)
		if !ok {
			return
		}
		if len(gm.missing) > 0 {
			missingReferencesRule(ctx, gm)
			return
		}
		out := BuildNoticeTextOutputFromLicenseMetadata
		if proptools.Bool(gm.properties.Xml) {
			out = BuildNoticeXmlOutputFromLicenseMetadata
		} else if proptools.Bool(gm.properties.Html) {
			out = BuildNoticeHtmlOutputFromLicenseMetadata
		}
		defaultName := ""
		if len(gm.properties.For) > 0 {
			defaultName = gm.properties.For[0]
		}

		modules := make([]Module, 0)
		for _, name := range gm.properties.For {
			mods := ctx.ModuleVariantsFromName(gm, name)
			for _, mod := range mods {
				if mod == nil {
					continue
				}
				if !mod.Enabled(ctx) { // don't depend on variants without build rules
					continue
				}
				modules = append(modules, mod)
			}
		}
		if ctx.Failed() {
			return
		}
		out(ctx, gm.output, ctx.ModuleName(gm),
			proptools.StringDefault(gm.properties.ArtifactName, defaultName),
			[]string{
				filepath.Join(ctx.Config().OutDir(), "target", "product", ctx.Config().DeviceName()) + "/",
				ctx.Config().OutDir() + "/",
				ctx.Config().SoongOutDir() + "/",
			}, modules...)
	})
}

func GenNoticeBuildRulesFactory() Singleton {
	return &genNoticeBuildRules{}
}

type genNoticeProperties struct {
	// For specifies the modules for which to generate a notice file.
	For []string
	// ArtifactName specifies the internal name to use for the notice file.
	// It appears in the "used by:" list for targets whose entire name is stripped by --strip_prefix.
	ArtifactName *string
	// Stem specifies the base name of the output file.
	Stem *string `android:"arch_variant"`
	// Html indicates an html-format file is needed. The default is text. Can be Html or Xml but not both.
	Html *bool
	// Xml indicates an xml-format file is needed. The default is text. Can be Html or Xml but not both.
	Xml *bool
	// Gzipped indicates the output file must be compressed with gzip. Will append .gz to suffix if not there.
	Gzipped *bool
	// Suffix specifies the file extension to use. Defaults to .html for html, .xml for xml, or no extension for text.
	Suffix *string
	// Visibility specifies where this license can be used
	Visibility []string
}

type genNoticeModule struct {
	ModuleBase
	DefaultableModuleBase

	properties genNoticeProperties

	output  OutputPath
	missing []string
}

func (m *genNoticeModule) DepsMutator(ctx BottomUpMutatorContext) {
	if ctx.ContainsProperty("licenses") {
		ctx.PropertyErrorf("licenses", "not supported on \"gen_notice\" modules")
	}
	if proptools.Bool(m.properties.Html) && proptools.Bool(m.properties.Xml) {
		ctx.ModuleErrorf("can be html or xml but not both")
	}
	if !ctx.Config().AllowMissingDependencies() {
		var missing []string
		// Verify the modules for which to generate notices exist.
		for _, otherMod := range m.properties.For {
			if !ctx.OtherModuleExists(otherMod) {
				missing = append(missing, otherMod)
			}
		}
		if len(missing) == 1 {
			ctx.PropertyErrorf("for", "no %q module exists", missing[0])
		} else if len(missing) > 1 {
			ctx.PropertyErrorf("for", "modules \"%s\" do not exist", strings.Join(missing, "\", \""))
		}
	}
}

func (m *genNoticeModule) getStem() string {
	stem := m.base().BaseModuleName()
	if m.properties.Stem != nil {
		stem = proptools.String(m.properties.Stem)
	}
	return stem
}

func (m *genNoticeModule) getSuffix() string {
	suffix := ""
	if m.properties.Suffix == nil {
		if proptools.Bool(m.properties.Html) {
			suffix = ".html"
		} else if proptools.Bool(m.properties.Xml) {
			suffix = ".xml"
		}
	} else {
		suffix = proptools.String(m.properties.Suffix)
	}
	if proptools.Bool(m.properties.Gzipped) && !strings.HasSuffix(suffix, ".gz") {
		suffix += ".gz"
	}
	return suffix
}

func (m *genNoticeModule) GenerateAndroidBuildActions(ctx ModuleContext) {
	if ctx.Config().AllowMissingDependencies() {
		// Verify the modules for which to generate notices exist.
		for _, otherMod := range m.properties.For {
			if !ctx.OtherModuleExists(otherMod) {
				m.missing = append(m.missing, otherMod)
			}
		}
		m.missing = append(m.missing, ctx.GetMissingDependencies()...)
		m.missing = FirstUniqueStrings(m.missing)
	}
	out := m.getStem() + m.getSuffix()
	m.output = PathForModuleOut(ctx, out).OutputPath
	ctx.SetOutputFiles(Paths{m.output}, "")
}

func GenNoticeFactory() Module {
	module := &genNoticeModule{}

	base := module.base()
	module.AddProperties(&base.nameProperties, &module.properties)

	// The visibility property needs to be checked and parsed by the visibility module.
	setPrimaryVisibilityProperty(module, "visibility", &module.properties.Visibility)

	InitAndroidArchModule(module, DeviceSupported, MultilibCommon)
	InitDefaultableModule(module)

	return module
}

var _ AndroidMkEntriesProvider = (*genNoticeModule)(nil)

// Implements AndroidMkEntriesProvider
func (m *genNoticeModule) AndroidMkEntries() []AndroidMkEntries {
	return []AndroidMkEntries{AndroidMkEntries{
		Class:      "ETC",
		OutputFile: OptionalPathForPath(m.output),
	}}
}

// missingReferencesRule emits an ErrorRule for missing module references.
func missingReferencesRule(ctx BuilderContext, m *genNoticeModule) {
	if len(m.missing) < 1 {
		panic(fmt.Errorf("missing references rule requested with no missing references"))
	}

	ctx.Build(pctx, BuildParams{
		Rule:        ErrorRule,
		Output:      m.output,
		Description: "notice for " + proptools.StringDefault(m.properties.ArtifactName, "container"),
		Args: map[string]string{
			"error": m.Name() + " references missing module(s): " + strings.Join(m.missing, ", "),
		},
	})
}
