<?php

namespace modules\selfserve\traits;
require_once WD . '/modules/selfserve/helpers/selfserve_lane_status.php';
require_once WD . '/modules/selfserve/classes/selfserve_lane.php';

use Exception;
use modules\selfserve\classes\selfserve_lane;
use modules\selfserve\classes\selfserve_lane_command_arguments;
use modules\selfserve\helpers\selfserve_lane_command;
use modules\selfserve\helpers\selfserve_lane_log_action;
use modules\selfserve\helpers\selfserve_lane_status;

trait selfserve_lane_status_t
{
    /**
     * @enum selfserve_lane_status
     * @description The lane availability status, which can be one of the following values:
     * @values OCCUPIED, FAULT, AVAILABLE, MAINTENANCE, CLOSED, RESERVED
     * @var selfserve_lane_status $status
     */
    public selfserve_lane_status $status;

    /**
     * Get the current status of the self-serve lane
     * @return selfserve_lane_status The current status of the self-serve lane
     * @throws Exception If the execution of the release command fails
     */
    public function getLaneStatus(): selfserve_lane_status
    {
        $status = $this->getLaneCache($this->id, self::CACHE_SELFSERVE_LANE_KEY_STATUS, selfserve_lane_status::class);
        if (!empty($status)) {
            $this->status = $status;
        }
        else if (empty($this->status)) {
            // If not found in cache, default to AVAILABLE
            $this->status = selfserve_lane_status::AVAILABLE;
            $this->setLaneCache($this->id, self::CACHE_SELFSERVE_LANE_KEY_STATUS, $this->status);
        }
        // If the status is RESERVED, check if the reservation has expired
        if ($this->status->equals(selfserve_lane_status::RESERVED) && $this->isReservationExpired()) {
            // Release the lane if the reservation has expired
            $this->execute(selfserve_lane_command::RELEASE, new selfserve_lane_command_arguments());
        }
        return $this->status;
    }

    /**
     * Set the current status of the self-serve lane
     * @param selfserve_lane_status $status The new status of the self-serve lane
     * @return selfserve_lane_status_t|selfserve_lane
     */
    public function setLaneStatus(selfserve_lane_status $status): self
    {
        // Get the old status to determine what we are clearing
        $old_status = $this->getLaneStatus();

        $this->status = $status;
        $this->setLaneCache($this->id, self::CACHE_SELFSERVE_LANE_KEY_STATUS, $this->status);

        // Log specific status changes
        switch ($status) {
            case selfserve_lane_status::MAINTENANCE:
                $this->logLaneAction(selfserve_lane_log_action::SET_MAINTENANCE);
                break;
            case selfserve_lane_status::FAULT:
                $this->logLaneAction(selfserve_lane_log_action::SET_FAULT);
                break;
            case selfserve_lane_status::CLOSED:
                $this->logLaneAction(selfserve_lane_log_action::CLOSE_LANE);
                break;
            case selfserve_lane_status::RESERVED:
                $this->logLaneAction(selfserve_lane_log_action::RESERVE_LANE);
                break;
            case selfserve_lane_status::AVAILABLE:
                if ($old_status->equals(selfserve_lane_status::MAINTENANCE)) {
                    $this->logLaneAction(selfserve_lane_log_action::CLEAR_MAINTENANCE);
                } else if ($old_status->equals(selfserve_lane_status::FAULT)) {
                    $this->logLaneAction(selfserve_lane_log_action::CLEAR_FAULT);
                } else if ($old_status->equals(selfserve_lane_status::CLOSED)) {
                    $this->logLaneAction(selfserve_lane_log_action::OPEN_LANE);
                } else if ($old_status->equals(selfserve_lane_status::RESERVED)) {
                    $this->logLaneAction(selfserve_lane_log_action::RELEASE_LANE);
                }
                break;
        }

        return $this;
    }
}