// 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.RegisterSingletonType("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() { // 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
}

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 _ OutputFileProducer = (*genNoticeModule)(nil)

// Implements OutputFileProducer
func (m *genNoticeModule) OutputFiles(tag string) (Paths, error) {
	if tag == "" {
		return Paths{m.output}, nil
	}
	return nil, fmt.Errorf("unrecognized tag %q", tag)
}

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, ", "),
		},
	})
}
