// Copyright 2016 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 (
	"github.com/google/blueprint"
)

// This file implements hooks that external module types can use to inject logic into existing
// module types.  Each hook takes an interface as a parameter so that new methods can be added
// to the interface without breaking existing module types.

// Load hooks are run after the module's properties have been filled from the blueprint file, but
// before the module has been split into architecture variants, and before defaults modules have
// been applied.
type LoadHookContext interface {
	// TODO: a new context that includes Config() but not Target(), etc.?
	BaseModuleContext
	AppendProperties(...interface{})
	PrependProperties(...interface{})
	CreateModule(ModuleFactory, ...interface{}) Module
}

// Arch hooks are run after the module has been split into architecture variants, and can be used
// to add architecture-specific properties.
type ArchHookContext interface {
	BaseModuleContext
	AppendProperties(...interface{})
	PrependProperties(...interface{})
}

func AddLoadHook(m blueprint.Module, hook func(LoadHookContext)) {
	h := &m.(Module).base().hooks
	h.load = append(h.load, hook)
}

func AddArchHook(m blueprint.Module, hook func(ArchHookContext)) {
	h := &m.(Module).base().hooks
	h.arch = append(h.arch, hook)
}

func (x *hooks) runLoadHooks(ctx LoadHookContext, m *ModuleBase) {
	if len(x.load) > 0 {
		for _, x := range x.load {
			x(ctx)
			if ctx.Failed() {
				return
			}
		}
	}
}

func (x *hooks) runArchHooks(ctx ArchHookContext, m *ModuleBase) {
	if len(x.arch) > 0 {
		for _, x := range x.arch {
			x(ctx)
			if ctx.Failed() {
				return
			}
		}
	}
}

type InstallHookContext interface {
	ModuleContext
	Path() InstallPath
	Symlink() bool
}

// Install hooks are run after a module creates a rule to install a file or symlink.
// The installed path is available from InstallHookContext.Path(), and
// InstallHookContext.Symlink() will be true if it was a symlink.
func AddInstallHook(m blueprint.Module, hook func(InstallHookContext)) {
	h := &m.(Module).base().hooks
	h.install = append(h.install, hook)
}

type installHookContext struct {
	ModuleContext
	path    InstallPath
	symlink bool
}

func (x *installHookContext) Path() InstallPath {
	return x.path
}

func (x *installHookContext) Symlink() bool {
	return x.symlink
}

func (x *hooks) runInstallHooks(ctx ModuleContext, path InstallPath, symlink bool) {
	if len(x.install) > 0 {
		mctx := &installHookContext{
			ModuleContext: ctx,
			path:          path,
			symlink:       symlink,
		}
		for _, x := range x.install {
			x(mctx)
			if mctx.Failed() {
				return
			}
		}
	}
}

type hooks struct {
	load    []func(LoadHookContext)
	arch    []func(ArchHookContext)
	install []func(InstallHookContext)
}

func registerLoadHookMutator(ctx RegisterMutatorsContext) {
	ctx.TopDown("load_hooks", LoadHookMutator).Parallel()
}

func LoadHookMutator(ctx TopDownMutatorContext) {
	if m, ok := ctx.Module().(Module); ok {
		m.base().commonProperties.DebugName = ctx.ModuleName()

		// Cast through *topDownMutatorContext because AppendProperties is implemented
		// on *topDownMutatorContext but not exposed through TopDownMutatorContext
		var loadHookCtx LoadHookContext = ctx.(*topDownMutatorContext)
		m.base().hooks.runLoadHooks(loadHookCtx, m.base())
	}
}

func archHookMutator(ctx TopDownMutatorContext) {
	if m, ok := ctx.Module().(Module); ok {
		// Cast through *topDownMutatorContext because AppendProperties is implemented
		// on *topDownMutatorContext but not exposed through TopDownMutatorContext
		var archHookCtx ArchHookContext = ctx.(*topDownMutatorContext)
		m.base().hooks.runArchHooks(archHookCtx, m.base())
	}
}
