<?php
//
// Simple Digital Clock Dashlet (Bare TZ list + Font picker + Subtitle size + 12/24 toggle)
//

include_once(dirname(__FILE__) . '/../dashlethelper.inc.php');

// Run the initialization function
simple_digital_init();

function simple_digital_init()
{
    $name = "simple_digital";

    $args = array(
        DASHLET_NAME            => $name,
        DASHLET_VERSION         => "1.4.0",
        DASHLET_AUTHOR          => "Nagios Enterprises, LLC",
        DASHLET_DESCRIPTION     => _("Resizable digital clock (no seconds) with a bare-bones time zone list, 12/24‑hour toggle, subtitle, font picker, and subtitle size control."),
        DASHLET_FILTER_GROUPS   => array("other"),
        DASHLET_COPYRIGHT       => "Copyright &copy; 2025 Nagios Enterprises, LLC",
        DASHLET_HOMEPAGE        => "https://www.nagios.com",
        DASHLET_FUNCTION        => "simple_digital_func",
        DASHLET_TITLE           => _("Digital Clock"),
        DASHLET_OUTBOARD_CLASS  => "simple_digital_outboardclass",
        DASHLET_INBOARD_CLASS   => "simple_digital_inboardclass",
        DASHLET_PREVIEW_CLASS   => "simple_digital_previewclass",
        DASHLET_WIDTH           => "300",
        DASHLET_HEIGHT          => "200",
        DASHLET_OPACITY         => "1.0",
        DASHLET_BACKGROUND      => "",
        DASHLET_ISCUSTOM        => false
    );

    register_dashlet($name, $args);
}

function simple_digital_func($mode = DASHLET_MODE_PREVIEW, $id = "", $args = null)
{
    $output = "";

    // ----- Curated options -----
    $server_tz = date_default_timezone_get();

    // Popular, human-friendly regions (you can tweak labels to taste)
    $CURATED_TZ = array(
        'America/New_York'      => 'US — Eastern',
        'America/Chicago'       => 'US — Central',
        'America/Denver'        => 'US — Mountain',
        'America/Los_Angeles'   => 'US — Pacific',
        'Europe/London'         => 'UK — London',
        'Europe/Berlin'         => 'Europe — Central (Berlin)',
        'Asia/Kolkata'          => 'India',
        'Asia/Shanghai'         => 'China',
        'Asia/Tokyo'            => 'Japan',
        'Australia/Sydney'      => 'Australia — Eastern (Sydney)',
        'Pacific/Auckland'      => 'New Zealand',
        'Etc/UTC'               => 'UTC', // keep here too for convenience
    );

    // "Main 24" — one representative IANA zone for each whole-hour UTC offset (UTC−11 … UTC+12).
    // Chosen to be non-DST where possible so the offset is stable year-round.
    $TZ_BY_OFFSET_24 = array(
        'Pacific/Pago_Pago'              => 'UTC−11 — American Samoa',
        'Pacific/Honolulu'               => 'UTC−10 — Hawaiʻi',
        'Pacific/Gambier'                => 'UTC−09 — Gambier Islands',
        'Pacific/Pitcairn'               => 'UTC−08 — Pitcairn',
        'America/Phoenix'                => 'UTC−07 — Arizona (no DST)',
        'America/Guatemala'              => 'UTC−06 — Guatemala',
        'America/Bogota'                 => 'UTC−05 — Colombia',
        'America/Barbados'               => 'UTC−04 — Barbados',
        'America/Argentina/Buenos_Aires' => 'UTC−03 — Argentina',
        'Atlantic/South_Georgia'         => 'UTC−02 — South Georgia',
        'Atlantic/Cape_Verde'            => 'UTC−01 — Cape Verde',
        'Etc/UTC'                        => 'UTC±00 — Coordinated Universal Time',
        'Africa/Lagos'                   => 'UTC+01 — West Africa',
        'Africa/Johannesburg'            => 'UTC+02 — South Africa',
        'Africa/Nairobi'                 => 'UTC+03 — East Africa',
        'Asia/Dubai'                     => 'UTC+04 — United Arab Emirates',
        'Asia/Karachi'                   => 'UTC+05 — Pakistan',
        'Asia/Dhaka'                     => 'UTC+06 — Bangladesh',
        'Asia/Bangkok'                   => 'UTC+07 — Indochina (Bangkok)',
        'Asia/Shanghai'                  => 'UTC+08 — China (Shanghai)',
        'Asia/Tokyo'                     => 'UTC+09 — Japan',
        'Australia/Brisbane'             => 'UTC+10 — Australia (Brisbane)',
        'Pacific/Guadalcanal'            => 'UTC+11 — Solomon Islands',
        'Pacific/Tarawa'                 => 'UTC+12 — Kiribati (Tarawa)',
    );

    // Curated font stacks (CSS font-family values)
    $CURATED_FONTS = array(
        'inherit'       => array('label' => 'Theme Default (inherit)', 'stack' => 'inherit'),
        'seven_segment' => array('label' => 'Seven‑Segment style', 'stack' => '"DSEG7 Classic","DSEG7Classic-Regular","DS-Digital","Digital-7","Orbitron","Courier New",monospace'),
        'mono_clean'    => array('label' => 'Monospaced Clean', 'stack' => '"Roboto Mono","Menlo","Consolas","DejaVu Sans Mono",monospace'),
        'orbitron'      => array('label' => 'Orbitron / Tech', 'stack' => '"Orbitron","Arial Black","Segoe UI",sans-serif'),
        'lcd'           => array('label' => 'LCD‑ish', 'stack' => '"LCD","DS-Digital","Digital-7","Courier New",monospace'),
    );

    // ----- Read & sanitize args -----
    $configured_timezone = isset($args['timezone']) ? trim($args['timezone']) : 'browser'; // 'browser' | 'server' | curated IANA key
    $font_key = isset($args['font']) ? trim($args['font']) : 'inherit';
    $subtitle_raw = isset($args['subtitle']) ? $args['subtitle'] : '';

    // 12/24-hour toggle ("12" or "24"; default 12-hour)
    $hour_format = isset($args['hour_format']) ? trim($args['hour_format']) : '12';
    $hour_format = ($hour_format === '24') ? '24' : '12';

    // subtitle size (% of time font)
    $subtitle_ratio = isset($args['subtitle_ratio']) ? (int)$args['subtitle_ratio'] : 22;   // default 22%
    $subtitle_ratio = max(10, min(100, $subtitle_ratio)); // clamp to 10–100%

    // Enforce 50-char limit server-side
    if (function_exists('mb_substr')) {
        $subtitle_raw = mb_substr($subtitle_raw, 0, 50);
    } else {
        $subtitle_raw = substr($subtitle_raw, 0, 50);
    }
    $subtitle_safe_html = htmlspecialchars($subtitle_raw, ENT_QUOTES, 'UTF-8');

    // Font stack for JS
    $font_stack = isset($CURATED_FONTS[$font_key]) ? $CURATED_FONTS[$font_key]['stack'] : $CURATED_FONTS['inherit']['stack'];

    switch ($mode) {

        case DASHLET_MODE_GETCONFIGHTML:
            ob_start();
            ?>
            <div class="simple-digital-config">
                <!-- Time Zone -->
                <div class="control-group">
                    <label for="timezone"><strong><?php echo _("Time Zone"); ?></strong></label>
                    <select name="timezone" id="timezone" class="form-control" style="max-width:100%;">
                        <option value="browser" <?php echo ($configured_timezone === 'browser' ? 'selected' : ''); ?>>
                            <?php echo _("Browser (automatic)"); ?>
                        </option>
                        <option value="server" <?php echo ($configured_timezone === 'server' ? 'selected' : ''); ?>>
                            <?php echo sprintf(_("Server (%s)"), htmlspecialchars($server_tz, ENT_QUOTES, 'UTF-8')); ?>
                        </option>
                        <optgroup label="<?php echo _("Popular Time Zones"); ?>">
                            <?php foreach ($CURATED_TZ as $iana => $label): ?>
                                <option value="<?php echo htmlspecialchars($iana, ENT_QUOTES, 'UTF-8'); ?>"
                                    <?php echo ($configured_timezone === $iana ? 'selected' : ''); ?>>
                                    <?php echo htmlspecialchars($label, ENT_QUOTES, 'UTF-8'); ?>
                                </option>
                            <?php endforeach; ?>
                        </optgroup>

                        <optgroup label="<?php echo _('By UTC Offset (24 zones)'); ?>">
                            <?php foreach ($TZ_BY_OFFSET_24 as $iana => $label): ?>
                                <option value="<?php echo htmlspecialchars($iana, ENT_QUOTES, 'UTF-8'); ?>"
                                    <?php echo ($configured_timezone === $iana ? 'selected' : ''); ?>>
                                    <?php echo htmlspecialchars($label, ENT_QUOTES, 'UTF-8'); ?>
                                </option>
                            <?php endforeach; ?>
                        </optgroup>
                    </select>
                </div>

                <!-- Time format -->
                <div class="control-group" style="margin-top:10px;">
                    <label for="hour_format"><strong><?php echo _("Time format"); ?></strong></label>
                    <select name="hour_format" id="hour_format" class="form-control" style="max-width:100%;">
                        <option value="12" <?php echo ($hour_format === '12' ? 'selected' : ''); ?>>
                            <?php echo _("12-hour (AM/PM)"); ?>
                        </option>
                        <option value="24" <?php echo ($hour_format === '24' ? 'selected' : ''); ?>>
                            <?php echo _("24-hour (00-23)"); ?>
                        </option>
                    </select>
                    <p class="help-block" style="margin-top:6px;">
                        <?php echo _("Choose between 12-hour (with AM/PM) or 24-hour time."); ?>
                    </p>
                </div>

                <!-- Font -->
                <div class="control-group" style="margin-top:10px;">
                    <label for="font"><strong><?php echo _("Font"); ?></strong></label>
                    <select name="font" id="font" class="form-control" style="max-width:100%;">
                        <?php foreach ($CURATED_FONTS as $key => $meta): ?>
                            <option value="<?php echo htmlspecialchars($key, ENT_QUOTES, 'UTF-8'); ?>"
                                <?php echo ($font_key === $key ? 'selected' : ''); ?>>
                                <?php echo htmlspecialchars($meta['label'], ENT_QUOTES, 'UTF-8'); ?>
                            </option>
                        <?php endforeach; ?>
                    </select>
                    <p class="help-block" style="margin-top:6px;">
                        <?php echo _("If a listed font isn't installed, the next fallback is used automatically."); ?>
                    </p>
                </div>

                <!-- Subtitle -->
                <div class="control-group" style="margin-top:10px;">
                    <label for="subtitle"><strong><?php echo _("Subtitle (optional)"); ?></strong></label>
                    <input type="text"
                           id="subtitle"
                           name="subtitle"
                           maxlength="40"
                           value="<?php echo $subtitle_safe_html; ?>"
                           class="form-control"
                           style="width:100%;"
                           placeholder="<?php echo htmlspecialchars(_('Up to 40 characters (shown under the digits)'), ENT_QUOTES, 'UTF-8'); ?>">
                </div>

                <!-- Subtitle size -->
                <div class="control-group" style="margin-top:10px;">
                    <label for="subtitle_ratio"><strong><?php echo _("Subtitle size (% of time)"); ?></strong></label>
                    <input type="number"
                           id="subtitle_ratio"
                           name="subtitle_ratio"
                           min="10" max="60" step="1"
                           value="<?php echo (int)$subtitle_ratio; ?>"
                           class="form-control"
                           style="width:100%;max-width:200px;">
                    <p class="help-block" style="margin-top:6px;">
                        <?php echo _("Default 22%. Increase to make the subtitle larger relative to the digits."); ?>
                    </p>
                </div>
            </div>
            <?php
            $output = ob_get_clean();
            break;


        case DASHLET_MODE_PREVIEW:
            $imgbase = get_dashlet_url_base("simple_digital") . "/images/";
            $imgdir  = dirname(__FILE__) . "/images/";

            $output = "<img src='" . $imgbase . "preview.png' alt='Simple Digital' style='max-width:100%;height:auto;'>";

            if (function_exists('is_neptune') && is_neptune()) {
                if (function_exists('get_theme') && get_theme() == "neptunelight" && file_exists($imgdir . "neptune_light_preview.png")) {
                    $output = "<img src='" . $imgbase . "neptune_light_preview.png' alt='Simple Digital' />";
                } elseif (file_exists($imgdir . "neptune_dark_preview.png")) {
                    $output = "<img src='" . $imgbase . "neptune_dark_preview.png' alt='Simple Digital' />";
                }
            }

            break;


        case DASHLET_MODE_OUTBOARD:
        case DASHLET_MODE_INBOARD:
            // Normalize timezone for JS
            $tz_for_js = '';
            if ($configured_timezone === 'server') {
                $tz_for_js = $server_tz;
            } elseif ($configured_timezone !== 'browser') {
                // Allow popular curated + the 24-by-offset list
                $ALLOWED_TZ = $CURATED_TZ + $TZ_BY_OFFSET_24; // union by keys
                $tz_for_js = array_key_exists($configured_timezone, $ALLOWED_TZ) ? $configured_timezone : '';
            }

            // HTML + JS
            $output = '
            <div id="sd-container-' . $id . '" style="width:100%;height:100%;display:flex;align-items:center;justify-content:center;overflow:hidden;">
                <div id="sd-inner-' . $id . '" style="display:flex;flex-direction:column;align-items:center;justify-content:center;max-width:100%;max-height:100%;text-align:center;">
                    <div id="sd-time-' . $id . '" style="white-space:nowrap;font-weight:600;"></div>
                    <div id="sd-sub-' . $id . '" style="margin-top:0.25em;word-break:break-word;overflow-wrap:anywhere;"></div>
                </div>
            </div>

            <script>
            (function() {
                var container = document.getElementById("sd-container-' . $id . '");
                var inner = document.getElementById("sd-inner-' . $id . '");
                var timeEl = document.getElementById("sd-time-' . $id . '");
                var subEl  = document.getElementById("sd-sub-' . $id . '");

                var configuredTimeZone = ' . json_encode($tz_for_js) . '; // "" => browser default
                var subtitle = ' . json_encode($subtitle_raw) . ';
                var fontStack = ' . json_encode($font_stack) . '; // CSS font-family value
                var hourFormat = ' . json_encode($hour_format) . '; // "12" | "24"
                var subtitlePercent = ' . json_encode((int)$subtitle_ratio) . '; // subtitle size %

                // Apply font (if not inherit)
                if (fontStack && fontStack !== "inherit") {
                    timeEl.style.fontFamily = fontStack;
                    subEl.style.fontFamily = fontStack;
                }
                // Tabular numbers (where supported) + subtle spacing
                timeEl.style.fontVariantNumeric = "tabular-nums";
                timeEl.style.letterSpacing = "0.02em";

                if (subEl) subEl.textContent = subtitle || "";

                function formatNow() {
                    var is24 = (hourFormat === "24");
                    var opts = {
                        // 24h uses two-digit hours (00-23). 12h keeps natural (no leading zero).
                        hour: is24 ? "2-digit" : "numeric",
                        minute: "2-digit",
                        hour12: !is24,
                        hourCycle: is24 ? "h23" : "h12" // be explicit across locales
                    };
                    if (configuredTimeZone) opts.timeZone = configuredTimeZone;
                    return new Intl.DateTimeFormat("en-US", opts).format(new Date());
                }

                var last = "";
                function updateTime() {
                    var t = formatNow();
                    if (t !== last) {
                        last = t;
                        timeEl.textContent = t;
                        resizeToFit();
                    }
                }

                function resizeToFit() {
                    if (!container || !inner) return;

                    var w = container.clientWidth;
                    var h = container.clientHeight;
                    if (w <= 0 || h <= 0) return;

                    var minSize = 4, maxSize = 1000, mid, pad = 16;

                    timeEl.style.whiteSpace = "nowrap";

                    function applySize(sz) {
                        timeEl.style.fontSize = sz + "px";
                        var sub = Math.max(8, Math.floor(sz * (subtitlePercent / 100))); // use configured %
                        subEl.style.fontSize = sub + "px";
                        timeEl.style.lineHeight = "1.0";
                        subEl.style.lineHeight = "1.1";
                    }

                    while (minSize <= maxSize) {
                        mid = Math.floor((minSize + maxSize) / 2);
                        applySize(mid);

                        if (inner.scrollWidth <= (w - pad) && inner.scrollHeight <= (h - pad)) {
                            minSize = mid + 1;
                        } else {
                            maxSize = mid - 1;
                        }
                    }
                    applySize(Math.max(4, maxSize));
                }

                // Initial render & size
                updateTime();
                resizeToFit();

                // React to changes
                window.addEventListener("resize", resizeToFit);
                if (window.ResizeObserver) {
                    new ResizeObserver(resizeToFit).observe(container);
                }

                // Tick every second to catch minute rollover; display shows hh:mm only
                setInterval(updateTime, 1000);
            })();
            </script>
            ';
            break;
    }

    return $output;
}
?>
