<?php

declare(strict_types=1);

require_once dirname(__DIR__, 2) . implode(\DIRECTORY_SEPARATOR, ['', 'inc', 'include.php']);

header('Content-Type: application/json');
$door = new pvv\side\Door($pdo);

if ($_SERVER['REQUEST_METHOD'] === 'POST') {
  if (isset($_SERVER['HTTP_AUTHORIZATION'])) {
    [$type, $data] = explode(' ', $_SERVER['HTTP_AUTHORIZATION'], 2);
    if (strcasecmp($type, 'Bearer') == 0) {
      if (hash_equals($data, $DOOR_SECRET)) {
        handleSetState();
      } else {
        echo '{"status": "error", "message": "Invalid authentication key"}';
        exit;
      }
    } else {
      echo '{"status": "error", "message": "Invalid authentication method"}';
      exit;
    }
  } else {
    echo '{"status": "error", "message": "Missing authentication"}';
    exit;
  }
} elseif ($_SERVER['REQUEST_METHOD'] === 'GET') {

  if (isset($_GET['period'])) {
    $period = (string) htmlspecialchars($_GET['period']);

    if ($period == 'day') {
      $startTime = (new \DateTimeImmutable())
        ->setTimestamp(time())
        ->sub(new \DateInterval('P1D'));
    } elseif ($period == 'week') {
      $startTime = (new \DateTimeImmutable())
        ->setTimestamp(time())
        ->sub(new \DateInterval('P1W'));
    } else {
      echo '{"status": "error", "message": "Invalid period"}';
      exit;
    }

    $lines = $door->getEntriesAfter($startTime);
    if (isset($_GET['edgeonly']) && (bool) htmlspecialchars($_GET['edgeonly'])) {
      // Ignore repeats
      $lines = getChanges($lines);
    }

    echo json_encode([
      'status' => 'OK',
      'entries' => array_map(
        function ($line) {
          return [
            'time' => $line->getTimestamp(),
            'open' => $line->isOpen(),
          ];
        },
        $lines
      ),
    ]);
  } else {
    // Only last entry
    $line = $door->getCurrent();
    if (is_null($line)) {
      echo '{"status": "error", "message": "No door data"}';
      exit;
    }
    echo json_encode([
      'status' => 'OK',
      'time' => $line->getTimestamp(),
      'open' => $line->isOpen(),
    ]);
  }
}


function handleSetState(): void {
  global $door;

  $jsonobj = file_get_contents('php://input');
  $event = json_decode($jsonobj);

  if ((!isset($event->time)) || (!is_numeric($event->time))) {
    echo '{"status": "error", "message": "Invalid timestamp"}';
    exit;
  }
  if ((!isset($event->isDoorOpen)) || (!is_bool($event->isDoorOpen))) {
    echo '{"status": "error", "message": "Invalid door state"}';
    exit;
  }

  $time = (new \DateTimeImmutable())->setTimestamp((int) $event->time);

  $door->createEvent($time, $event->isDoorOpen);
  echo '{"status": "OK"}';
}

function getChanges($items) {
  $prevState = 2;
  $res = [];

  foreach ($items as $item) {
    if ($item->isOpen() !== $prevState) {
      $res[] = $item;
      $prevState = $item->isOpen();
    }
  }

  return $res;
}
