package main

import (
	"context"
	"errors"
	"sync"

	"golang.org/x/crypto/bcrypt"
)

var (
	mu         sync.RWMutex
	clients    = make(map[uint32]*Client)
	chatGroups = make(map[uint32]ChatGroup)
)

func CreateGroup(ctx context.Context, chatGroup *ChatGroup) {
	mu.Lock()
	defer mu.Unlock()
	chatGroups[chatGroup.Id] = *chatGroup
}

func DeleteGroup(ctx context.Context, chatGroup *ChatGroup) {
	mu.Lock()
	defer mu.Unlock()
	delete(chatGroups, chatGroup.Id)
}

func CreateClient(ctx context.Context, client *Client) error {
	mu.Lock()
	defer mu.Unlock()
	clients[client.Id] = client

	hashed, err := bcrypt.GenerateFromPassword([]byte(client.PasswordHash), bcrypt.DefaultCost)
	if err != nil {
		return err
	}

	client.PasswordHash = string(hashed)

	//err := DbSaveClientWithoutGroups(ctx, client)
	//if err != nil {
	//	return err
	//}
	return nil
}

func CheckPassword(ctx context.Context, id uint32, password string) error {
	client, err := GetClientFromId(id)
	if err != nil {
		return err
	}

	err = bcrypt.CompareHashAndPassword([]byte(client.PasswordHash), []byte(password))
	if err != nil {
		return err
	}
	return nil
}

func GetIdFromClientName(ctx context.Context, name string) (uint32, error) {
	for _, client := range clients {
		if client.Name == name {
			return client.Id, nil
		}
	}
	return 0, errors.New("client not found")
}

func GetClientFromId(id uint32) (*Client, error) {
	client, ok := clients[id]
	if !ok {
		return nil, errors.New("no such user")
	}
	return client, nil
}

func ConnectClientToGroups(ctx context.Context, client *Client) {
	mu.Lock()
	defer mu.Unlock()
	for _, groupIn := range client.Groups {
		chatGroups[groupIn.Id].Members[client.Id] = client
	}
}

func DisconnectClientFromGroups(ctx context.Context, client *Client) {
	mu.Lock()
	defer mu.Unlock()
	for _, groupIn := range client.Groups {
		delete(chatGroups[groupIn.Id].Members, client.Id)
	}
}
