<?php

namespace onespace\tools\activeApi\models\oneaccess;

use onespace\tools\activeApi\components\clients\OneAccessClient;
use onespace\tools\activeApi\helpers\BitwiseHelperTrait;
use yii\helpers\ArrayHelper;
use yii\web\NotFoundHttpException;

/**
 * This class is intended to be extended from within the child service,
 * though it shouldn't need to be if you just need a basic interface
 * with the method / endpoint without any extra methods.
 *
 * @property integer $id
 * @property string $guid
 * @property integer $template_id
 * @property integer $direction
 * @property string $external_params
 * @property integer $type
 * @property integer $interface
 * @property integer $interface_index
 * @property string $logical_address
 * @property string $mac_address
 * @property integer $codehop_mode  See `\OS\PB\CodeHopConfig\CodeHopModes`
 * @property integer $codehop_button    Bitwise value. See `\OS\PB\CodeHopButtonMask\CodeHopButtonMask`
 *
 * @author  Gareth Palmer <gareth@one-space.co.za>
 */
class Reader extends \onespace\tools\activeApi\models\BaseActiveApiModel {
    use BitwiseHelperTrait;

    public $id;
    public $guid;
    public $template_id;
    public $direction;
    public $external_params;
    public $type;
    public $interface;
    public $interface_index;
    public $logical_address;
    public $mac_address;
    public $codehop_mode;
    public $codehop_button;

    public $template;
    public $accessGatewayReaders;

    public const DIRECTION_NOT_SET = "0";
    public const DIRECTION_ENTRY   = "1";
    public const DIRECTION_EXIT    = "2";
    public const DIRECTION_BOTH    = "3";

    public const INTERFACE_NOT_SET   = "0";
    public const INTERFACE_RELAY     = "1";
    public const INTERFACE_WIEGAND   = "2";
    public const INTERFACE_INPUT     = "3";
    public const INTERFACE_RE403     = "4";
    public const INTERFACE_EXPANSION = "5";
    public const INTERFACE_LED       = "6";
    public const INTERFACE_RS485     = "8";
    public const INTERFACE_BLE       = "9";
    public const INTERFACE_BLE_LR    = "10";
    public const INTERFACE_MODEM     = "11";
    public const INTERFACE_ETHERNET  = "12";
    public const INTERFACE_WIFI2G4   = "13";
    public const INTERFACE_WIFI5G    = "14";
    public const INTERFACE_RF868     = "15";

    /**
     * {@inheritdoc}
     */
    public function rules() {
        return ArrayHelper::merge(parent::rules(), [
            [['external_params', 'logical_address', 'mac_address'], 'default', 'value' => null],
            [['codehop_button'], 'default', 'value' => 0],
            [['guid', 'template_id', 'direction', 'type', 'interface'], 'required'],
            [['id', 'template_id', 'direction', 'type', 'interface', 'interface_index', 'codehop_mode', 'codehop_button'], 'integer'],
            [['guid'], 'string', 'max' => 36],
            [['external_params', 'logical_address'], 'string', 'max' => 255],
            [['mac_address'], 'string', 'max' => 20],
            [['template', 'accessGatewayReaders'], 'safe'],
        ]);
    }

    /**
     * {@inheritdoc}
     */
    public function client(): OneAccessClient {
        return new OneAccessClient();
    }

    /**
     * {@inheritdoc}
     */
    public function primaryKey(): string {
        return 'id';
    }

    /**
     * {@inheritdoc}
     */
    public function baseEndpoints(): array {
        return [
            'v1' => 'v1/reader',
        ];
    }

    public static function directions(): array {
        return [
            self::DIRECTION_NOT_SET => 'Not Set',
            self::DIRECTION_ENTRY   => 'Entry',
            self::DIRECTION_EXIT    => 'Exit',
            self::DIRECTION_BOTH    => 'Both',
        ];
    }

    public static function interfaces(): array {
        return [
            self::INTERFACE_NOT_SET   => 'Not Set',
            self::INTERFACE_RELAY     => 'Relay (Relay - output only)',
            self::INTERFACE_WIEGAND   => 'Wiegand (Wiegand interface - Inputs D0, D1. Outputs Red, Green, Buzzer)',
            self::INTERFACE_INPUT     => 'Input (Digital Input with EOL sensing)',
            self::INTERFACE_RE403     => 'RF403 (RF receiver IC with DataOut and RSSI analog output for Sherlo Remotes)',
            self::INTERFACE_EXPANSION => 'Expansion (I2C interface with 5V for some kind of expansion (solar charger for example))',
            self::INTERFACE_LED       => 'LED (LEDs that can be controlled. eg: Status)',
            self::INTERFACE_RS485     => 'RS485 (Half Duplex)',
            self::INTERFACE_BLE       => 'BLE (Standard BLE 1Mbps)',
            self::INTERFACE_BLE_LR    => 'BLELongRange (BLE over Long Range Coded Phy)',
            self::INTERFACE_MODEM     => 'Modem (IPv4 over LTE/GSM)',
            self::INTERFACE_ETHERNET  => 'Ethernet (IPv4 or IPv6)',
            self::INTERFACE_WIFI2G4   => 'WiFi2G4 (IPv4 or IPv6 - specific to 2.4GHz WiFi)',
            self::INTERFACE_WIFI5G    => 'WiFi5G (IPv4 or IPv6 - specific to 5GHz WiFi)',
            self::INTERFACE_RF868     => 'RF868 (868MHz FSK Transceiver)',
        ];
    }

    public static function interfacesGrouped(): array {
        return [
            self::INTERFACE_NOT_SET   => 'Not Set',
            "Non-networkable interfaces" => [
                self::INTERFACE_RELAY     => 'Relay (Relay - output only)',
                self::INTERFACE_WIEGAND   => 'Wiegand (Wiegand interface - Inputs D0, D1. Outputs Red, Green, Buz)',
                self::INTERFACE_INPUT     => 'Input (Digital Input with EOL sensing)',
                self::INTERFACE_RE403     => 'RF403 (RF receiver IC with DataOut and RSSI analog output for Sherlo Remotes)',
                self::INTERFACE_EXPANSION => 'Expansion (I2C interface with 5V for some kind of expansion (solar charger for example))',
                self::INTERFACE_LED       => 'LED (LEDs that can be controlled. eg: Status)',
            ],
            "Networkable interfaces" => [
                self::INTERFACE_RS485     => 'RS485 (Half Duplex)',
                self::INTERFACE_BLE       => 'BLE (Standard BLE 1Mbps)',
                self::INTERFACE_BLE_LR    => 'BLELongRange (BLE over Long Range Coded Phy)',
                self::INTERFACE_MODEM     => 'Modem (IPv4 over LTE/GSM)',
                self::INTERFACE_ETHERNET  => 'Ethernet (IPv4 or IPv6)',
                self::INTERFACE_WIFI2G4   => 'WiFi2G4 (IPv4 or IPv6 - specific to 2.4GHz WiFi)',
                self::INTERFACE_WIFI5G    => 'WiFi5G (IPv4 or IPv6 - specific to 5GHz WiFi)',
                self::INTERFACE_RF868     => 'RF868 (868MHz FSK Transceiver)',
            ],
        ];
    }

    /**
     * @throws NotFoundHttpException
     */
    public static function findById(int $id): static {
        $model = self::findOne(['id' => $id]);
        if ($model === null) {
            throw new NotFoundHttpException("Reader not found");
        }
        return $model;
    }
}
