<?php
$response = [];
$response['context'] = "poi3dSensorQuery";

function signRequest($method, $uri, $service, $region, $accessKey, $secretKey, $payload, $headers) {
  $timestamp = gmdate('Ymd\THis\Z');
  $date = gmdate('Ymd');

  // Step 1: Create Canonical Request
  $canonicalUri = $uri;
  $canonicalQueryString = '';
  $canonicalHeaders = "host:{$headers['host']}\n" . "x-amz-date:{$timestamp}\n";
  $signedHeaders = 'host;x-amz-date';

  $hashedPayload = hash('sha256', $payload);
  $canonicalRequest = "{$method}\n{$canonicalUri}\n{$canonicalQueryString}\n{$canonicalHeaders}\n{$signedHeaders}\n{$hashedPayload}";

  // Step 2: Create String to Sign
  $algorithm = 'AWS4-HMAC-SHA256';
  $credentialScope = "{$date}/{$region}/{$service}/aws4_request";
  $hashedCanonicalRequest = hash('sha256', $canonicalRequest);
  $stringToSign = "{$algorithm}\n{$timestamp}\n{$credentialScope}\n{$hashedCanonicalRequest}";

  // Step 3: Calculate Signature
  $kDate = hash_hmac('sha256', $date, 'AWS4' . $secretKey, true);
  $kRegion = hash_hmac('sha256', $region, $kDate, true);
  $kService = hash_hmac('sha256', $service, $kRegion, true);
  $kSigning = hash_hmac('sha256', 'aws4_request', $kService, true);
  $signature = hash_hmac('sha256', $stringToSign, $kSigning);

  // Step 4: Add Signing Information to Headers
  $authorizationHeader = "{$algorithm} Credential={$accessKey}/{$credentialScope}, SignedHeaders={$signedHeaders}, Signature={$signature}";

  return [
    'Authorization' => $authorizationHeader,
    'x-amz-date' => $timestamp,
  ];
}

function getDeviceShadow($host, $region, $accessKey, $secretKey, $thingName) {
  $method = 'GET';
  $uri = "/things/{$thingName}/shadow";
  $service = 'iotdata';
  $payload = '';

  $headers = [
    'host' => $host,
  ];

  $signedHeaders = signRequest($method, $uri, $service, $region, $accessKey, $secretKey, $payload, $headers);

  $url = "https://{$host}{$uri}";

  $ch = curl_init($url);
  curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
  curl_setopt($ch, CURLOPT_HTTPHEADER, [
    "Authorization: {$signedHeaders['Authorization']}",
    "x-amz-date: {$signedHeaders['x-amz-date']}",
    "Content-Type: application/json",
  ]);

  $response = curl_exec($ch);

  if (curl_errno($ch)) {
    echo 'Request Error: ' . curl_error($ch) . "\n";
    return null;
  }

  $httpStatus = curl_getinfo($ch, CURLINFO_HTTP_CODE);
  curl_close($ch);

  if ($httpStatus == 200) {
    return $response;
  } else {
    echo "Error querying device shadow. HTTP Status: $httpStatus\n";
    echo "Response: $response\n";
    return null;
  }
}

if ( isset($_POST['data']) ) {
  
  $postData = json_decode ( $_POST['data']);
  $queryData = $postData->queryData;
  
  //format of posted data:
  /*
  data:
  {
    queryData:
    {
      sensorUrl:"", //the id or URL which accesses the sensor
      uName:"",     //the user name
      uPwd:""       //the password
    }
  }
  */
  
  if($queryData == null)
  {
    $response['success'] = false;
    $response['infoText'] = "invalid post data";
    $response['value'] = 0.0;
    echo json_encode($response);  
    exit;
  }
  
  //enable CORS
  //Allow from any origin https://stackoverflow.com/questions/8719276/cross-origin-request-headerscors-with-php-headers
  if(isset($_SERVER["HTTP_ORIGIN"]))
  {
    // You can decide if the origin in $_SERVER['HTTP_ORIGIN'] is something you want to allow, or as we do here, just allow all
    header("Access-Control-Allow-Origin: {$_SERVER['HTTP_ORIGIN']}");
  }
  else
  {
    //No HTTP_ORIGIN set, so we allow any. You can disallow if needed here
    header("Access-Control-Allow-Origin: *");
  }
  
  header("Access-Control-Allow-Credentials: true");
  header("Access-Control-Max-Age: 600");    // cache for 10 minutes
  
  if($_SERVER["REQUEST_METHOD"] == "OPTIONS")
  {
    if (isset($_SERVER["HTTP_ACCESS_CONTROL_REQUEST_METHOD"]))
      header("Access-Control-Allow-Methods: POST, GET, OPTIONS, DELETE, PUT"); //Make sure you remove those you do not want to support

    if (isset($_SERVER["HTTP_ACCESS_CONTROL_REQUEST_HEADERS"]))
      header("Access-Control-Allow-Headers: {$_SERVER['HTTP_ACCESS_CONTROL_REQUEST_HEADERS']}");
  
    //Just exit with 200 OK with the above headers for OPTIONS method
    exit(0);
  }

  if (( empty( $queryData->sensorUrl ) ) || ( empty( $queryData->uName ) ) || ( empty( $queryData->uPwd ) ) ){
    $response['success'] = false;
    $response['infoText'] = "not enough parameters given";
    $response['value'] = 0.0;
    echo json_encode($response);  
    exit;
  }
  
  // ---------- query implementation for sensors in AWS IoT Core ----------
  
  $nameParts = explode("|", $queryData->uName);
  $accessParts = explode("|", $queryData->uPwd);
  
  $host = $nameParts[0];               //IoT endpoint (passed in $queryData->uName[0])
  $region = $nameParts[1];             //passed in $queryData->uName[1] e.g., "us-east-1" 
  $accessKey = $accessParts[0];        //AWS Access Key ID (passed in $queryData->uPwd[0])
  $secretKey = $accessParts[1];        //AWS Secret Access Key (passed in $queryData->uPwd[1])
  $thingName = $queryData->sensorUrl;  //Thing Name (passed in $queryData->sensorUrl

  $sensorData = getDeviceShadow($host, $region, $accessKey, $secretKey, $thingName);
  
  if($sensorData != null){
    $response['success'] = true;
    $response['infoText'] = "test sensor object returned";
    $response['value'] = json_decode($sensorData, true);    
    //print_r($sensorData);
    echo json_encode($response);  
    exit;
  }

  // ------------------------------------------------------------

  //std error
  $response['success'] = false;
  $response['infoText'] = "could not query sensor";
  $response['value'] = 0.0;
  echo json_encode($response);  
}
else {
  // initial condition failed
  $response['success'] = false;
  $response['infoText'] = "no query data given";
  $response['value'] = 0.0;
  echo json_encode($response);  
}
?>
