<?php
namespace Misuzu\Users;

use Index\Colour\Colour;
use Index\Data\IDbConnection;

class UsersContext {
    private Users $users;
    private Roles $roles;
    private Bans $bans;
    private Warnings $warnings;
    private ModNotes $modNotes;

    private array $userInfos = [];
    private array $userColours = [];
    private array $userRanks = [];

    private array $activeBans = [];

    public function __construct(IDbConnection $dbConn) {
        $this->users = new Users($dbConn);
        $this->roles = new Roles($dbConn);
        $this->bans = new Bans($dbConn);
        $this->warnings = new Warnings($dbConn);
        $this->modNotes = new ModNotes($dbConn);
    }

    public function getUsers(): Users {
        return $this->users;
    }

    public function getRoles(): Roles {
        return $this->roles;
    }

    public function getBans(): Bans {
        return $this->bans;
    }

    public function getWarnings(): Warnings {
        return $this->warnings;
    }

    public function getModNotes(): ModNotes {
        return $this->modNotes;
    }

    public function getUserInfo(string $value, int|string|null $select = null): UserInfo {
        $select = Users::resolveGetUserSelectAlias($select ?? Users::GET_USER_ID);
        if(($select & Users::GET_USER_ID) > 0 && array_key_exists($value, $this->userInfos))
            return $this->userInfos[$value];

        $userInfo = $this->users->getUser($value, $select);
        $userId = $userInfo->getId();

        return $this->userInfos[$userId] = $userInfo;
    }

    public function getUserColour(UserInfo|string|null $userInfo): Colour {
        if($userInfo === null)
            return Colour::none();
        $userId = $userInfo instanceof UserInfo ? $userInfo->getId() : $userInfo;

        if(array_key_exists($userId, $this->userColours))
            return $this->userColours[$userId];

        return $this->userColours[$userId] = $this->users->getUserColour($userInfo);
    }

    public function getUserRank(UserInfo|string|null $userInfo): int {
        if($userInfo === null)
            return 0;
        if($userInfo instanceof UserInfo)
            $userInfo = $userInfo->getId();

        if(array_key_exists($userInfo, $this->userRanks))
            return $this->userRanks[$userInfo];

        return $this->userRanks[$userInfo] = $this->users->getUserRank($userInfo);
    }

    public function tryGetActiveBan(
        UserInfo|string|null $userInfo = null,
        int $minimumSeverity = Bans::SEVERITY_MIN
    ): ?BanInfo {
        if($userInfo === null)
            return null;
        if($userInfo instanceof UserInfo)
            $userInfo = $userInfo->getId();

        if(!array_key_exists($userInfo, $this->activeBans))
            $this->activeBans[$userInfo] = $this->bans->tryGetActiveBan($userInfo);

        return $this->activeBans[$userInfo];
    }

    public function hasActiveBan(
        UserInfo|string|null $userInfo = null,
        int $minimumSeverity = Bans::SEVERITY_MIN
    ): bool {
        return $this->tryGetActiveBan($userInfo, $minimumSeverity) !== null;
    }
}
