<?php

namespace objects;

use classes\db;
use classes\object_property;
use classes\selfserve;
use Exception;
use traits\db_object_t;

class department_lanes_o extends db
{
    use db_object_t;

    public object_property $department; // The department id
    public object_property $name; // The lane name
    public object_property $relay_in_id; // The Shelly relay for the entrance port (if applicable)
    public object_property $relay_out_id; // The Shelly relay for the exit port (if applicable)
    public object_property $relay_machine_id; // The Shelly relay for the machine (if applicable)
    public object_property $created_at;
    public object_property $updated_at;
    public object_property $deleted_at;


    public function structure(): void
    {
        $this->setTable('department_lanes');
    }

    public function getLaneStatus(): \modules\selfserve\helpers\selfserve_lane_status
    {
        self::requireSelected();
        $selfserve = new selfserve();
        $lane = $selfserve->lane((int)$this->id);
        return $lane->getLaneStatus();
    }

    /**
     * Add a department lane
     * @param int $department The department id
     * @param string $name The lane name
     * @param string|null $relay_in_id The Shelly relay for the entrance port (if applicable)
     * @param string|null $relay_out_id The Shelly relay for the exit port (if applicable)
     * @param string|null $relay_machine_id The Shelly relay for the machine (if applicable)
     * @return department_lanes_o
     * @throws Exception If the object was not created successfully
     */
    public function add(int $department, string $name, string $relay_in_id = null, string $relay_out_id = null, string $relay_machine_id = null): department_lanes_o
    {
        global /** @var db $db */
        $db;
        // Sanitize the input
        $department = (int)$department;
        $name = $db->escape_string($name);
        if (!is_null($relay_in_id)) {
            $relay_in_id = $db->escape_string($relay_in_id);
        }
        if (!is_null($relay_out_id)) {
            $relay_out_id = $db->escape_string($relay_out_id);
        }
        if (!is_null($relay_machine_id)) {
            $relay_machine_id = $db->escape_string($relay_machine_id);
        }
        // Add the object
        $tmp_id = self::add_object([
            'department' => $department,
            'name' => $name,
            ...(!is_null($relay_in_id) ? ['relay_in_id' => $relay_in_id] : []), // If the relay_in_id is null, it will be set to null in the database
            ...(!is_null($relay_out_id) ? ['relay_out_id' => $relay_out_id] : []), // If the relay_out_id is null, it will be set to null in the database
            ...(!is_null($relay_machine_id) ? ['relay_machine_id' => $relay_machine_id] : []), // If the relay_machine_id is null, it will be set to null in the database
        ]);
        $this->id = $tmp_id;
        self::getObjectProperties();
        self::objectChanged();
        return $this;
    }

    public function getObjectProperties(): void
    {
        $this->department = new object_property($this->table, $this->id, 'department', 'int', false);
        $this->name = new object_property($this->table, $this->id, 'name', 'string', false);
        $this->relay_in_id = new object_property($this->table, $this->id, 'relay_in_id', 'string', false);
        $this->relay_out_id = new object_property($this->table, $this->id, 'relay_out_id', 'string', false);
        $this->relay_machine_id = new object_property($this->table, $this->id, 'relay_machine_id', 'string', false);
        $this->created_at = new object_property($this->table, $this->id, 'created_at', 'timestamp', false);
        $this->updated_at = new object_property($this->table, $this->id, 'updated_at', 'timestamp', false);
        $this->deleted_at = new object_property($this->table, $this->id, 'deleted_at', 'timestamp', false);
    }

    public function objectChanged(): void
    {
        //TODO: Add cache invalidation
    }

    public function asArray(): array
    {
        return [
            'id' => (int)$this->id,
            'department' => (int)$this->department->value(),
            'name' => (string)$this->name->value(),
            'relay_in_id' => (string)$this->relay_in_id->value(),
            'relay_out_id' => (string)$this->relay_out_id->value(),
            'relay_machine_id' => (string)$this->relay_machine_id->value(),
            // Status of the lane
            'status' => (string)$this->getLaneStatus()->name,
            // Timestamps
            'created_at' => (string)$this->created_at->value(),
            'updated_at' => (string)$this->updated_at->value(),
        ];
    }

    /**
     * Get the self-serve lane products available for this lane
     * @return array An array of product ids available for this lane
     * @throws Exception
     */
    public function getSelfServeLaneProducts(): array
    {
        self::requireSelected();
        return department_selfserve_tasks_o::getLaneProducts((int)$this->id);
    }

    /**
     * @throws Exception
     * @return department_lanes_o[] An array of department lane objects for the specified department
     */
    public function getDepartmentLanes(int $department_id): array
    {
        $lanes = [];
        $department_lanes = self::getFieldsWhere(
            [
                'department' => $department_id,
                'deleted_at' => null
            ],
            [
                'id',
            ],
        );
        foreach ( $department_lanes as $department_lane ) {
            $lanes[] = (new department_lanes_o())->select((int)$department_lane['id']);
        }
        return $lanes;
    }
}