<?php

namespace SHServ\Entities;

use \SHServ\Entities\DeviceAuth;
use \SHServ\Entities\Area;
use \SHServ\Tools\DeviceAPI\Base;
use \SHServ\Tools\DeviceAPI\Relay;
use \SHServ\Tools\DeviceAPI\Button;
use \SHServ\Tools\DeviceAPI\Sensor;
use \SHServ\Tools\DeviceAPI\Hatch;

class Device extends \SHServ\Middleware\Entity {
	
	use \SHServ\Helpers\MetaImplementation;
	use \SHServ\Entities\Traits\AreaPlacing;

	public static $table_name = "devices";
	protected static $fields = [
		"id", "area_id", "alias", "name", "device_type", "device_ip",
		"device_mac", "device_hard_id", "firmware_version", "connection_status", 
		"status", "description", "last_contact", "create_at", "update_at"
	];

	protected $device_auth_instance;
	protected $device_api_instance;

	public function __construct(Int $id, Array $data = []){
		parent::__construct(
			self::$table_name,
			$id,
			$data
		);	
	}

	public function remove() {
		$this -> status = "removed";
		return $this -> update();
	}

	public static function get_status_list() {
		return ["active", "removed", "freezed"];
	}

	public function auth(): DeviceAuth | null {
		if($this -> device_auth_instance) {
			return $this -> device_auth_instance;
		}

		$result = app() -> thin_builder -> select(
			DeviceAuth::$table_name, 
			DeviceAuth::get_fields(), 
			[ ["device_id", "=", $this -> id()] ]
		);

		if(!$result) {
			return null;
		}

		$this -> device_auth_instance = new DeviceAuth($result[0]["id"], $result[0], $this);

		return $this -> device_auth_instance ?? null;
	}

	public function clear_device_auth_cache(): void {
		$this -> device_auth_instance = null;
	}

	public function device_api(): ?Base {
		if($this -> device_api_instance) {
			return $this -> device_api_instance;
		}

		switch($this -> device_type) {
			case "relay": 
				$this -> device_api_instance = new Relay($this -> device_ip);
				break;
			case "button": 
				$this -> device_api_instance = new Button($this -> device_ip);
				break;
			case "sensor": 
				$this -> device_api_instance = new Sensor($this -> device_ip);
				break;
			case "hatch": 
				$this -> device_api_instance = new Hatch($this -> device_ip);
				break;
			default: 
				$this -> device_api_instance = new Base($this -> device_ip);
		}

		if($this -> auth()) {
			$this -> device_api_instance -> set_local_token($this -> auth() -> device_token);
		}

		$this -> device_api_instance -> set_on_success_callback(function() {
			$this -> touch_last_contact();
		});

		return $this -> device_api_instance ?? null;
	}

	public function set_device_token(String $token) {
		$this -> device_api() -> remote_set_token($token);
		$auth = $this -> auth();
		if(!$auth)
			return false;

		$auth -> device_token = $token;
		$this -> device_api_instance -> set_local_token($token);
		return $auth -> update();
	}

	public function resetup(String $token) {
		return $this -> set_device_token($token);
	}

	public function ping() {
		return app() -> utils -> fast_ping_tcp($this -> device_ip);
	}

	public function touch_last_contact(): void {
		$this -> last_contact = date("Y-m-d H:i:s");
		$this -> update();
	}
}
