<?php

namespace SHServ\Controllers;

use \SHServ\Models\Devices;
use \SHServ\Tools\DeviceScanner;
use \SHServ\Entities\Device;
use \SHServ\Entities\Area;

class DevicesRESTAPIController extends \SHServ\Middleware\Controller {
	public function scanning__ready_to_setup() {
		$device_model = new Devices();
		$devices = $device_model -> get_unregistered_devices();

		return $this -> utils() -> response_success([
			"devices" => $devices
		]);
	}

	public function scanning__all() {
		$device_model = new Devices();
		$devices = $device_model -> scanning_localnet(FCONF["device_ip_range"][0], FCONF["device_ip_range"][1]);

		return $this -> utils() -> response_success([
			"devices" => $devices
		]);
	}

	public function setup_new_device($device_ip, $alias, $name, $description) {
		$devices_model = new \SHServ\Models\Devices();

		if(strlen($device_ip) < 7) {
			return $this -> utils() -> response_error("invalid_ip");
		}

		if(!strlen($alias)) {
			return $this -> utils() -> response_error("empty_field", ["alias"]);
		}

		if(!strlen($name)) {
			return $this -> utils() -> response_error("empty_field", ["name"]);
		}

		if(!$devices_model -> alias_is_uniq($alias)) {
			return $this -> utils() -> response_error("alias_already_exists", ["alias"]);
		}

		$result = $devices_model -> connect_new_device($device_ip, $alias, $name, $description);

		if($result and $result instanceof \SHServ\Entities\Device) {
			$device_about = $result -> device_api() -> get_about();
			return $this -> utils() -> response_success([
				"device" => [
					"id" => $result -> id(),
					"alias" => $result -> alias,
					"name" => $result -> name,
					"description" => $result -> description,
					"device" => $device_about["data"]
				]
			]);
		}

		return $this -> utils() -> response_error($result["err_alias"]);
	}

	public function remove_device($device_id) {
		$devices_model  = new Devices();
		$result = $devices_model -> remove_device(intval($device_id));

		if(!$result["result"]) {
			return $this -> utils() -> response_error(
				$result["err_alias"], 
				[], 
				[ "device_msg" => $result["device_msg"] ]
			);
		}

		return $this -> utils() -> response_success([
			"result" => $result["result"] ? true : false,
			"device_msg" => $result["device_msg"]
		]);
	}

	public function reboot_device($device_id) {
		$devices_model = new Devices();
		$result = $devices_model -> reboot_device(intval($device_id));

		if(!$result["result"]) {
			return $this -> utils() -> response_error(
				$result["err_alias"], 
				[], 
				[ "device_msg" => $result["msg"] ?? "" ]
			);
		}

		return $this -> utils() -> response_success([
			"device_msg" => $result["msg"]
		]);
	}

	public function device_info($device_id) {
		$device_id = intval($device_id);
		$devices_model = new Devices();
		$result = $devices_model -> get_device_info($device_id);

		if(!$result) {
			return $this -> utils() -> response_error("device_not_found");
		}

		return $this -> utils() -> response_success([ "device" => $result ]);
	}

	public function device($device_id) {
		$devices_model = new Devices();
		$device = $devices_model -> by_id(intval($device_id));

		if(!$device) {
			return $this -> utils() -> response_error("device_not_found");
		}

		$info = [
			"id" => $device -> id(),
			"alias" => $device -> alias,
			"device_type" => $device -> device_type,
			"device_hard_id" => $device -> device_hard_id,
			"device_mac" => $device -> device_mac,
			"device_ip" => $device -> device_ip,
			"firmware_version" => $device -> firmware_version,
			"name" => $device -> name,
			"description" => $device -> description,
			"status" => $device -> status,
			"connection_status" => $device -> connection_status,
			"last_contact" => $device -> last_contact,
			"create_at" => $device -> create_at
		];

		return $this -> utils() -> response_success([ "device" => $info ]);
	}

	public function device_status($device_id) {
		$devices_model = new Devices();
		$device = $devices_model -> by_id(intval($device_id));

		if(!$device) {
			return $this -> utils() -> response_error("device_not_found");
		}

		$device_status = $device -> device_api() -> get_status();

		if(!$device_status) {
			return $this -> utils() -> response_error("device_request_fail");
		}

		$response_data = [
			"id" => $device -> id(),
			"alias" => $device -> alias,
			"device_response" => $device_status
		];

		return $this -> utils() -> response_success(["device" => $response_data]);
	}

	public function do_device_action($device_id, $action, $params) {
		$devices_model = new Devices();
		$device = $devices_model -> by_id(intval($device_id));

		if(!$device) {
			return $this -> utils() -> response_error("device_not_found");
		}

		$result = $device -> device_api() -> post_action($action, $params);
		$device_response = $result["data"] ?? [];

		if(!$device_response) {
			return $this -> utils() -> response_error("device_request_fail");
		}

		if($device_response["status"] != "ok") {
			return $this -> utils() -> response_error("device_request_fail", [], [
				"device_status" => $device_response["status"],
				"device_error" => $device_response["status"] ?? "",
				"device_msg" => $device_response["message"] ?? ""
			]);
		}

		$response_data = [
			"id" => $device -> id(),
			"alias" => $device -> alias,
			"device_response" => $device_response
		];

		return $this -> utils() -> response_success(["device" => $response_data]);
	}

	public function place_in_area($target_id, $place_in_area_id) {
		if($target_id != intval($target_id) or intval($target_id) < 1) {
			return $this -> utils() -> response_error("invalid_id", ["target_id"]);
		}

		if($place_in_area_id != intval($place_in_area_id) or intval($place_in_area_id) < 1) {
			return $this -> utils() -> response_error("invalid_id", ["place_in_area_id"]);
		}

		$device = new Device(intval($target_id));
		$place_area = new Area(intval($place_in_area_id));

		if(!$device) {
			return $this -> utils() -> response_error("device_not_found");
		}

		if(!$place_area) {
			return $this -> utils() -> response_error("area_not_exists");
		}

		if(!$device -> place_in_area($place_area)) {
			return $this -> utils() -> response_error("undefined_error");
		}

		return $this -> utils() -> response_success();
	}

	public function unassign_from_area($target_id) {
		if($target_id != intval($target_id) or intval($target_id) < 1) {
			return $this -> utils() -> response_error("invalid_id", ["target_id"]);
		}

		$device = new Device(intval($target_id));

		if(!$device) {
			return $this -> utils() -> response_error("device_not_found");
		}

		return $device -> place_in_area_id(0)
			? $this -> utils() -> response_success()
			: $this -> utils() -> response_error("undefined_error");
	}

	public function devices_list($status = "active") {
		$status_list = Device::get_status_list();
		if(!in_array($status, $status_list)) {
			return $this -> utils() -> response_error("wrong_status_name");
		}

		$devices_model = new Devices();
		$devices = $devices_model -> get_device_list($status);

		return $this -> utils() -> response_success([
			"devices" => array_map(function($device) {
				return $device -> to_array();
			}, $devices),
			"total" => count($devices)
		]);
	}

	public function update_name($device_id, $name) {
		$device_id = intval($device_id);

		if($device_id < 1) {
			return $this -> utils() -> response_error("invalid_id", ["device_id"]);
		}

		$device = new Device($device_id);

		if(!$device) {
			return $this -> utils() -> response_error("device_not_found");
		}

		if(!strlen($name)) {
			return $this -> utils() -> response_error("empty_field", ["name"]);
		}

		if(!$device -> device_api() -> set_device_name($name)) {
			return $this -> utils() -> response_error("device_request_fail");
		}

		$device -> name = $name;
		$device -> update();

		return $this -> utils() -> response_success();
	}

	public function update_description($device_id, $description) {
		$device_id = intval($device_id);

		if($device_id < 1) {
			return $this -> utils() -> response_error("invalid_id", ["device_id"]);
		}

		$device = new Device($device_id);

		if(!$device) {
			return $this -> utils() -> response_error("device_not_found");
		}

		$device -> description = $description;
		$device -> update();

		return $this -> utils() -> response_success();
	}

	public function update_alias($device_id, $new_alias) {
		$device_id = intval($device_id);

		if($device_id < 1) {
			return $this -> utils() -> response_error("invalid_id", ["device_id"]);
		}

		$device = new Device($device_id);

		if(!$device) {
			return $this -> utils() -> response_error("device_not_found");
		}

		$devices_model = new \SHServ\Models\Devices();

		if(!$devices_model -> alias_is_uniq($new_alias)) {
			return $this -> utils() -> response_error("alias_already_exists", ["new_alias"]);
		}

		$device -> alias = $new_alias;
		$device -> update();

		return $this -> utils() -> response_success();
	}
}