package main

import (
	"sync"
	"time"

	"go-socket/Enums/ConnectionState"

	"github.com/coder/websocket"
	"github.com/google/uuid"
)

type User struct {
	Mu           sync.RWMutex
	Name         string
	Pronouns     string
	PasswordHash string
	CreatedAt    time.Time
	WsConn       *websocket.Conn
	Id           uint32
	Groups       map[uint32]struct{}
	Connections  map[uuid.UUID]*Connection
	Color        [3]uint8
}

type Connection struct {
	Mu             sync.RWMutex                    `json:"-"`
	Id             uuid.UUID                       `json:"id"`
	CreatedAt      time.Time                       `json:"createdAt"`
	MessagesBuff   [MaxDirectMsgCache]*Message     `json:"-"`
	NextBuffIdx    uint32                          `json:"-"`
	HaveOverflowed bool                            `json:"-"`
	RequestorId    uint32                          `json:"requestorId"`
	RecipientId    uint32                          `json:"recipientId"`
	State          ConnectionState.ConnectionState `json:"state"`
}

func (conn *Connection) AddMessageToBuff(message *Message) {
	conn.Mu.Lock()
	defer conn.Mu.Unlock()

	conn.MessagesBuff[conn.NextBuffIdx%MaxDirectMsgCache] = message
	conn.NextBuffIdx++
	if conn.NextBuffIdx >= MaxDirectMsgCache {
		conn.HaveOverflowed = true
	}
}

// GetSortedMessagesBuff returns arr, length
func (conn *Connection) GetSortedMessagesBuff() (*[MaxDirectMsgCache]*Message, uint32) {
	conn.Mu.RLock()
	defer conn.Mu.RUnlock()

	if !conn.HaveOverflowed {
		return &conn.MessagesBuff, conn.NextBuffIdx
	}

	sorted := new([MaxDirectMsgCache]*Message)
	for i := uint32(0); i < MaxDirectMsgCache; i++ {
		sorted[i] = conn.MessagesBuff[(conn.NextBuffIdx+i)%MaxDirectMsgCache]
	}
	return sorted, MaxDirectMsgCache
}

type Message struct {
	Id             uuid.UUID `json:"id"`
	Content        string    `json:"content"`
	CreatedAt      time.Time `json:"createdAt"`
	Sender         uint32    `json:"sender"`
	Receiver       uuid.UUID `json:"receiver"`
}

type Group struct {
	Name             string              `json:"name"`
	CreatedAt        time.Time           `json:"createdAt"`
	Id               uint32              `json:"-"`
	CreatorId        uint32              `json:"creatorId"`
	OwnerId          uint32              `json:"ownerId"`
	Users            map[uint32]struct{} `json:"-"`
	Color            [3]uint8            `json:"color"`
	EnableUserColors bool                `json:"enableUserColors"`
}

type LoginReturn struct {
	Token  string `json:"token"`
	UserId uint32 `json:"userId"`
}
