<?php

namespace SHServ\Helpers;

use \SHServ\Models\Devices;

class DeviceScriptsHelper {
	protected $devices_model;

	public function __construct(Devices $devices_model) {
		$this -> devices_model = $devices_model;
	}

	public function devices(): Devices {
		return $this -> devices_model;
	}


	/**
	 * Синхронизировать указанный канал реле с указанным каналом устройства кнопки.
	 * Синхронизация низкоуровневая и одностороняя, от реле к кнопке.
	 * @param  Relay       $relay  
	 * @param  Button      $btn
	 * @param  int|integer $relay_channel
	 * @param  int|integer $btn_channel
	 * @return void
	 */
	public function sync_relay_to_btn_channel(\SHServ\Tools\DeviceAPI\Relay $relay_api, \SHServ\Tools\DeviceAPI\Button $btn_block_api, int $relay_channel = 0, int $btn_channel = 0): void {
		$relay_channels = ($relay_api -> get_status())["channels"];

		$btn_block_api -> set_channel_state(
			$relay_channels[$relay_channel]["state"] == "on" ? "enabled" : "disabled", 
			$btn_channel
		);
	}

	/**
	 * Синхронизировать состояние каналов реле с соответствующими блоками кнопок с указанными каналами. 
	 * Синхронизация односторонняя от реле к кнопкам
	 * @param  Array  $sync_map    [ 
	 *   relay_channel_num => [
	 *     ["alias" => "button_alias", "channel" => 1],
	 *     ["alias" => "button_alias_2", "channel" => 0],
	 *   ]
	 * ]
	 * @param  String $relay_alias 
	 * @return Bool
	 */
	public function sync_relay_to_btns(Array $sync_map, String $relay_alias): Bool {
		if(isset($sync_map["connections"])) {
			$sync_map = $this -> prepare_sync_map_by_alias($sync_map, $relay_alias);
		}

		$relay = $this -> devices() -> by_alias($relay_alias);
		if(!$relay) {
			return false;
		}

		$relay_api = $relay -> device_api();
		if(!($relay_api instanceof \SHServ\Tools\DeviceAPI\Relay)) {
			return false;
		}

		foreach($sync_map as $relay_channel => $btns) {
			foreach($btns as $item) {
				$btn = $this -> devices() -> by_alias($item["alias"]);
				if(!$btn) {
					continue;
				}

				$btn_api = $btn -> device_api();
				if(!($btn_api instanceof \SHServ\Tools\DeviceAPI\Button)) {
					continue;
				}

				$this -> sync_relay_to_btn_channel($relay_api, $btn_api, $relay_channel, intval($item["channel"]));
			}
		}

		return true;
	}

	/**
	 * Синхронизировать состояние каналов устройства "кнопка" с соответствующими реле с указанными каналами. 
	 * Синхронизация односторонняя от реле к кнопкам
	 * @param  Array  $sync_map    [ 
	 *   button_channel_num => [
	 *     ["alias" => "relay_alias", "channel" => 1],
	 *     ["alias" => "relay_alias_2", "channel" => 0],
	 *   ]
	 * ]
	 * @param  String $btn_alias 
	 * @return Bool
	 */
	public function sync_btn_channels(Array $sync_map, String $btn_alias): Bool {
		if(isset($sync_map["connections"])) {
			$sync_map = $this -> prepare_sync_map_by_alias($sync_map, $btn_alias);
		}

		$btn = $this -> devices() -> by_alias($btn_alias);
		if(!$btn) {
			return false;
		}

		$btn_api = $btn -> device_api();
		if(!($btn_api instanceof \SHServ\Tools\DeviceAPI\Button)) {
			return false;
		}

		foreach($sync_map as $btn_channel => $relays) {
			foreach($relays as $item) {
				$relay = $this -> devices() -> by_alias($item["alias"]);
				if(!$relay) {
					continue;
				}

				$relay_api = $relay -> device_api();
				if(!($relay_api instanceof \SHServ\Tools\DeviceAPI\Relay)) {
					continue;
				}

				$this -> sync_relay_to_btn_channel($relay_api, $btn_api, intval($item["channel"]), $btn_channel);
			}
		}

		return true;
	}

	public function get_sync_entries_by_type(Array $sync_map, String $type): Array {
		$map = $sync_map["connections"];
		$device_entries = [];

		foreach($map as $connection) {
			foreach($connection as $device_entry) {
				if(!isset($device_entry["type"]) or $device_entry["type"] != $type) {
					continue;
				}

				if(!isset($device_entry["alias"])) {
					continue;
				}

				$device_entries[] = $device_entry;
			}
		}

		return $device_entries;
	}

	public function prepare_sync_map_by_alias(Array $sync_map, String $alias): Array {
		$result = [];

		foreach($sync_map["connections"] as $connection) {
			foreach($connection as $device_entry) {
				if($device_entry["alias"] != $alias) {					
					continue;
				}

				$result[$device_entry["channel"]] = array_filter($connection, function($i) use($alias) { 
					return $i["alias"] != $alias;
				});

				break;
			}
		}

		return $result;
	}
}