package main

import (
	"fmt"
	"sync"

	"github.com/google/uuid"
)

var (
	mu          sync.RWMutex
	CacheUsers  = make(map[uint32]*User)
	CacheGroups = make(map[uint32]*Group)
)

func CacheGetUserById(id uint32) (*User, error) {
	mu.RLock()
	defer mu.RUnlock()

	user, ok := CacheUsers[id]
	if !ok {
		return nil, fmt.Errorf("user %d not found", id)
	}
	return user, nil
}

func CacheGetUserByName(name string) (*User, error) {
	mu.RLock()
	defer mu.RUnlock()

	for _, user := range CacheUsers {
		if user.Name == name {
			return user, nil
		}
	}
	return nil, fmt.Errorf("user %s not found", name)
}

func CacheSaveUser(user *User) {
	mu.Lock()
	defer mu.Unlock()

	CacheUsers[user.Id] = user
}

func CacheDeleteUser(id uint32) {
	mu.Lock()
	defer mu.Unlock()

	delete(CacheUsers, id)
}

func CacheSaveGroup(group *Group) {
	mu.Lock()
	defer mu.Unlock()

	CacheGroups[group.Id] = group
}

func CacheDeleteGroup(id uint32) {
	mu.Lock()
	defer mu.Unlock()
	delete(CacheGroups, id)
}

func CacheAddConnection(a, b *User, conn *Connection) {
	first, second := a, b
	if a.Id > b.Id {
		first, second = b, a
	}
	first.Mu.Lock()
	second.Mu.Lock()
	a.Connections[conn.Id] = conn
	b.Connections[conn.Id] = conn
	second.Mu.Unlock()
	first.Mu.Unlock()
}

func CacheDeleteConnection(a, b *User, id uuid.UUID) {
	first, second := a, b
	if a.Id > b.Id {
		first, second = b, a
	}
	first.Mu.Lock()
	second.Mu.Lock()
	delete(a.Connections, id)
	delete(b.Connections, id)
	second.Mu.Unlock()
	first.Mu.Unlock()
}

func CacheGetConnection(user *User, id uuid.UUID) (*Connection, bool) {
	user.Mu.RLock()
	defer user.Mu.RUnlock()
	conn, ok := user.Connections[id]
	return conn, ok
}

func CacheGetGroup(id uint32) (*Group, error) {
	mu.RLock()
	defer mu.RUnlock()

	group, ok := CacheGroups[id]
	if !ok {
		return nil, fmt.Errorf("group %d not found", id)
	}

	return group, nil
}
