<?php
require_once (dirname(__FILE__).'/../require.php');
error_reporting(~E_WARNING & ~E_NOTICE);
header('Content-Type: application/json');

function getDeviceLocalizationByMessages($idDevice) {
    $db = new Database();
    $localization = new stdClass();
    $localization->latitude = "0.0";
    $localization->longitude = "0.0";
    $localization->accuracy = "0.0";
    $localization->internalId = "0";

    try {
        $conn = $db->getConnection();
        if ($conn === null) {
            return $localization;
        }

        $waitLoc = 0;
        $stmt = $conn->prepare(
            "SELECT json_configuration
             FROM device_configurations
             WHERE id_devices = :idDevice AND active = 1
             ORDER BY id DESC
             LIMIT 1"
        );
        $stmt->bindValue(':idDevice', (int)$idDevice, PDO::PARAM_INT);
        $stmt->execute();
        $configRow = $stmt->fetch(PDO::FETCH_ASSOC);
        if ($configRow && !empty($configRow['json_configuration'])) {
            $config = json_decode($configRow['json_configuration'], true);
            if (json_last_error() === JSON_ERROR_NONE && isset($config['WaitLoc'])) {
                $waitLoc = (int)$config['WaitLoc'];
            }
        }

        if ($waitLoc < 0) {
            $waitLoc = 0;
        }

        $stmt = $conn->prepare(
            "SELECT text, insert_time
             FROM device_messages
             WHERE id_devices = :idDevice
               AND STR_TO_DATE(insert_time, '%Y-%m-%d %H:%i:%s') >= DATE_SUB(NOW(), INTERVAL :waitLoc SECOND)
               AND STR_TO_DATE(insert_time, '%Y-%m-%d %H:%i:%s') <= NOW()
             ORDER BY STR_TO_DATE(insert_time, '%Y-%m-%d %H:%i:%s') DESC, id DESC"
        );
        $stmt->bindValue(':idDevice', (int)$idDevice, PDO::PARAM_INT);
        $stmt->bindValue(':waitLoc', (int)$waitLoc, PDO::PARAM_INT);
        $stmt->execute();
        $rows = $stmt->fetchAll(PDO::FETCH_ASSOC);

        $latestGps = null;
        $bestBeaconMac = null;
        $bestWifiMac = null;

        foreach ($rows as $row) {
            if (empty($row['text'])) {
                continue;
            }

            $message = json_decode($row['text'], true);
            if (json_last_error() !== JSON_ERROR_NONE || !isset($message['Body'])) {
                continue;
            }

            $body = $message['Body'];

            if ($latestGps === null) {
                $gps = isset($body['GPSLocation']) && is_array($body['GPSLocation']) ? $body['GPSLocation'] : null;
                $latitude = extractFirstNonEmptyValue($gps, array('Latitude', 'latitude'));
                $longitude = extractFirstNonEmptyValue($gps, array('Longitude', 'longitude'));
                if (isMeaningfulCoordinate($latitude) && isMeaningfulCoordinate($longitude)) {
                    $accuracy = extractFirstNonEmptyValue($gps, array('Accuracy', 'accuracy', 'Hop', 'hop'));
                    $latestGps = array(
                        'latitude' => (string)$latitude,
                        'longitude' => (string)$longitude,
                        'accuracy' => ($accuracy === null || $accuracy === '') ? '0.0' : (string)$accuracy,
                    );
                }
            }

            if ($bestBeaconMac === null) {
                $beacons = isset($body['BeaconLocation']) && is_array($body['BeaconLocation']) ? $body['BeaconLocation'] : array();
                if (count($beacons) > 0) {
                    $bestBeacon = getBestMacByRssi($beacons);
                    if ($bestBeacon !== null) {
                        $bestBeaconMac = $bestBeacon;
                    }
                }
            }

            if ($bestWifiMac === null) {
                $wifiLocations = isset($body['NewWiFiLocations']) && is_array($body['NewWiFiLocations']) ? $body['NewWiFiLocations'] : array();
                if (count($wifiLocations) > 0) {
                    $bestWifi = getBestMacByRssi($wifiLocations);
                    if ($bestWifi !== null) {
                        $bestWifiMac = $bestWifi;
                    }
                }
            }

            if ($latestGps !== null && $bestBeaconMac !== null && $bestWifiMac !== null) {
                break;
            }
        }

        if ($latestGps !== null) {
            $localization->latitude = $latestGps['latitude'];
            $localization->longitude = $latestGps['longitude'];
            $localization->accuracy = $latestGps['accuracy'];
        }

        if ($bestBeaconMac !== null) {
            $localization->internalId = $bestBeaconMac;
        } elseif ($bestWifiMac !== null) {
            $localization->internalId = $bestWifiMac;
        }

        return $localization;
    } catch (Exception $e) {
        return $localization;
    }
}

function extractFirstNonEmptyValue($source, $keys) {
    if (!is_array($source)) {
        return null;
    }

    foreach ($keys as $key) {
        if (array_key_exists($key, $source)) {
            $value = $source[$key];
            if ($value !== null && $value !== '' && strtolower((string)$value) !== 'null') {
                return $value;
            }
        }
    }

    return null;
}

function isMeaningfulCoordinate($value) {
    if ($value === null || $value === '') {
        return false;
    }

    if (!is_numeric($value)) {
        return false;
    }

    return ((float)$value) != 0.0;
}

function getBestMacByRssi($items) {
    $bestMac = null;
    $bestRssi = null;

    foreach ($items as $item) {
        if (!is_array($item)) {
            continue;
        }

        $mac = extractFirstNonEmptyValue($item, array('Mac', 'mac', 'BSSID', 'bssid', 'WifiMac', 'wifiMac'));
        $rssi = extractFirstNonEmptyValue($item, array('Rssi', 'RSSI', 'rssi', 'Signal', 'signal', 'Dbm', 'dbm'));

        if ($mac === null || $rssi === null || !is_numeric($rssi)) {
            continue;
        }

        $rssi = (int)$rssi;
        if ($bestRssi === null || $rssi > $bestRssi) {
            $bestRssi = $rssi;
            $bestMac = (string)$mac;
        }
    }

    return $bestMac;
}

if($_SERVER['REQUEST_METHOD'] === 'POST'){
    $paramsJson = file_get_contents('php://input');
    $params = json_decode($paramsJson);
    $token = $params->token;
    $deviceGroup = DeviceDB::getDeviceGroupByToken($token);
    if($deviceGroup === null){
        die('{"message":"Invalid token"}');
    }
    $roots = array();
    $z=0;
    $devices = DeviceDB::getDevicesByIdDeviceGroup($deviceGroup->id);
    if($devices !== null) {
        for ($i = 0; $i < count($devices); $i++) {
            $root = new stdClass();
            $device = $devices[$i];
            $root->device = $device;
            $alarms = DeviceDB::getDeviceAlarmsByIdDevice($device->id);
            if($alarms === null) {
                $alarms = array();
            }
            $messageLocalization = getDeviceLocalizationByMessages($device->id);
            for ($j = 0; $j < count($alarms); $j++) {
                if($messageLocalization !== null) {
                    $alarms[$j]->latitude = $messageLocalization->latitude;
                    $alarms[$j]->longitude = $messageLocalization->longitude;
                    $alarms[$j]->accuracy = $messageLocalization->accuracy;
                    $alarms[$j]->internalId = $messageLocalization->internalId;
                }
                $alarm = $alarms[$j];
                $id = $alarm->id;
                DeviceDB::setDeviceAlarmRead($id);
            }
            $root->alarms = $alarms;
            $watchdogAlarms = DeviceDB::getDeviceWatchdogAlarmsByIdDevice($device->id);
            if($watchdogAlarms === null) {
                $watchdogAlarms = array();
            }
            for ($j = 0; $j < count($watchdogAlarms); $j++) {
                if($messageLocalization !== null) {
                    $watchdogAlarms[$j]->latitude = $messageLocalization->latitude;
                    $watchdogAlarms[$j]->longitude = $messageLocalization->longitude;
                    $watchdogAlarms[$j]->accuracy = $messageLocalization->accuracy;
                    $watchdogAlarms[$j]->internalId = $messageLocalization->internalId;
                }
                $watchdog = $watchdogAlarms[$j];
                $id = $watchdog->id;
                DeviceDB::setDeviceWatchdogAlarmRead($id);
            }
            $root->watchdogAlarms = $watchdogAlarms;
            $roots[$z] = $root;
            $z++;
        }
        $main = new stdClass();
        $main->roots = $roots;
        $main->message = "OK";
        die(json_encode($main));
    }
    else{
        die('{"message":"No devices found"}');
    }
}
else if ($_SERVER['REQUEST_METHOD'] === 'PUT') {

}
else if ($_SERVER['REQUEST_METHOD'] === 'GET') {

}
