package cache

import (
	"jannex/robot-control-manager/modules/structs"
	"jannex/robot-control-manager/modules/utils"
	"sort"
	"sync"

	"git.ex.umbach.dev/Alex/roese-utils/rspagination"
)

var robots = make(map[string]*structs.Robot)
var rMu sync.RWMutex

func AddRobot(robot *structs.Robot) {
	rMu.Lock()
	defer rMu.Unlock()

	robots[robot.Id] = robot
}

func AddRobots(newRobots []structs.Robot) {
	rMu.Lock()
	defer rMu.Unlock()

	for i := range newRobots {
		r := &newRobots[i]
		robots[r.Id] = r
	}
}

func GetRobots() map[string]*structs.Robot {
	rMu.RLock()
	defer rMu.RUnlock()

	return robots
}

func GetAllRobots(query rspagination.PageQuery) structs.RobotsResponse {
	rMu.RLock()
	defer rMu.RUnlock()

	var r []structs.APIRobot

	for _, v := range robots {
		r = append(r, structs.APIRobot{
			Id:                  v.Id,
			Type:                v.Type,
			Name:                v.Name,
			Status:              v.Status,
			Address:             v.Address,
			CurrentJobName:      v.CurrentJobName,
			JobsWaitingCount:    v.JobsWaitingCount,
			JobsWaitingNameList: utils.GetJobsWaitingNameList(v.JobsWaitingNameList),
			FirmwareVersion:     v.FirmwareVersion,
			ConnectedAt:         v.ConnectedAt,
			CreatedAt:           v.CreatedAt,
		})
	}

	// sort after created at
	sort.SliceStable(r, func(i, j int) bool {
		return r[i].CreatedAt.After(r[j].CreatedAt)
	})

	start, end := rspagination.GetPage(len(r), query.Page, utils.RobotsPageLimit)

	return structs.RobotsResponse{
		Robots:     r[start:end],
		TotalPages: rspagination.CalculateTotalPages(len(r), utils.RobotsPageLimit),
	}
}

func IsRobotInList(robotId string) bool {
	rMu.RLock()
	defer rMu.RUnlock()

	for _, r := range robots {
		if r.Id == robotId {
			return true
		}
	}

	return false
}

func GetRobotByName(robotName string) *structs.Robot {
	rMu.RLock()
	defer rMu.RUnlock()

	for _, r := range robots {
		if r.Name == robotName {
			return r
		}
	}

	return nil
}

func GetRobotById(robotId string) *structs.Robot {
	rMu.RLock()
	defer rMu.RUnlock()

	return robots[robotId]
}

func RemoveRobotById(robotId string) {
	rMu.Lock()
	defer rMu.Unlock()

	delete(robots, robotId)
}

func IsRobotNameInList(robotName string) bool {
	rMu.RLock()
	defer rMu.RUnlock()

	for _, r := range robots {
		if r.Name == robotName {
			return true
		}
	}

	return false
}

func IsRobotIdInList(robotId string) bool {
	return GetRobotById(robotId) != nil
}
