// Copyright 2015 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 proptools

import (
	"fmt"
	"reflect"
)

// AppendProperties appends the values of properties in the property struct src to the property
// struct dst. dst and src must be the same type, and both must be pointers to structs.
//
// The filter function can prevent individual properties from being appended by returning false, or
// abort AppendProperties with an error by returning an error.  Passing nil for filter will append
// all properties.
//
// An error returned by AppendProperties that applies to a specific property will be an
// *ExtendPropertyError, and can have the property name and error extracted from it.
//
// The append operation is defined as appending strings, pointers to strings, and slices of
// strings normally, OR-ing bool values, replacing non-nil pointers to booleans, and recursing into
// embedded structs, pointers to structs, and interfaces containing
// pointers to structs.  Appending the zero value of a property will always be a no-op.
func AppendProperties(dst interface{}, src interface{}, filter ExtendPropertyFilterFunc) error {
	return extendProperties(dst, src, filter, false)
}

// PrependProperties prepends the values of properties in the property struct src to the property
// struct dst. dst and src must be the same type, and both must be pointers to structs.
//
// The filter function can prevent individual properties from being prepended by returning false, or
// abort PrependProperties with an error by returning an error.  Passing nil for filter will prepend
// all properties.
//
// An error returned by PrependProperties that applies to a specific property will be an
// *ExtendPropertyError, and can have the property name and error extracted from it.
//
// The prepend operation is defined as prepending strings, pointers to strings, and slices of
// strings normally, OR-ing bool values, replacing non-nil pointers to booleans, and recursing into
// embedded structs, pointers to structs, and interfaces containing
// pointers to structs.  Prepending the zero value of a property will always be a no-op.
func PrependProperties(dst interface{}, src interface{}, filter ExtendPropertyFilterFunc) error {
	return extendProperties(dst, src, filter, true)
}

// AppendMatchingProperties appends the values of properties in the property struct src to the
// property structs in dst.  dst and src do not have to be the same type, but every property in src
// must be found in at least one property in dst.  dst must be a slice of pointers to structs, and
// src must be a pointer to a struct.
//
// The filter function can prevent individual properties from being appended by returning false, or
// abort AppendProperties with an error by returning an error.  Passing nil for filter will append
// all properties.
//
// An error returned by AppendMatchingProperties that applies to a specific property will be an
// *ExtendPropertyError, and can have the property name and error extracted from it.
//
// The append operation is defined as appending strings, pointers to strings, and slices of
// strings normally, OR-ing bool values, replacing non-nil pointers to booleans, and recursing into
// embedded structs, pointers to structs, and interfaces containing
// pointers to structs.  Appending the zero value of a property will always be a no-op.
func AppendMatchingProperties(dst []interface{}, src interface{},
	filter ExtendPropertyFilterFunc) error {
	return extendMatchingProperties(dst, src, filter, false)
}

// PrependMatchingProperties prepends the values of properties in the property struct src to the
// property structs in dst.  dst and src do not have to be the same type, but every property in src
// must be found in at least one property in dst.  dst must be a slice of pointers to structs, and
// src must be a pointer to a struct.
//
// The filter function can prevent individual properties from being prepended by returning false, or
// abort PrependProperties with an error by returning an error.  Passing nil for filter will prepend
// all properties.
//
// An error returned by PrependProperties that applies to a specific property will be an
// *ExtendPropertyError, and can have the property name and error extracted from it.
//
// The prepend operation is defined as prepending strings, pointers to strings, and slices of
// strings normally, OR-ing bool values, replacing non-nil pointers to booleans, and recursing into
// embedded structs, pointers to structs, and interfaces containing
// pointers to structs.  Prepending the zero value of a property will always be a no-op.
func PrependMatchingProperties(dst []interface{}, src interface{},
	filter ExtendPropertyFilterFunc) error {
	return extendMatchingProperties(dst, src, filter, true)
}

type ExtendPropertyFilterFunc func(property string,
	dstField, srcField reflect.StructField,
	dstValue, srcValue interface{}) (bool, error)

type ExtendPropertyError struct {
	Err      error
	Property string
}

func (e *ExtendPropertyError) Error() string {
	return fmt.Sprintf("can't extend property %q: %s", e.Property, e.Err)
}

func extendPropertyErrorf(property string, format string, a ...interface{}) *ExtendPropertyError {
	return &ExtendPropertyError{
		Err:      fmt.Errorf(format, a...),
		Property: property,
	}
}

func extendProperties(dst interface{}, src interface{}, filter ExtendPropertyFilterFunc,
	prepend bool) error {

	dstValue, err := getStruct(dst)
	if err != nil {
		return err
	}
	srcValue, err := getStruct(src)
	if err != nil {
		return err
	}

	if dstValue.Type() != srcValue.Type() {
		return fmt.Errorf("expected matching types for dst and src, got %T and %T", dst, src)
	}

	dstValues := []reflect.Value{dstValue}

	return extendPropertiesRecursive(dstValues, srcValue, "", filter, true, prepend)
}

func extendMatchingProperties(dst []interface{}, src interface{}, filter ExtendPropertyFilterFunc,
	prepend bool) error {

	dstValues := make([]reflect.Value, len(dst))
	for i := range dst {
		var err error
		dstValues[i], err = getStruct(dst[i])
		if err != nil {
			return err
		}
	}

	srcValue, err := getStruct(src)
	if err != nil {
		return err
	}

	return extendPropertiesRecursive(dstValues, srcValue, "", filter, false, prepend)
}

func extendPropertiesRecursive(dstValues []reflect.Value, srcValue reflect.Value,
	prefix string, filter ExtendPropertyFilterFunc, sameTypes, prepend bool) error {

	srcType := srcValue.Type()
	for i := 0; i < srcValue.NumField(); i++ {
		srcField := srcType.Field(i)
		if srcField.PkgPath != "" {
			// The field is not exported so just skip it.
			continue
		}
		if HasTag(srcField, "blueprint", "mutated") {
			continue
		}

		propertyName := prefix + PropertyNameForField(srcField.Name)
		srcFieldValue := srcValue.Field(i)

		found := false
		for _, dstValue := range dstValues {
			dstType := dstValue.Type()
			var dstField reflect.StructField

			if dstType == srcType {
				dstField = dstType.Field(i)
			} else {
				var ok bool
				dstField, ok = dstType.FieldByName(srcField.Name)
				if !ok {
					continue
				}
			}

			found = true

			dstFieldValue := dstValue.FieldByIndex(dstField.Index)

			if srcFieldValue.Kind() != dstFieldValue.Kind() {
				return extendPropertyErrorf(propertyName, "mismatched types %s and %s",
					dstFieldValue.Type(), srcFieldValue.Type())
			}

			switch srcFieldValue.Kind() {
			case reflect.Interface:
				if dstFieldValue.IsNil() != srcFieldValue.IsNil() {
					return extendPropertyErrorf(propertyName, "nilitude mismatch")
				}
				if dstFieldValue.IsNil() {
					continue
				}

				dstFieldValue = dstFieldValue.Elem()
				srcFieldValue = srcFieldValue.Elem()

				if srcFieldValue.Kind() != reflect.Ptr || dstFieldValue.Kind() != reflect.Ptr {
					return extendPropertyErrorf(propertyName, "interface not a pointer")
				}

				fallthrough
			case reflect.Ptr:
				ptrKind := srcFieldValue.Type().Elem().Kind()
				if ptrKind == reflect.Bool || ptrKind == reflect.String {
					if srcFieldValue.Type() != dstFieldValue.Type() {
						return extendPropertyErrorf(propertyName, "mismatched pointer types %s and %s",
							dstFieldValue.Type(), srcFieldValue.Type())
					}
					break
				} else if ptrKind != reflect.Struct {
					return extendPropertyErrorf(propertyName, "pointer is a %s", ptrKind)
				}

				// Pointer to a struct
				if dstFieldValue.IsNil() != srcFieldValue.IsNil() {
					return extendPropertyErrorf(propertyName, "nilitude mismatch")
				}
				if dstFieldValue.IsNil() {
					continue
				}

				dstFieldValue = dstFieldValue.Elem()
				srcFieldValue = srcFieldValue.Elem()

				fallthrough
			case reflect.Struct:
				if sameTypes && dstFieldValue.Type() != srcFieldValue.Type() {
					return extendPropertyErrorf(propertyName, "mismatched types %s and %s",
						dstFieldValue.Type(), srcFieldValue.Type())
				}

				// Recursively extend the struct's fields.
				err := extendPropertiesRecursive([]reflect.Value{dstFieldValue}, srcFieldValue,
					propertyName+".", filter, sameTypes, prepend)
				if err != nil {
					return err
				}
				continue
			case reflect.Bool, reflect.String, reflect.Slice:
				if srcFieldValue.Type() != dstFieldValue.Type() {
					return extendPropertyErrorf(propertyName, "mismatched types %s and %s",
						dstFieldValue.Type(), srcFieldValue.Type())
				}
			default:
				return extendPropertyErrorf(propertyName, "unsupported kind %s",
					srcFieldValue.Kind())
			}

			if filter != nil {
				b, err := filter(propertyName, dstField, srcField,
					dstFieldValue.Interface(), srcFieldValue.Interface())
				if err != nil {
					return &ExtendPropertyError{
						Property: propertyName,
						Err:      err,
					}
				}
				if !b {
					continue
				}
			}

			switch srcFieldValue.Kind() {
			case reflect.Bool:
				// Boolean OR
				dstFieldValue.Set(reflect.ValueOf(srcFieldValue.Bool() || dstFieldValue.Bool()))
			case reflect.String:
				// Append the extension string.
				if prepend {
					dstFieldValue.SetString(srcFieldValue.String() +
						dstFieldValue.String())
				} else {
					dstFieldValue.SetString(dstFieldValue.String() +
						srcFieldValue.String())
				}
			case reflect.Slice:
				if srcFieldValue.IsNil() {
					break
				}

				newSlice := reflect.MakeSlice(srcFieldValue.Type(), 0,
					dstFieldValue.Len()+srcFieldValue.Len())
				if prepend {
					newSlice = reflect.AppendSlice(newSlice, srcFieldValue)
					newSlice = reflect.AppendSlice(newSlice, dstFieldValue)
				} else {
					newSlice = reflect.AppendSlice(newSlice, dstFieldValue)
					newSlice = reflect.AppendSlice(newSlice, srcFieldValue)
				}
				dstFieldValue.Set(newSlice)
			case reflect.Ptr:
				if srcFieldValue.IsNil() {
					break
				}

				switch ptrKind := srcFieldValue.Type().Elem().Kind(); ptrKind {
				case reflect.Bool:
					if prepend {
						if dstFieldValue.IsNil() {
							dstFieldValue.Set(reflect.ValueOf(BoolPtr(srcFieldValue.Elem().Bool())))
						}
					} else {
						// For append, replace the original value.
						dstFieldValue.Set(reflect.ValueOf(BoolPtr(srcFieldValue.Elem().Bool())))
					}
				case reflect.String:
					dstStr := ""
					if !dstFieldValue.IsNil() {
						dstStr = dstFieldValue.Elem().String()
					}
					if prepend {
						dstFieldValue.Set(reflect.ValueOf(StringPtr(srcFieldValue.Elem().String() + dstStr)))
					} else {
						dstFieldValue.Set(reflect.ValueOf(StringPtr(dstStr + srcFieldValue.Elem().String())))
					}
				default:
					panic(fmt.Errorf("unexpected pointer kind %s", ptrKind))
				}
			}
		}
		if !found {
			return extendPropertyErrorf(propertyName, "failed to find property to extend")
		}
	}

	return nil
}

func getStruct(in interface{}) (reflect.Value, error) {
	value := reflect.ValueOf(in)
	if value.Kind() != reflect.Ptr {
		return reflect.Value{}, fmt.Errorf("expected pointer to struct, got %T", in)
	}
	value = value.Elem()
	if value.Kind() != reflect.Struct {
		return reflect.Value{}, fmt.Errorf("expected pointer to struct, got %T", in)
	}
	return value, nil
}
