<?php
putenv("TZ=UTC");
define("IEM_APPID", 153);
require_once "../../config/settings.inc.php";
date_default_timezone_set('UTC');
require_once "../../include/database.inc.php";
require_once "../../include/forms.php";
require_once "../../include/myview.php";
$t = new MyView();
$t->iemselect2 = TRUE;
require_once "../../include/mos_lib.php";
$mosdb = iemdb("mos");
pg_query($mosdb, "SET TIME ZONE 'UTC'");

$year = get_int404("year", date("Y", time() + 86400));
$month = get_int404("month", date("m", time() + 86400));
$day = get_int404("day", date("d", time() + 86400));
$model = get_str404("model", "GFS", 3);
$station = get_str404("station", "KAMW", 6);
$vname = strtolower(get_str404("vname", "tmp"));
/** @disregard complaint about mosvars being undefined */
if (!array_key_exists($vname, $mosvars)) {
    $vname = "tmp";
}
$models = array(
    "GFS" => "AVN/GIS",
    "MEX" => "GFS Extended (MEX)",
    "NAM" => "NAM",
    "ETA" => "ETA",
    "NBS" => "NBS",
    "NBE" => "NBE",
    "LAV" => "LAV",
);
if (!array_key_exists($model, $models)) {
    $model = "NBE";
}

$centeredTime = new DateTimeImmutable("$year-$month-$day 12:00:00", new DateTimeZone('UTC'));
$namSwitch = new DateTimeImmutable("2008-12-09 12:00:00", new DateTimeZone('UTC'));
$gfsSwitch = new DateTimeImmutable("2003-12-16 12:00:00", new DateTimeZone('UTC'));
// When archival changed from +1 to standard synop hours
$nbmSwitch = new DateTimeImmutable("2026-05-07 13:00:00", new DateTimeZone('UTC'));
if ($model == "NAM" && $centeredTime < $namSwitch) {
    $model = "ETA";
}
if ($model == "GFS" && $centeredTime < $gfsSwitch) {
    $model = "AVN";
}

// Compute the window of time to look for model runs
$startDT = $centeredTime->sub(new DateInterval('P3DT12H'));
$endDT = $centeredTime->add(new DateInterval('P1D'));

if ($model == "MEX" || $model == "NBE") {
    $endDT = $centeredTime->add(new DateInterval('P7D'));
}

// Archive interval in hours
$runsper = array(
    "GFS" => 6,
    "AVN" => 6,
    "NAM" => 12,
    "ETA" => 12,
    "MEX" => 12,
    "NBE" => 6,
    "NBS" => 6,
    "LAV" => 6
);
// Offset from hour modulo 6 for some models
// So 0z becomes 1z
$hroffset = array();
if ($centeredTime < $nbmSwitch) {
    $hroffset["NBS"] = 1;
    $hroffset["NBE"] = 1;
}
// compute the run times available between the start and end times
$runtimes = array();
$runtimeParamValues = array();
$runtimeEpochs = array();
$sts = $startDT->getTimestamp();
$ets = $endDT->getTimestamp();
$hroff = isset($hroffset[$model]) ? $hroffset[$model] : 0;
$sts = $sts + (($sts / 3600) % $runsper[$model] + $hroff) * 3600;
for ($now = $sts; $now <= $ets; $now += (3600 * $runsper[$model])) {
    $runtimeDT = (new DateTimeImmutable("@$now"))->setTimezone(
        new DateTimeZone('UTC')
    );
    $s = $runtimeDT->format("Y-m-d H:i");
    $runtimes[] = $s;
    $runtimeParamValues[] = $runtimeDT->format("Y-m-d\\TH:i:s\\Z");
    $runtimeEpochs[] = $runtimeDT->getTimestamp();
}

/** @var array<string, array> $data */
$data = array();
$table = sprintf(
    "<div class=\"card shadow-sm border-0 mb-4\">" .
        "<div class=\"card-header bg-body-tertiary\">" .
        "<div class=\"d-flex flex-wrap align-items-center justify-content-between gap-2\">" .
        "<h2 class=\"h5 mb-0\">[%s] %s MOS %s</h2>" .
        "<span class=\"badge text-bg-secondary\">Runs near %sZ</span>" .
        "</div></div><div class=\"card-body p-0\">",
    $station,
    $model,
    strtoupper($vname),
    $centeredTime->format("Y-m-d H")
);
$table .= sprintf(
    "<table class=\"table table-sm table-bordered table-striped table-hover mb-0\">" .
        "<thead class=\"table-light sticky-top\"><tr><th scope=\"col\"></th><th scope=\"col\" colspan=\"%s\">" .
        "Model Run Initialized at (UTC)</th></tr><tr><th scope=\"col\" class=\"text-nowrap\">Valid (UTC)</th>",
    sizeof($runtimes)
);
foreach ($runtimes as $i => $s) {
    $table .= sprintf(
        "<th scope=\"col\" class=\"text-nowrap\">%sZ</th>",
        date('d/H', $runtimeEpochs[$i])
    );
    $data[$s] = array();
}
$table .= "</tr></thead><tbody>\n";

$stname = iem_pg_prepare($mosdb, "SELECT *, t06_1 ||'/'||t06_2 as t06, " .
    "t12_1 ||'/'|| t12_2 as t12 from alldata WHERE " .
    "runtime = ANY($1::timestamptz[]) and station = $2 and model = $3");
$datestrs = "{" . implode(",", $runtimeParamValues) . "}";
$rs = pg_execute(
    $mosdb,
    $stname,
    array($datestrs, $station, $model));
while ($row = pg_fetch_assoc($rs)) {
    $data[substr($row["runtime"], 0, 16)][substr($row["ftime"], 0, 16)] = $row[$vname];
}

// The table is oriented with columns being sequential model runs
// and rows being sequential valid times.  To make things simple,
// just iterate over every hour between the start and end times
for ($now = $sts; $now <= ($ets + 3 * 86400); $now += 3600) {
    $thisrow = sprintf("<tr><th scope=\"row\" class=\"text-nowrap\">%sZ</th>", date('d/H', $now));
    $allnulls = TRUE;
    $lookup = date('Y-m-d H:i', $now);
    foreach ($runtimes as $k => $s) {
        $val = null;
        if (array_key_exists($lookup, $data[$s])) {
            $val = $data[$s][$lookup];
        }
        if (!is_null($val)) {
            $allnulls = FALSE;
        }
        $thisrow .= sprintf("<td>%s</td>", $val);
    }
    $thisrow .= "</tr>\n";
    if (!$allnulls) {
        $table .= $thisrow;
    }
}
$table .= "</tbody></table></div></div>";

$t->title = "Model Output Statistics Table for $station";

/** @disregard complaint about mosvars being undefined */
$variableSelect = make_select(
    "vname",
    $vname,
    $mosvars,
    "",
    "form-select iemselect2",
    FALSE,
    TRUE,
    TRUE,
    array("id" => "vname")
);
$modelSelect = make_select(
    "model",
    $model,
    $models,
    "",
    "form-select",
    FALSE,
    FALSE,
    TRUE,
    array("id" => "model")
);
$yearSelect = str_replace(
    "<select",
    "<select class=\"form-select\" id=\"year\"",
    yearSelect(2000, $year)
);
$monthSelect = str_replace(
    "<select",
    "<select class=\"form-select\" id=\"month\"",
    monthSelect($month)
);
$daySelect = str_replace(
    "<select",
    "<select class=\"form-select\" id=\"day\"",
    daySelect($day)
);

$content = <<<EOM
<nav aria-label="breadcrumb" class="mb-3">
    <ol class="breadcrumb">
        <li class="breadcrumb-item"><a href="/mos/">Model Output Statistics</a></li>
        <li class="breadcrumb-item active" aria-current="page">Single Variable Data Table</li>
    </ol>
</nav>

<div class="alert alert-info mb-4" role="alert">
    This page compares a single MOS variable for one forecast point across multiple model runs,
    making it easier to see forecast trends over time. Use four-character station IDs (for example, KAMW).
</div>

<div class="card shadow-sm border-0 mb-4">
    <div class="card-header bg-primary-subtle">
        <h1 class="h5 mb-0">MOS Table Controls</h1>
    </div>
    <div class="card-body">
        <form name="updator" class="row g-3 align-items-end">
            <div class="col-md-3">
                <label for="station" class="form-label">Station</label>
                <input id="station" type="text" name="station" value="$station" class="form-control" maxlength="6" required>
            </div>
            <div class="col-md-5">
                <label for="vname" class="form-label">Variable</label>
                $variableSelect
            </div>
            <div class="col-md-4">
                <label for="model" class="form-label">Model</label>
                $modelSelect
            </div>

            <div class="col-sm-4 col-md-2">
                <label for="year" class="form-label">Year</label>
                $yearSelect
            </div>
            <div class="col-sm-4 col-md-2">
                <label for="month" class="form-label">Month</label>
                $monthSelect
            </div>
            <div class="col-sm-4 col-md-2">
                <label for="day" class="form-label">Day</label>
                $daySelect
            </div>
            <div class="col-md-6 d-grid d-md-flex justify-content-md-end">
                <button type="submit" class="btn btn-primary px-4">Generate Table</button>
            </div>
        </form>
    </div>
</div>
EOM;

$content .= $table;
$t->content = $content;
$t->render('full.phtml');
