// Copyright (C) 2021 The Android Open Source Project
//
// 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 sdk

import (
	"fmt"
	"math"
	"reflect"
	"strings"
)

// Supports customizing sdk snapshot output based on target build release.

// buildRelease represents the version of a build system used to create a specific release.
//
// The name of the release, is the same as the code for the dessert release, e.g. S, Tiramisu, etc.
type buildRelease struct {
	// The name of the release, e.g. S, Tiramisu, etc.
	name string

	// The index of this structure within the dessertBuildReleases list.
	//
	// The buildReleaseCurrent does not appear in the dessertBuildReleases list as it has an ordinal value
	// that is larger than the size of the dessertBuildReleases.
	ordinal int
}

func (br *buildRelease) EarlierThan(other *buildRelease) bool {
	return br.ordinal < other.ordinal
}

// String returns the name of the build release.
func (br *buildRelease) String() string {
	return br.name
}

// buildReleaseSet represents a set of buildRelease objects.
type buildReleaseSet struct {
	// Set of *buildRelease represented as a map from *buildRelease to struct{}.
	contents map[*buildRelease]struct{}
}

// addItem adds a build release to the set.
func (s *buildReleaseSet) addItem(release *buildRelease) {
	s.contents[release] = struct{}{}
}

// addRange adds all the build releases from start (inclusive) to end (inclusive).
func (s *buildReleaseSet) addRange(start *buildRelease, end *buildRelease) {
	for i := start.ordinal; i <= end.ordinal; i += 1 {
		s.addItem(dessertBuildReleases[i])
	}
}

// contains returns true if the set contains the specified build release.
func (s *buildReleaseSet) contains(release *buildRelease) bool {
	_, ok := s.contents[release]
	return ok
}

// String returns a string representation of the set, sorted from earliest to latest release.
func (s *buildReleaseSet) String() string {
	list := []string{}
	addRelease := func(release *buildRelease) {
		if _, ok := s.contents[release]; ok {
			list = append(list, release.name)
		}
	}
	// Add the names of the build releases in this set in the order in which they were created.
	for _, release := range dessertBuildReleases {
		addRelease(release)
	}
	// Always add "current" to the list of names last if it is present in the set.
	addRelease(buildReleaseCurrent)
	return fmt.Sprintf("[%s]", strings.Join(list, ","))
}

var (
	// nameToBuildRelease contains a map from name to build release.
	nameToBuildRelease = map[string]*buildRelease{}

	// dessertBuildReleases lists all the available dessert build releases, i.e. excluding current.
	dessertBuildReleases = []*buildRelease{}

	// allBuildReleaseSet is the set of all build releases.
	allBuildReleaseSet = &buildReleaseSet{contents: map[*buildRelease]struct{}{}}

	// Add the dessert build releases from oldest to newest.
	buildReleaseS = initBuildRelease("S")
	buildReleaseT = initBuildRelease("Tiramisu")
	buildReleaseU = initBuildRelease("UpsideDownCake")

	// Add the current build release which is always treated as being more recent than any other
	// build release, including those added in tests.
	buildReleaseCurrent = initBuildRelease("current")
)

// initBuildRelease creates a new build release with the specified name.
func initBuildRelease(name string) *buildRelease {
	ordinal := len(dessertBuildReleases)
	if name == "current" {
		// The current build release is more recent than all other build releases, including those
		// created in tests so use the max int value. It cannot just rely on being created after all
		// the other build releases as some are created in tests which run after the current build
		// release has been created.
		ordinal = math.MaxInt
	}
	release := &buildRelease{name: name, ordinal: ordinal}
	nameToBuildRelease[name] = release
	allBuildReleaseSet.addItem(release)
	if name != "current" {
		// As the current build release has an ordinal value that does not correspond to its position
		// in the dessertBuildReleases list do not add it to the list.
		dessertBuildReleases = append(dessertBuildReleases, release)
	}
	return release
}

// latestDessertBuildRelease returns the latest dessert release build name, i.e. the last dessert
// release added to the list, which does not include current.
func latestDessertBuildRelease() *buildRelease {
	return dessertBuildReleases[len(dessertBuildReleases)-1]
}

// nameToRelease maps from build release name to the corresponding build release (if it exists) or
// the error if it does not.
func nameToRelease(name string) (*buildRelease, error) {
	if r, ok := nameToBuildRelease[name]; ok {
		return r, nil
	}

	return nil, fmt.Errorf("unknown release %q, expected one of %s", name, allBuildReleaseSet)
}

// parseBuildReleaseSet parses a build release set string specification into a build release set.
//
// The specification consists of one of the following:
// * a single build release name, e.g. S, T, etc.
// * a closed range (inclusive to inclusive), e.g. S-T
// * an open range, e.g. T+.
//
// This returns the set if the specification was valid or an error.
func parseBuildReleaseSet(specification string) (*buildReleaseSet, error) {
	set := &buildReleaseSet{contents: map[*buildRelease]struct{}{}}

	if strings.HasSuffix(specification, "+") {
		rangeStart := strings.TrimSuffix(specification, "+")
		start, err := nameToRelease(rangeStart)
		if err != nil {
			return nil, err
		}
		end := latestDessertBuildRelease()
		set.addRange(start, end)
		// An open-ended range always includes the current release.
		set.addItem(buildReleaseCurrent)
	} else if strings.Contains(specification, "-") {
		limits := strings.SplitN(specification, "-", 2)
		start, err := nameToRelease(limits[0])
		if err != nil {
			return nil, err
		}

		end, err := nameToRelease(limits[1])
		if err != nil {
			return nil, err
		}

		if start.ordinal > end.ordinal {
			return nil, fmt.Errorf("invalid closed range, start release %q is later than end release %q", start.name, end.name)
		}

		set.addRange(start, end)
	} else {
		release, err := nameToRelease(specification)
		if err != nil {
			return nil, err
		}
		set.addItem(release)
	}

	return set, nil
}

// Given a set of properties (struct value), set the value of a field within that struct (or one of
// its embedded structs) to its zero value.
type fieldPrunerFunc func(structValue reflect.Value)

// A property that can be cleared by a propertyPruner.
type prunerProperty struct {
	// The name of the field for this property. It is a "."-separated path for fields in non-anonymous
	// sub-structs.
	name string

	// Sets the associated field to its zero value.
	prunerFunc fieldPrunerFunc
}

// propertyPruner provides support for pruning (i.e. setting to their zero value) properties from
// a properties structure.
type propertyPruner struct {
	// The properties that the pruner will clear.
	properties []prunerProperty
}

// gatherFields recursively processes the supplied structure and a nested structures, selecting the
// fields that require pruning and populates the propertyPruner.properties with the information
// needed to prune those fields.
//
// containingStructAccessor is a func that if given an object will return a field whose value is
// of the supplied structType. It is nil on initial entry to this method but when this method is
// called recursively on a field that is a nested structure containingStructAccessor is set to a
// func that provides access to the field's value.
//
// namePrefix is the prefix to the fields that are being visited. It is "" on initial entry to this
// method but when this method is called recursively on a field that is a nested structure
// namePrefix is the result of appending the field name (plus a ".") to the previous name prefix.
// Unless the field is anonymous in which case it is passed through unchanged.
//
// selector is a func that will select whether the supplied field requires pruning or not. If it
// returns true then the field will be added to those to be pruned, otherwise it will not.
func (p *propertyPruner) gatherFields(structType reflect.Type, containingStructAccessor fieldAccessorFunc, namePrefix string, selector fieldSelectorFunc) {
	for f := 0; f < structType.NumField(); f++ {
		field := structType.Field(f)
		if field.PkgPath != "" {
			// Ignore unexported fields.
			continue
		}

		// Save a copy of the field index for use in the function.
		fieldIndex := f

		name := namePrefix + field.Name

		fieldGetter := func(container reflect.Value) reflect.Value {
			if containingStructAccessor != nil {
				// This is an embedded structure so first access the field for the embedded
				// structure.
				container = containingStructAccessor(container)
			}

			// Skip through interface and pointer values to find the structure.
			container = getStructValue(container)

			defer func() {
				if r := recover(); r != nil {
					panic(fmt.Errorf("%s for fieldIndex %d of field %s of container %#v", r, fieldIndex, name, container.Interface()))
				}
			}()

			// Return the field.
			return container.Field(fieldIndex)
		}

		fieldType := field.Type
		if selector(name, field) {
			zeroValue := reflect.Zero(fieldType)
			fieldPruner := func(container reflect.Value) {
				if containingStructAccessor != nil {
					// This is an embedded structure so first access the field for the embedded
					// structure.
					container = containingStructAccessor(container)
				}

				// Skip through interface and pointer values to find the structure.
				container = getStructValue(container)

				defer func() {
					if r := recover(); r != nil {
						panic(fmt.Errorf("%s\n\tfor field (index %d, name %s)", r, fieldIndex, name))
					}
				}()

				// Set the field.
				container.Field(fieldIndex).Set(zeroValue)
			}

			property := prunerProperty{
				name,
				fieldPruner,
			}
			p.properties = append(p.properties, property)
		} else {
			switch fieldType.Kind() {
			case reflect.Struct:
				// Gather fields from the nested or embedded structure.
				var subNamePrefix string
				if field.Anonymous {
					subNamePrefix = namePrefix
				} else {
					subNamePrefix = name + "."
				}
				p.gatherFields(fieldType, fieldGetter, subNamePrefix, selector)

			case reflect.Map:
				// Get the type of the values stored in the map.
				valueType := fieldType.Elem()
				// Skip over * types.
				if valueType.Kind() == reflect.Ptr {
					valueType = valueType.Elem()
				}
				if valueType.Kind() == reflect.Struct {
					// If this is not referenced by a pointer then it is an error as it is impossible to
					// modify a struct that is stored directly as a value in a map.
					if fieldType.Elem().Kind() != reflect.Ptr {
						panic(fmt.Errorf("Cannot prune struct %s stored by value in map %s, map values must"+
							" be pointers to structs",
							fieldType.Elem(), name))
					}

					// Create a new pruner for the values of the map.
					valuePruner := newPropertyPrunerForStructType(valueType, selector)

					// Create a new fieldPruner that will iterate over all the items in the map and call the
					// pruner on them.
					fieldPruner := func(container reflect.Value) {
						mapValue := fieldGetter(container)

						for _, keyValue := range mapValue.MapKeys() {
							itemValue := mapValue.MapIndex(keyValue)

							defer func() {
								if r := recover(); r != nil {
									panic(fmt.Errorf("%s\n\tfor key %q", r, keyValue))
								}
							}()

							valuePruner.pruneProperties(itemValue.Interface())
						}
					}

					// Add the map field pruner to the list of property pruners.
					property := prunerProperty{
						name + "[*]",
						fieldPruner,
					}
					p.properties = append(p.properties, property)
				}
			}
		}
	}
}

// pruneProperties will prune (set to zero value) any properties in the struct referenced by the
// supplied struct pointer.
//
// The struct must be of the same type as was originally passed to newPropertyPruner to create this
// propertyPruner.
func (p *propertyPruner) pruneProperties(propertiesStruct interface{}) {

	defer func() {
		if r := recover(); r != nil {
			panic(fmt.Errorf("%s\n\tof container %#v", r, propertiesStruct))
		}
	}()

	structValue := reflect.ValueOf(propertiesStruct)
	for _, property := range p.properties {
		property.prunerFunc(structValue)
	}
}

// fieldSelectorFunc is called to select whether a specific field should be pruned or not.
// name is the name of the field, including any prefixes from containing str
type fieldSelectorFunc func(name string, field reflect.StructField) bool

// newPropertyPruner creates a new property pruner for the structure type for the supplied
// properties struct.
//
// The returned pruner can be used on any properties structure of the same type as the supplied set
// of properties.
func newPropertyPruner(propertiesStruct interface{}, selector fieldSelectorFunc) *propertyPruner {
	structType := getStructValue(reflect.ValueOf(propertiesStruct)).Type()
	return newPropertyPrunerForStructType(structType, selector)
}

// newPropertyPruner creates a new property pruner for the supplied properties struct type.
//
// The returned pruner can be used on any properties structure of the supplied type.
func newPropertyPrunerForStructType(structType reflect.Type, selector fieldSelectorFunc) *propertyPruner {
	pruner := &propertyPruner{}
	pruner.gatherFields(structType, nil, "", selector)
	return pruner
}

// newPropertyPrunerByBuildRelease creates a property pruner that will clear any properties in the
// structure which are not supported by the specified target build release.
//
// A property is pruned if its field has a tag of the form:
//
//	`supported_build_releases:"<build-release-set>"`
//
// and the resulting build release set does not contain the target build release. Properties that
// have no such tag are assumed to be supported by all releases.
func newPropertyPrunerByBuildRelease(propertiesStruct interface{}, targetBuildRelease *buildRelease) *propertyPruner {
	return newPropertyPruner(propertiesStruct, func(name string, field reflect.StructField) bool {
		if supportedBuildReleases, ok := field.Tag.Lookup("supported_build_releases"); ok {
			set, err := parseBuildReleaseSet(supportedBuildReleases)
			if err != nil {
				panic(fmt.Errorf("invalid `supported_build_releases` tag on %s of %T: %s", name, propertiesStruct, err))
			}

			// If the field does not support tha target release then prune it.
			return !set.contains(targetBuildRelease)

		} else {
			// Any untagged fields are assumed to be supported by all build releases so should never be
			// pruned.
			return false
		}
	})
}
