// Copyright (c) HashiCorp, Inc.
// SPDX-License-Identifier: MPL-2.0

package schema

import (
	"bytes"
	"fmt"
	"reflect"
	"sort"
	"strconv"
	"sync"

	"github.com/hashicorp/terraform/internal/legacy/helper/hashcode"
)

// HashString hashes strings. If you want a Set of strings, this is the
// SchemaSetFunc you want.
func HashString(v interface{}) int {
	return hashcode.String(v.(string))
}

// HashInt hashes integers. If you want a Set of integers, this is the
// SchemaSetFunc you want.
func HashInt(v interface{}) int {
	return hashcode.String(strconv.Itoa(v.(int)))
}

// HashResource hashes complex structures that are described using
// a *Resource. This is the default set implementation used when a set's
// element type is a full resource.
func HashResource(resource *Resource) SchemaSetFunc {
	return func(v interface{}) int {
		var buf bytes.Buffer
		SerializeResourceForHash(&buf, v, resource)
		return hashcode.String(buf.String())
	}
}

// HashSchema hashes values that are described using a *Schema. This is the
// default set implementation used when a set's element type is a single
// schema.
func HashSchema(schema *Schema) SchemaSetFunc {
	return func(v interface{}) int {
		var buf bytes.Buffer
		SerializeValueForHash(&buf, v, schema)
		return hashcode.String(buf.String())
	}
}

// Set is a set data structure that is returned for elements of type
// TypeSet.
type Set struct {
	F SchemaSetFunc

	m    map[string]interface{}
	once sync.Once
}

// NewSet is a convenience method for creating a new set with the given
// items.
func NewSet(f SchemaSetFunc, items []interface{}) *Set {
	s := &Set{F: f}
	for _, i := range items {
		s.Add(i)
	}

	return s
}

// CopySet returns a copy of another set.
func CopySet(otherSet *Set) *Set {
	return NewSet(otherSet.F, otherSet.List())
}

// Add adds an item to the set if it isn't already in the set.
func (s *Set) Add(item interface{}) {
	s.add(item, false)
}

// Remove removes an item if it's already in the set. Idempotent.
func (s *Set) Remove(item interface{}) {
	s.remove(item)
}

// Contains checks if the set has the given item.
func (s *Set) Contains(item interface{}) bool {
	_, ok := s.m[s.hash(item)]
	return ok
}

// Len returns the amount of items in the set.
func (s *Set) Len() int {
	return len(s.m)
}

// List returns the elements of this set in slice format.
//
// The order of the returned elements is deterministic. Given the same
// set, the order of this will always be the same.
func (s *Set) List() []interface{} {
	result := make([]interface{}, len(s.m))
	for i, k := range s.listCode() {
		result[i] = s.m[k]
	}

	return result
}

// Difference performs a set difference of the two sets, returning
// a new third set that has only the elements unique to this set.
func (s *Set) Difference(other *Set) *Set {
	result := &Set{F: s.F}
	result.once.Do(result.init)

	for k, v := range s.m {
		if _, ok := other.m[k]; !ok {
			result.m[k] = v
		}
	}

	return result
}

// Intersection performs the set intersection of the two sets
// and returns a new third set.
func (s *Set) Intersection(other *Set) *Set {
	result := &Set{F: s.F}
	result.once.Do(result.init)

	for k, v := range s.m {
		if _, ok := other.m[k]; ok {
			result.m[k] = v
		}
	}

	return result
}

// Union performs the set union of the two sets and returns a new third
// set.
func (s *Set) Union(other *Set) *Set {
	result := &Set{F: s.F}
	result.once.Do(result.init)

	for k, v := range s.m {
		result.m[k] = v
	}
	for k, v := range other.m {
		result.m[k] = v
	}

	return result
}

func (s *Set) Equal(raw interface{}) bool {
	other, ok := raw.(*Set)
	if !ok {
		return false
	}

	return reflect.DeepEqual(s.m, other.m)
}

// HashEqual simply checks to the keys the top-level map to the keys in the
// other set's top-level map to see if they are equal. This obviously assumes
// you have a properly working hash function - use HashResource if in doubt.
func (s *Set) HashEqual(raw interface{}) bool {
	other, ok := raw.(*Set)
	if !ok {
		return false
	}

	ks1 := make([]string, 0)
	ks2 := make([]string, 0)

	for k := range s.m {
		ks1 = append(ks1, k)
	}
	for k := range other.m {
		ks2 = append(ks2, k)
	}

	sort.Strings(ks1)
	sort.Strings(ks2)

	return reflect.DeepEqual(ks1, ks2)
}

func (s *Set) GoString() string {
	return fmt.Sprintf("*Set(%#v)", s.m)
}

func (s *Set) init() {
	s.m = make(map[string]interface{})
}

func (s *Set) add(item interface{}, computed bool) string {
	s.once.Do(s.init)

	code := s.hash(item)
	if computed {
		code = "~" + code

		if isProto5() {
			tmpCode := code
			count := 0
			for _, exists := s.m[tmpCode]; exists; _, exists = s.m[tmpCode] {
				count++
				tmpCode = fmt.Sprintf("%s%d", code, count)
			}
			code = tmpCode
		}
	}

	if _, ok := s.m[code]; !ok {
		s.m[code] = item
	}

	return code
}

func (s *Set) hash(item interface{}) string {
	code := s.F(item)
	// Always return a nonnegative hashcode.
	if code < 0 {
		code = -code
	}
	return strconv.Itoa(code)
}

func (s *Set) remove(item interface{}) string {
	s.once.Do(s.init)

	code := s.hash(item)
	delete(s.m, code)

	return code
}

func (s *Set) index(item interface{}) int {
	return sort.SearchStrings(s.listCode(), s.hash(item))
}

func (s *Set) listCode() []string {
	// Sort the hash codes so the order of the list is deterministic
	keys := make([]string, 0, len(s.m))
	for k := range s.m {
		keys = append(keys, k)
	}
	sort.Sort(sort.StringSlice(keys))
	return keys
}
