package starmap

import (
	"errors"
	"os"
)

func (stack *StarStackMem) Count() int {
	stack.kvPushmu.Lock()
	defer stack.kvPushmu.Unlock()
	return len(stack.kvStack)
}

func (stack *StarStackMem) Push(val interface{}) error {
	stack.kvPushmu.Lock()
	defer stack.kvPushmu.Unlock()
	stack.kvStack = append(stack.kvStack, val)
	return nil
}

func (stack *StarStackMem) Pop() (interface{}, error) {
	stack.kvPushmu.Lock()
	defer stack.kvPushmu.Unlock()
	if len(stack.kvStack) == 0 {
		return nil, errors.New("Empty Stacks")
	}
	val := stack.kvStack[0]
	stack.kvStack = stack.kvStack[1:]
	return val, nil
}

func (stack *StarStackMem) MustPop() interface{} {
	val, _ := stack.Pop()
	return val
}

func Get(key interface{}) (interface{}, error) {
	return globalMap.Get(key)
}

func (m *StarMapKV) Get(key interface{}) (interface{}, error) {
	var err error
	m.mu.RLock()
	defer m.mu.RUnlock()
	data, ok := m.kvMap[key]
	if !ok {
		err = os.ErrNotExist
	}
	return data, err
}

func (m *StarMapKV) MustGet(key interface{}) interface{} {
	result, _ := m.Get(key)
	return result
}
func MustGet(key interface{}) interface{} {
	return globalMap.MustGet(key)
}

func Store(key interface{}, value interface{}) error {
	return globalMap.Store(key, value)
}
func (m *StarMapKV) Store(key interface{}, value interface{}) error {
	m.mu.Lock()
	defer m.mu.Unlock()
	m.kvMap[key] = value
	return nil
}

func Exists(key interface{}) bool {
	return globalMap.Exists(key)
}

func (m *StarMapKV) Exists(key interface{}) bool {
	m.mu.RLock()
	defer m.mu.RUnlock()
	_, ok := m.kvMap[key]
	return ok
}

func Delete(key interface{}) error {
	return globalMap.Delete(key)
}
func (m *StarMapKV) Delete(key interface{}) error {
	m.mu.Lock()
	defer m.mu.Unlock()
	delete(m.kvMap, key)
	return nil
}

func Range(run func(k interface{}, v interface{}) bool) error {
	return globalMap.Range(run)
}

func (m *StarMapKV) Range(run func(k interface{}, v interface{}) bool) error {
	for k, v := range m.kvMap {
		if !run(k, v) {
			break
		}
	}
	return nil
}
