// Copyright (C) 2016 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 analysis

import (
	"fmt"
	"sort"
	"strings"

	"android.googlesource.com/platform/tools/gpu/api/semantic"
)

// Value interface compliance check.
var _ = Value(&MapValue{})

// MapValue is an implementation of Value that represents a map variable.
// Map entries are stored in the KeyToValue and ValueToKey fields. These two
// maps are always kept in sync.
//
// MapValue attempts to reduce the number of entries stored to a minimum to
// maintain decent performance while also trying to keep enough information to
// provide useful information (avoid tending towards unbounded keys and values).
//
// All insertions and merges use the following method when merging the key value
// pair (k, v) into the map:
//  • If m contains an equivalent key to k, then change the existing value to be
//    a union of the existing value and v.
//  • If m contains an equivalent value to v, then change the existing key to be
//    a union of the existing key and k.
//  • If m does not contain an equivalent key to k or an equivalent value to v
//    then add a new entry to m.
type MapValue struct {
	// The map type.
	Map *semantic.Map

	// A map of keys to values. The inverse of ValueToKey.
	KeyToValue map[Value]Value

	// A map of values to keys. The inverse of KeyToValue.
	ValueToKey map[Value]Value
}

func (v *MapValue) String() string {
	parts := make([]string, 0, len(v.KeyToValue))
	for k, v := range v.KeyToValue {
		parts = append(parts, fmt.Sprintf("<%v: %v>", k, v))
	}
	sort.Strings(parts)
	return fmt.Sprintf("{ %v }", strings.Join(parts, ", "))
}

// Print returns a textual representation of the value.
func (v *MapValue) Print(results *Results) string {
	parts := make([]string, 0, len(v.KeyToValue))
	for k, v := range v.KeyToValue {
		parts = append(parts, fmt.Sprintf("<%v: %v>", k.Print(results), v.Print(results)))
	}
	sort.Strings(parts)
	return fmt.Sprintf("{ %v }", strings.Join(parts, ", "))
}

// Type returns the semantic map type of the value.
func (v *MapValue) Type() semantic.Type {
	return v.Map
}

// Equivalent returns false as maps do not support equivalency tests.
func (v *MapValue) Equivalent(o Value) bool {
	return false // Maps don't do equivalency.
}

// Equals returns False as maps do not support equality tests.
func (v *MapValue) Equals(o Value) Possibility {
	return False // Maps don't do equality.
}

// Valid returns true.
func (v *MapValue) Valid() bool {
	return true
}

// Union (∪) returns a map value with all the keys of v and o mapped to their
// respective values.
// o must be of type *MapValue.
func (v *MapValue) Union(o Value) Value {
	if v == o {
		return v
	}
	out := v.Clone().(*MapValue)
	for key, val := range o.(*MapValue).KeyToValue {
		out.mergeInline(key, val)
	}
	return out
}

// Intersect is not supported by MapValue and will panic if called.
func (v *MapValue) Intersect(o Value) Value {
	panic("Intersect not implemented for maps")
}

// Difference is not supported by MapValue and will panic if called.
func (v *MapValue) Difference(o Value) Value {
	panic("Difference not implemented for maps")
}

// Clone returns a copy of v with a unique pointer.
func (v *MapValue) Clone() Value {
	out := &MapValue{
		Map:        v.Map,
		KeyToValue: make(map[Value]Value, len(v.KeyToValue)),
		ValueToKey: make(map[Value]Value, len(v.KeyToValue)),
	}
	for k, v := range v.KeyToValue {
		out.KeyToValue[k] = v
		out.ValueToKey[v] = k
	}
	return out
}

// ContainsKey returns the possibility of the key existing in the map.
func (v *MapValue) ContainsKey(key Value) Possibility {
	result := False
	for k := range v.KeyToValue {
		switch k.Equals(key) {
		case Maybe:
			result = Maybe
		case True:
			return True
		}
	}
	return result
}

// Put returns a copy of v with the new mapping of key to val.
func (v *MapValue) Put(key, val Value) *MapValue {
	out := v.Clone().(*MapValue)
	if k, v := out.findEqualByKey(key); k != nil {
		delete(out.KeyToValue, k)
		delete(out.ValueToKey, v)
	}
	out.mergeInline(key, val)
	return out
}

// Get return the union of all values that might have a key equal to key.
func (v *MapValue) Get(s *scope, key Value) Value {
	candidates := []Value{}
	for k, v := range v.KeyToValue {
		if k.Equals(key).MaybeTrue() {
			candidates = append(candidates, v)
		}
	}
	if len(candidates) == 0 {
		// TODO: Track potential invalid map index.
		return s.unknownOf(v.Map.ValueType)
	}
	return unionOf(candidates...)
}

// findEqualByKey looks for an existing key in v that is equal to keyin,
// returning the existing key and value if found. If no key equal to keyin
// is found then (nil, nil) is returned.
func (v *MapValue) findEqualByKey(keyin Value) (key, val Value) {
	if val, ok := v.KeyToValue[keyin]; ok {
		return keyin, val
	}
	for k, v := range v.KeyToValue {
		if k.Equals(keyin) == True {
			return k, v
		}
	}
	return nil, nil
}

// findEquivalentByKey looks for an existing key in v that is equivalent to
// keyin, returning the existing key and value if found. If no key equivalent to
// keyin is found then (nil, nil) is returned.
func (v *MapValue) findEquivalentByKey(keyin Value) (key, val Value) {
	if val, ok := v.KeyToValue[keyin]; ok {
		return keyin, val
	}
	for k, v := range v.KeyToValue {
		if k.Equivalent(keyin) {
			return k, v
		}
	}
	return nil, nil
}

// findEquivalentByVal looks for an existing value in v that is equivalent to
// valin, returning the existing key and value if found. If no value equivalent
// to valin is found then (nil, nil) is returned.
func (v *MapValue) findEquivalentByVal(valin Value) (key, val Value) {
	if key, ok := v.ValueToKey[valin]; ok {
		return key, valin
	}
	for v, k := range v.ValueToKey {
		if v.Equivalent(valin) {
			return k, v
		}
	}
	return nil, nil
}

// mergeInline merges the key-val pair into the map v using the method described
// in the MapValue documentation.
func (v *MapValue) mergeInline(key, val Value) {
	if !key.Valid() {
		panic("Attempting to put invalid key into map")
	}
	if existingKey, existingVal := v.findEquivalentByKey(key); existingVal != nil {
		delete(v.KeyToValue, existingKey)
		delete(v.ValueToKey, existingVal)
		val = val.Union(existingVal)
	}
	if existingKey, existingVal := v.findEquivalentByVal(val); existingKey != nil {
		delete(v.KeyToValue, existingKey)
		delete(v.ValueToKey, existingVal)
		key = key.Union(existingKey)
	}
	v.KeyToValue[key] = val
	v.ValueToKey[val] = key
}
