<?php

/*
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 */


$output = [];

$lat = round($VARS["latitude"], 2);
$lon = round($VARS["longitude"], 2);

if (empty($VARS["nocache"])) {
    $cacheresp = $memcache->get("gis.weather.$lat,$lon");
    if ($cacheresp !== false) {
        exitWithJson(json_decode($cacheresp, true));
    }
}

$json = file_get_contents("https://api.darksky.net/forecast/" . env("darksky_apikey", "") . "/$lat,$lon?units=us&exclude=alerts,flags");
$weather = json_decode($json, TRUE);

$minutely = [];

foreach ($weather["minutely"]["data"] as $m) {
    $minutely[] = [
        "time" => $m["time"],
        "precip" => round($m["precipIntensity"], 3)
    ];
}
$hourly = [];
$mintemp = false;
$maxtemp = false;
$maxwind = false;
$precipchance = false;
$preciptype = "";
$maxcloudcover = false;
$cloudcovers = []; // For calculating average
$summaryicon = "clear";
$oldicon = "clear";
$nowicon = "clear";
$lasttimestamp = time();

foreach ($weather["hourly"]["data"] as $w) {
    if ($w["time"] > strtotime("now + " . env("weather_summary_hours", 8) . " hours")) {
        continue;
    }

    $hourly[] = [
        "time" => $w["time"],
        "temp" => $w["temperature"],
        "feelslike" => $w["apparentTemperature"],
        "windspeed" => $w["windSpeed"],
        "winddirection" => $w["windBearing"],
        "precipchance" => $w["precipProbability"]
    ];

    if ($mintemp === false) {
        $mintemp = $w["temperature"];
    }
    if ($maxtemp === false) {
        $maxtemp = $w["temperature"];
    }
    if ($maxwind === false) {
        $maxwind = $w["windSpeed"];
    }
    if ($precipchance === false) {
        $precipchance = $w["precipProbability"];
    }
    if ($maxcloudcover === false) {
        $maxcloudcover = $w["cloudCover"] * 100.0;
    }
    $mintemp = min($w["temperature"], $mintemp);
    $maxtemp = max($w["temperature"], $maxtemp);
    $maxwind = max($w["windSpeed"], $maxwind);
    $precipchance = max($w["precipProbability"], $precipchance);
    $maxcloudcover = max($w["cloudCover"] * 100.0, $maxcloudcover);
    $cloudcovers[] = $w["cloudCover"];
    $lasttimestamp = max($w["time"], $lasttimestamp);
}

$avgcloudcover = array_sum($cloudcovers) / count($cloudcovers);

if ($precipchance > 0.2) {
    $summaryicon = "rain";
    $oldicon = "rain";
    if ($maxtemp < 28) {
        $summaryicon = "snow";
        $oldicon = "snow";
    }
} else if ($mintemp > 55 && $maxtemp > 85 && $avgcloudcover <= 25) {
    $summaryicon = "heat";
} else if ($maxwind >= 20) {
    $summaryicon = "windy";
    $oldicon = "windy";
} else if ($avgcloudcover >= 75 || $maxcloudcover >= 90) {
    $summaryicon = "cloudy";
    $oldicon = "cloudy";
} else if ($avgcloudcover <= 15) {
    $summaryicon = "mostly-sunny";
    $oldicon = "partly-cloudy";
} else if ($maxcloudcover >= 33) {
    $summaryicon = "partly-cloudy";
    $oldicon = "partly-cloudy";
}

if ($weather["currently"]["icon"] == "rain") {
    $nowicon = "rain";
} else if ($weather["currently"]["icon"] == "snow") {
    $nowicon = "snow";
} else if ($weather["currently"]["icon"] == "fog") {
    $nowicon = "fog";
} else if ($weather["currently"]["icon"] == "partly-cloudy-day" || $weather["currently"]["icon"] == "partly-cloudy-night") {
    $nowicon = "partly-cloudy";
} else if ($weather["currently"]["icon"] == "cloudy") {
    $nowicon = "cloudy";
}
if (($nowicon == "mostly-sunny" || $nowicon == "clear" || $nowicon == "partly-cloudy") && $weather["currently"]["apparentTemperature"] > 80) {
    $nowicon = "heat";
}

$dailyforecast = [];

foreach ($weather["daily"]["data"] as $w) {
    $dailyforecast[] = [
        "date" => $w["time"],
        "temp" => [
            "min" => $w["temperatureLow"],
            "max" => $w["temperatureHigh"]
        ],
        "precipitation" => [
            "chance" => empty($w["precipProbability"]) ? 0 : $w["precipProbability"]
        ],
        "windspeed" => $w["windSpeed"],
        "uv_index" => round($w["uvIndex"], 1)
    ];
}

$reverse_geocode_url = ($_SERVER['SERVER_PORT'] == 443 ? "https://" : "http://") . $_SERVER['HTTP_HOST'] . str_replace("/gis/weather/", "/gis/geocode/reverse/", $_SERVER['REQUEST_URI']);
$geocode = json_decode(file_get_contents($reverse_geocode_url), TRUE);

$location_name = "";

$epa_uv_index = null;

if ($geocode["status"] == "OK") {
    $location_name = implode(", ", [$geocode["address"]["city"], $geocode["address"]["state"]]);
    $city = $geocode["address"]["city"];
    $state = $geocode["address"]["state"];
    try {
        $epauv = $memcache->get("gis.weather.epauv.$state.$city");
        if ($epauv !== false) {
            $epa_data = json_decode($epauv, true);
        } else {
            $epa_url = "https://enviro.epa.gov/enviro/efservice/getEnvirofactsUVHOURLY/CITY/$city/STATE/$state/JSON";
            $epa_json = file_get_contents($epa_url);
            $epa_data = json_decode($epa_json, true);
            $memcache->set("gis.weather.epauv.$state.$city", $epa_json, 60 * 60 * 4);
        }

        // Find which returned result is closest to the current date and time
        $closest = $epa_data[0];
        foreach ($epa_data as $entry) {
            if (abs(time() - strtotime(str_replace("/", " ", $entry["DATE_TIME"]))) < abs(time() - strtotime(str_replace("/", " ", $closest["DATE_TIME"])))) {
                $closest = $entry;
            }
        }
        $epa_uv_index = min($closest["UV_VALUE"], 11);
    } catch (Exception $ex) {
        $epa_uv_index = null;
    }
} else {
    $location_name = "Unknown";
}

$output = [
    "status" => "OK",
    "summary" => [
        "icon" => $summaryicon,
        "temp" => [
            "min" => $mintemp,
            "max" => $maxtemp
        ],
        "precipitation" => [
            "type" => $preciptype,
            "chance" => $precipchance
        ],
        "windspeed" => $maxwind,
        "cloudcover" => $maxcloudcover,
        "cloudcover_avg" => $avgcloudcover,
        "forecast_hours" => env("weather_summary_hours", 8),
        "forecast_until" => $lasttimestamp
    ],
    "now" => [
        "icon" => $nowicon,
        "temp" => $weather["currently"]["temperature"],
        "feelslike" => $weather["currently"]["apparentTemperature"],
        "uv_index" => (is_null($epa_uv_index) ? min(round($weather["currently"]["uvIndex"], 1), 11) : $epa_uv_index),
        "windspeed" => $weather["currently"]["windSpeed"],
        "winddirection" => $weather["currently"]["windBearing"]
    ],
    "today" => [
        "minutely" => $minutely,
        "hourly" => $hourly
    ],
    "forecast" => $dailyforecast,
    // From here to the next comment is deprecated
    "icon" => $oldicon,
    "temp" => [
        "min" => $mintemp,
        "max" => $maxtemp
    ],
    "precipitation" => [
        "type" => $preciptype,
        "chance" => $precipchance
    ],
    "windspeed" => $maxwind,
    "cloudcover" => $maxcloudcover,
    "cloudcover_avg" => $avgcloudcover,
    "forecast_hours" => env("weather_summary_hours", 8),
    "forecast_until" => $lasttimestamp,
    // the next comment
    "location_name" => $location_name,
    "latitude" => $lat,
    "longitude" => $lon,
    "source" => [
        "text" => "Powered by Dark Sky" . (is_null($epa_uv_index) ? "" : ", EPA"),
        "url" => "https://darksky.net/poweredby/"
    ]
];

$memcache->set("gis.weather.$lat,$lon", json_encode($output), 60 * 10);
exitWithJson($output);
