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

import (
	"encoding/gob"
	"fmt"

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

// This file implements Providers, modelled after Bazel
// (https://docs.bazel.build/versions/master/skylark/rules.html#providers).
// Each provider can be associated with a mutator, in which case the value for the provider for a
// module can only be set during the mutator call for the module, and the value can only be
// retrieved after the mutator call for the module. For providers not associated with a mutator, the
// value can for the provider for a module can only be set during GenerateBuildActions for the
// module, and the value can only be retrieved after GenerateBuildActions for the module.
//
// Providers are globally registered during init() and given a unique ID.  The value of a provider
// for a module is stored in an []any indexed by the ID.  If the value of a provider has
// not been set, the value in the []any will be nil.
//
// If the storage used by the provider value arrays becomes too large:
//  sizeof([]interface) * number of providers * number of modules that have a provider value set
// then the storage can be replaced with something like a bitwise trie.
//
// The purpose of providers is to provide a serializable checkpoint between modules to enable
// Blueprint to skip parts of the analysis phase when inputs haven't changed.  To that end,
// values passed to providers should be treated as immutable by callers to both the getters and
// setters.  Go doesn't provide any way to enforce immutability on arbitrary types, so it may be
// necessary for the getters and setters to make deep copies of the values, likely extending
// proptools.CloneProperties to do so.

type typedProviderKey[K any] struct {
	providerKey
}

type providerKey struct {
	id      int
	typ     string
	mutator string
}

type providerKeyGob struct {
	Id      int
	Typ     string
	Mutator string
}

func (m *providerKey) ToGob() *providerKeyGob {
	return &providerKeyGob{
		Id:      m.id,
		Typ:     m.typ,
		Mutator: m.mutator,
	}
}

func (m *providerKey) FromGob(data *providerKeyGob) {
	m.id = data.Id
	m.typ = data.Typ
	m.mutator = data.Mutator
}

func (m *providerKey) GobEncode() ([]byte, error) {
	return gobtools.CustomGobEncode[providerKeyGob](m)
}

func (m *providerKey) GobDecode(data []byte) error {
	return gobtools.CustomGobDecode[providerKeyGob](data, m)
}

func (p *providerKey) provider() *providerKey { return p }

type AnyProviderKey interface {
	provider() *providerKey
}
type ProviderKey[K any] struct {
	*typedProviderKey[K]
}

var _ AnyProviderKey = (*providerKey)(nil)
var _ AnyProviderKey = ProviderKey[bool]{}

var providerRegistry []*providerKey

// NewProvider returns a ProviderKey for the given type.
//
// The returned ProviderKey can be used to set a value of the ProviderKey's type for a module
// inside GenerateBuildActions for the module, and to get the value from GenerateBuildActions from
// any module later in the build graph.
func NewProvider[K any]() ProviderKey[K] {
	var defaultValue K
	gob.Register(defaultValue)
	return NewMutatorProvider[K]("")
}

// NewMutatorProvider returns a ProviderKey for the given type.
//
// The returned ProviderKey can be used to set a value of the ProviderKey's type for a module inside
// the given mutator for the module, and to get the value from GenerateBuildActions from any
// module later in the build graph in the same mutator, or any module in a later mutator or during
// GenerateBuildActions.
func NewMutatorProvider[K any](mutator string) ProviderKey[K] {
	checkCalledFromInit()

	typ := fmt.Sprintf("%T", *new(K))

	provider := ProviderKey[K]{
		typedProviderKey: &typedProviderKey[K]{
			providerKey: providerKey{
				id:      len(providerRegistry),
				typ:     typ,
				mutator: mutator,
			},
		},
	}

	providerRegistry = append(providerRegistry, &provider.providerKey)

	return provider
}

// initProviders fills c.providerMutators with the *mutatorInfo associated with each provider ID,
// if any.
func (c *Context) initProviders() {
	c.providerMutators = make([]*mutatorInfo, len(providerRegistry))
	for _, provider := range providerRegistry {
		for _, mutator := range c.mutatorInfo {
			if mutator.name == provider.mutator {
				c.providerMutators[provider.id] = mutator
			}
		}
	}
}

// setProvider sets the value for a provider on a moduleInfo.  Verifies that it is called during the
// appropriate mutator or GenerateBuildActions pass for the provider, and that the value is of the
// appropriate type.  The value should not be modified after being passed to setProvider.
//
// Once Go has generics the value parameter can be typed:
// setProvider(type T)(m *moduleInfo, provider ProviderKey(T), value T)
func (c *Context) setProvider(m *moduleInfo, provider *providerKey, value any) {
	if provider.mutator == "" {
		if !m.startedGenerateBuildActions {
			panic(fmt.Sprintf("Can't set value of provider %s before GenerateBuildActions started",
				provider.typ))
		} else if m.finishedGenerateBuildActions {
			panic(fmt.Sprintf("Can't set value of provider %s after GenerateBuildActions finished",
				provider.typ))
		}
	} else {
		expectedMutator := c.providerMutators[provider.id]
		if expectedMutator == nil {
			panic(fmt.Sprintf("Can't set value of provider %s associated with unregistered mutator %s",
				provider.typ, provider.mutator))
		} else if c.mutatorFinishedForModule(expectedMutator, m) {
			panic(fmt.Sprintf("Can't set value of provider %s after mutator %s finished",
				provider.typ, provider.mutator))
		} else if !c.mutatorStartedForModule(expectedMutator, m) {
			panic(fmt.Sprintf("Can't set value of provider %s before mutator %s started",
				provider.typ, provider.mutator))
		}
	}

	if m.providers == nil {
		m.providers = make([]any, len(providerRegistry))
	}

	if m.providers[provider.id] != nil {
		panic(fmt.Sprintf("Value of provider %s is already set", provider.typ))
	}

	m.providers[provider.id] = value

	if m.providerInitialValueHashes == nil {
		m.providerInitialValueHashes = make([]uint64, len(providerRegistry))
	}
	hash, err := proptools.CalculateHash(value)
	if err != nil {
		panic(fmt.Sprintf("Can't set value of provider %s: %s", provider.typ, err.Error()))
	}
	m.providerInitialValueHashes[provider.id] = hash
}

// provider returns the value, if any, for a given provider for a module.  Verifies that it is
// called after the appropriate mutator or GenerateBuildActions pass for the provider on the module.
// If the value for the provider was not set it returns nil.  The return value should always be considered read-only.
//
// Once Go has generics the return value can be typed and the type assert by callers can be dropped:
// provider(type T)(m *moduleInfo, provider ProviderKey(T)) T
func (c *Context) provider(m *moduleInfo, provider *providerKey) (any, bool) {
	if provider.mutator == "" {
		if !m.finishedGenerateBuildActions {
			panic(fmt.Sprintf("Can't get value of provider %s before GenerateBuildActions finished",
				provider.typ))
		}
	} else {
		expectedMutator := c.providerMutators[provider.id]
		if expectedMutator != nil && !c.mutatorFinishedForModule(expectedMutator, m) {
			panic(fmt.Sprintf("Can't get value of provider %s before mutator %s finished",
				provider.typ, provider.mutator))
		}
	}

	if len(m.providers) > provider.id {
		if p := m.providers[provider.id]; p != nil {
			return p, true
		}
	}

	return nil, false
}

func (c *Context) mutatorFinishedForModule(mutator *mutatorInfo, m *moduleInfo) bool {
	if c.finishedMutators[mutator.index] {
		// mutator pass finished for all modules
		return true
	}

	return m.finishedMutator >= mutator.index
}

func (c *Context) mutatorStartedForModule(mutator *mutatorInfo, m *moduleInfo) bool {
	if c.finishedMutators[mutator.index] {
		// mutator pass finished for all modules
		return true
	}

	return m.startedMutator >= mutator.index
}

// OtherModuleProviderContext is a helper interface that is a subset of ModuleContext, BottomUpMutatorContext, or
// TopDownMutatorContext for use in OtherModuleProvider.
type OtherModuleProviderContext interface {
	OtherModuleProvider(m Module, provider AnyProviderKey) (any, bool)
}

var _ OtherModuleProviderContext = BaseModuleContext(nil)
var _ OtherModuleProviderContext = ModuleContext(nil)
var _ OtherModuleProviderContext = BottomUpMutatorContext(nil)
var _ OtherModuleProviderContext = TopDownMutatorContext(nil)

// OtherModuleProvider reads the provider for the given module.  If the provider has been set the value is
// returned and the boolean is true.  If it has not been set the zero value of the provider's type  is returned
// and the boolean is false.  The value returned may be a deep copy of the value originally passed to SetProvider.
//
// OtherModuleProviderContext is a helper interface that accepts ModuleContext, BottomUpMutatorContext, or
// TopDownMutatorContext.
func OtherModuleProvider[K any](ctx OtherModuleProviderContext, module Module, provider ProviderKey[K]) (K, bool) {
	value, ok := ctx.OtherModuleProvider(module, provider)
	if !ok {
		var k K
		return k, false
	}
	return value.(K), ok
}

// SingletonModuleProviderContext is a helper interface that is a subset of Context and SingletonContext for use in
// SingletonModuleProvider.
type SingletonModuleProviderContext interface {
	ModuleProvider(m Module, provider AnyProviderKey) (any, bool)
}

var _ SingletonModuleProviderContext = &Context{}
var _ SingletonModuleProviderContext = SingletonContext(nil)

// SingletonModuleProvider reads the provider for the given module.  If the provider has been set the value is
// returned and the boolean is true.  If it has not been set the zero value of the provider's type  is returned
// and the boolean is false.  The value returned may be a deep copy of the value originally passed to SetProvider.
//
// SingletonModuleProviderContext is a helper interface that accepts Context or SingletonContext.
func SingletonModuleProvider[K any](ctx SingletonModuleProviderContext, module Module, provider ProviderKey[K]) (K, bool) {
	value, ok := ctx.ModuleProvider(module, provider)
	if !ok {
		var k K
		return k, false
	}
	return value.(K), ok
}

// ModuleProviderContext is a helper interface that is a subset of ModuleContext, BottomUpMutatorContext, or
// TopDownMutatorContext for use in ModuleProvider.
type ModuleProviderContext interface {
	Provider(provider AnyProviderKey) (any, bool)
}

var _ ModuleProviderContext = BaseModuleContext(nil)
var _ ModuleProviderContext = ModuleContext(nil)
var _ ModuleProviderContext = BottomUpMutatorContext(nil)
var _ ModuleProviderContext = TopDownMutatorContext(nil)

// ModuleProvider reads the provider for the current module.  If the provider has been set the value is
// returned and the boolean is true.  If it has not been set the zero value of the provider's type  is returned
// and the boolean is false.  The value returned may be a deep copy of the value originally passed to SetProvider.
//
// ModuleProviderContext is a helper interface that accepts ModuleContext, BottomUpMutatorContext, or
// TopDownMutatorContext.
func ModuleProvider[K any](ctx ModuleProviderContext, provider ProviderKey[K]) (K, bool) {
	value, ok := ctx.Provider(provider)
	if !ok {
		var k K
		return k, false
	}
	return value.(K), ok
}

// SetProviderContext is a helper interface that is a subset of ModuleContext, BottomUpMutatorContext, or
// TopDownMutatorContext for use in SetProvider.
type SetProviderContext interface {
	SetProvider(provider AnyProviderKey, value any)
}

var _ SetProviderContext = BaseModuleContext(nil)
var _ SetProviderContext = ModuleContext(nil)
var _ SetProviderContext = BottomUpMutatorContext(nil)
var _ SetProviderContext = TopDownMutatorContext(nil)

// SetProvider sets the value for a provider for the current module.  It panics if not called
// during the appropriate mutator or GenerateBuildActions pass for the provider, if the value
// is not of the appropriate type, or if the value has already been set.  The value should not
// be modified after being passed to SetProvider.
//
// SetProviderContext is a helper interface that accepts ModuleContext, BottomUpMutatorContext, or
// TopDownMutatorContext.
func SetProvider[K any](ctx SetProviderContext, provider ProviderKey[K], value K) {
	ctx.SetProvider(provider, value)
}
