<?php

namespace GriffinForms\Admin\App\Html;

use GriffinForms\Traits\Singleton;
use GriffinForms\Admin\App\Html\Traits\ViewLayoutJs;
use GriffinForms\Admin\App\Html\Traits\UiHelpersJs;

class LandingPage extends \GriffinForms\Admin\App\Html\Format
{
    use Singleton;
    use ViewLayoutJs;
    use UiHelpersJs;

    protected $js_events_views;
    protected $js_events_actions;
    protected $title_bar;
    protected $left_sidebar;
    protected $presentation_area;
    protected $right_sidebar;
    protected $status_bar;
    protected $modals;
    protected $assist_shell;
    /**
     * JS events which change view inside the app.
     */
    protected function setJsEventsViews()
    {
        $this->js_events_views = array(
            'formList' => 'form-list', // Table of forms.
            'formLayout' => 'form-layout', // When a single form is selected, its HTML is fetched.
            'formCreate' => 'form-create' // Form creation tools including template selection.
        );
    }

    /**
     * Secondary JS events which are dispatched on other app actions.
     */
    protected function setJsEventsActions()
    {
        $this->js_events_actions = array(
            'formSelected' => 'form-selected',
            'formHtmlReceived' => 'form-html-received'
        );
    }

    protected function setTitleBar()
    {
        $this->title_bar = new Containers\TitleBar();
    }

    protected function setLeftSideBar()
    {
        $this->left_sidebar = new Containers\LeftSideBar();
    }

    protected function setPresentationArea()
    {
        $this->presentation_area = new Containers\PresentationArea();
    }

    protected function setRightSideBar()
    {
        $this->right_sidebar = new Containers\RightSideBar();
    }

    protected function setStatusBar()
    {
        $this->status_bar = new Containers\StatusBar();
    }

    protected function setModals()
    {
        $this->modals = new Modals();
        $this->modals->setModals();
    }

    protected function setAssistShell()
    {
        $this->assist_shell = new Containers\AssistShell();
    }

       /**
     * Main app HTML sent to the views page.
     * @see Views/App $griffinforms_app->getHtml()
     */
    public function getHtml()
    {
        $this->enqueueInitialThemeFonts();
        $this->seedFormAreaBgColor();
        $this->modals->getHtml();
        if (!empty($_GET['form_id'])) {
            $quotes_file = dirname(dirname(__FILE__)) . '/loading-quotes.json';
            $quote_text  = '';
            $quote_author = '';
            if (is_readable($quotes_file)) {
                $quotes = json_decode(file_get_contents($quotes_file), true);
                if (!empty($quotes) && is_array($quotes)) {
                    $pick = $quotes[array_rand($quotes)];
                    $quote_text   = $pick['quote']  ?? '';
                    $quote_author = $pick['author'] ?? '';
                }
            }
            echo '<style>#griffinforms-app-loading-overlay{position:fixed;inset:0;z-index:100090;display:flex;align-items:center;justify-content:center;padding:32px;background:#fff;opacity:1;visibility:visible;}</style>';
            echo '<div id="griffinforms-app-loading-overlay" class="griffinforms-app-loading-overlay" aria-hidden="true">';
            echo '<div class="griffinforms-app-loading-card">';
            if ($quote_text !== '') {
                echo '<div class="griffinforms-app-loading-quote">';
                echo '<p class="griffinforms-app-loading-quote__text">' . esc_html($quote_text) . '</p>';
                echo '<p class="griffinforms-app-loading-quote__author">' . esc_html('— ' . $quote_author) . '</p>';
                echo '</div>';
            }
            echo '<div class="spinner-border text-secondary" role="status" aria-hidden="true"></div>';
            echo '<div class="griffinforms-app-loading-title">' . esc_html__('Loading builder', 'griffinforms-form-builder') . '</div>';
            echo '<div class="griffinforms-app-loading-text">' . esc_html__('Rendering the form builder and applying styles...', 'griffinforms-form-builder') . '</div>';
            echo '</div>';
            echo '</div>';
        }
        $wrapper_classes = 'gf-fullscreen';
        $wrapper_style = '';
        if (!empty($_GET['form_id'])) {
            $wrapper_style = ' style="visibility:hidden;opacity:0;pointer-events:none;"';
            $wrapper_classes .= ' is-loading';
        }
        echo '<div id="griffinforms-app-wrapper" class="' . esc_attr($wrapper_classes) . '"' . $wrapper_style . '>';
        $this->title_bar->getHtml();
        echo '<div id="griffinforms-form-area" class="d-flex align-self-stretch">';
        $this->left_sidebar->getHtml();
        $this->presentation_area->getHtml();
        $this->right_sidebar->getHtml();
        echo '</div>';
        $this->status_bar->getHtml();
        $this->assist_shell->getHtml();
        echo '</div>';
    }

    /**
     * Main app javascript added to page footer via hook
     * @see Views/App add_action
     */
    public function appJs()
    {
        ob_start();  // Start output buffering
    
        ?>
        jQuery(document).ready(function($) {
        <?php
    
        // Output JS functions
        $this->initializeeventsJs();
        $this->showContextItemsJs();
        $this->formHtmlReceivedListnerJs();
        $this->btnSpinnerJs();
    
        ?>
        
        function showContextItems(context) {
            $(".griffinforms-container").find("*[data-gf-context]").each(function(){
                $(this).hide();
                let itemContext = $(this).attr("data-gf-context");
                let result = itemContext.includes(context);
                if (result) {
                    $(this).show();
                }
            });
        }
    
        <?php
    
        // Output JS events
        $this->title_bar->getJs();
        $this->left_sidebar->getJs();
        $this->presentation_area->getJs();
        $this->right_sidebar->getJs();
        $this->status_bar->getJs();
        $this->assist_shell->getJs();
        $this->modals->getJs();
        if (!empty($_GET['form_id'])) {
            $gf_app_loading_overlay_hold_ms = 0;
            if (!empty($_GET['gf_overlay_hold_ms'])) {
                $gf_app_loading_overlay_hold_ms = absint($_GET['gf_overlay_hold_ms']);
            } elseif (!empty($_GET['gf_overlay_hold'])) {
                $gf_app_loading_overlay_hold_ms = 5000;
            }
            ?>
            const gfAppLoadingOverlay = document.getElementById("griffinforms-app-loading-overlay");
            const gfAppLoadingOverlayHoldMs = <?php echo absint($gf_app_loading_overlay_hold_ms); ?>;
            let gfAppLoadingOverlayFormHtmlReceived = false;
            let gfAppLoadingOverlayWindowLoaded = document.readyState === "complete";
            let gfAppLoadingOverlayHideScheduled = false;

            const hideGfAppLoadingOverlay = () => {
                if (!gfAppLoadingOverlay) {
                    return;
                }

                window.requestAnimationFrame(() => {
                    const gfAppWrapper = document.getElementById("griffinforms-app-wrapper");
                    if (gfAppWrapper) {
                        gfAppWrapper.style.visibility = "visible";
                        gfAppWrapper.style.opacity = "1";
                        gfAppWrapper.style.pointerEvents = "auto";
                    }
                    gfAppLoadingOverlay.classList.add("is-hiding");
                    window.setTimeout(() => {
                        if (gfAppLoadingOverlay && gfAppLoadingOverlay.parentNode) {
                            gfAppLoadingOverlay.parentNode.removeChild(gfAppLoadingOverlay);
                        }
                    }, 220);
                });
            };

            const scheduleGfAppLoadingOverlayHide = () => {
                if (gfAppLoadingOverlayHideScheduled) {
                    return;
                }

                if (!gfAppLoadingOverlayFormHtmlReceived || !gfAppLoadingOverlayWindowLoaded) {
                    return;
                }

                gfAppLoadingOverlayHideScheduled = true;
                window.setTimeout(() => {
                    window.requestAnimationFrame(() => {
                        window.requestAnimationFrame(hideGfAppLoadingOverlay);
                    });
                }, gfAppLoadingOverlayHoldMs);
            };

            document.addEventListener("form-html-received", () => {
                gfAppLoadingOverlayFormHtmlReceived = true;
                scheduleGfAppLoadingOverlayHide();
            }, { once: true });

            if (!gfAppLoadingOverlayWindowLoaded) {
                window.addEventListener("load", () => {
                    gfAppLoadingOverlayWindowLoaded = true;
                    scheduleGfAppLoadingOverlayHide();
                }, { once: true });
            }

            window.setTimeout(() => {
                gfAppLoadingOverlayFormHtmlReceived = true;
                gfAppLoadingOverlayWindowLoaded = true;
                scheduleGfAppLoadingOverlayHide();
            }, 10000 + gfAppLoadingOverlayHoldMs);
            <?php
        }
        $this->initializeViewJs();

        ?>
        });
        <?php
    
        $inline_js = ob_get_clean();  // Get the buffered output as a string
    
        // Use WordPress's wp_add_inline_script() to append the JS
        wp_add_inline_script('griffinforms-global-js', $inline_js);
    }

    private function initializeViewJs()
    {
        if (!empty($_GET['form_id'])) {
            echo 'document.dispatchEvent(formLayout);';
        } else {
            echo 'document.dispatchEvent(formList);';
        }
    }

    /**
     * Enqueues Google Fonts for the active form when the builder loads.
     */
    protected function enqueueInitialThemeFonts()
    {
        if (empty($_GET['form_id'])) {
            return;
        }

        $form_id = absint($_GET['form_id']);
        if ($form_id < 1) {
            return;
        }

        if (!isset($this->sql) || !is_object($this->sql)) {
            $this->setSql();
        }

        if (!is_object($this->sql)) {
            return;
        }

        if ($this->sql->itemExists('form', $form_id) === false) {
            return;
        }

        $theme_id = $this->sql->getItemValue($form_id, 'form_theme', 'form');
        if (empty($theme_id)) {
            return;
        }

        $form_theme = new \GriffinForms\Items\FormTheme();
        if (!$form_theme->loadItem(absint($theme_id))) {
            return;
        }

        $fonts = $form_theme->getExternalFontFamilies();
        if (empty($fonts) || !is_array($fonts)) {
            return;
        }

        foreach ($fonts as $font_name) {
            $font_name = trim((string) $font_name);
            if ($font_name === '') {
                continue;
            }

            $handle = 'griffinforms-theme-font-' . sanitize_title($font_name);
            $font_url = $this->buildGoogleFontsUrl($font_name);
            if (!$font_url) {
                continue;
            }

            wp_enqueue_style($handle, $font_url, array(), null);
        }
    }

    private function seedFormAreaBgColor(): void
    {
        if (empty($_GET['form_id'])) {
            return;
        }

        $form_id = absint($_GET['form_id']);
        if ($form_id < 1) {
            return;
        }

        if (!isset($this->sql) || !is_object($this->sql)) {
            $this->setSql();
        }

        if (!is_object($this->sql)) {
            return;
        }

        $theme_id = (int) $this->sql->getItemValue($form_id, 'form_theme', 'form');
        if ($theme_id < 1) {
            return;
        }

        $form_theme = new \GriffinForms\Items\FormTheme();
        if (!$form_theme->loadItem($theme_id)) {
            return;
        }

        $bg_color = $form_theme->getPageBackgroundColor();
        if ($bg_color === '') {
            return;
        }

        $resolved = $this->resolveTransparentBgColor($bg_color);
        $tinted = $this->tintColorWithWhite($resolved, 0.7);
        echo '<style id="griffinforms-form-area-bg-seed">#griffinforms-form-area { background-color: ' . esc_attr($tinted) . ' !important; }</style>';
        echo '<script>window._gfFormAreaBgColor = ' . wp_json_encode($tinted) . ';</script>';
    }

    private function resolveTransparentBgColor(string $color): string
    {
        $c = strtolower(trim($color));
        if ($c === '' || $c === 'transparent' || $c === 'rgba(0,0,0,0)' || $c === 'rgba(0, 0, 0, 0)') {
            return '#ffffff';
        }
        if (preg_match('/^rgba?\s*\(\s*\d+\s*,\s*\d+\s*,\s*\d+\s*,\s*0\s*\)$/', $c)) {
            return '#ffffff';
        }
        return $color;
    }

    private function tintColorWithWhite(string $hex, float $white_fraction): string
    {
        $hex = ltrim($hex, '#');
        if (strlen($hex) === 3) {
            $hex = $hex[0] . $hex[0] . $hex[1] . $hex[1] . $hex[2] . $hex[2];
        }
        if (strlen($hex) !== 6) {
            return '#' . $hex;
        }
        $r = hexdec(substr($hex, 0, 2));
        $g = hexdec(substr($hex, 2, 2));
        $b = hexdec(substr($hex, 4, 2));
        $r = (int) round($r + (255 - $r) * $white_fraction);
        $g = (int) round($g + (255 - $g) * $white_fraction);
        $b = (int) round($b + (255 - $b) * $white_fraction);
        return sprintf('#%02x%02x%02x', $r, $g, $b);
    }

    /**
     * Builds the Google Fonts URL for a given font family.
     *
     * @param string $font_name
     * @return string
     */
    protected function buildGoogleFontsUrl($font_name)
    {
        $font_name = trim((string) $font_name);
        if ($font_name === '') {
            return '';
        }

        $encoded_font = str_replace(' ', '+', urlencode($font_name));
        return "https://fonts.googleapis.com/css2?family={$encoded_font}:wght@400;500;600;700&display=swap";
    }
}
