<?php

namespace Components\Ui;

use Components\Base;

class SelectableCard extends Base
{
    private static bool $scriptsRendered = false;

    public static function selectedClasses(): string
    {
        return 'is-selected ring-brand shadow-xs';
    }

    public static function cardClasses(bool $selected = false): string
    {
        $classes = 'cursor-pointer select-none ring-2 ring-transparent transition-all duration-150 hover:ring-brand/40';
        if ($selected) {
            $classes .= ' ' . self::selectedClasses();
        }

        return $classes;
    }

    public static function renderScripts(): string
    {
        if (self::$scriptsRendered) {
            return '';
        }

        self::$scriptsRendered = true;

        ob_start();
        ?>
        <script type="text/javascript">
            (function () {
                if (window.__mhSelectableCard) {
                    return;
                }

                var selectedClasses = ['is-selected', 'ring-brand', 'shadow-xs'];
                var unselectedClasses = ['ring-transparent'];

                function runCallback(callback, card) {
                    if (typeof callback !== 'function') {
                        return;
                    }

                    try {
                        callback(card);
                    } catch (e) {}
                }

                function applySelectedState(card, isSelected) {
                    if (!card || !card.classList) {
                        return;
                    }

                    if (isSelected) {
                        selectedClasses.forEach(function (className) {
                            card.classList.add(className);
                        });
                        unselectedClasses.forEach(function (className) {
                            card.classList.remove(className);
                        });
                        card.setAttribute('aria-selected', 'true');
                        return;
                    }

                    selectedClasses.forEach(function (className) {
                        card.classList.remove(className);
                    });
                    unselectedClasses.forEach(function (className) {
                        card.classList.add(className);
                    });
                    card.setAttribute('aria-selected', 'false');
                }

                function getContainer(card, opts) {
                    if (!card) {
                        return null;
                    }

                    if (opts && opts.containerSelector && typeof card.closest === 'function') {
                        var container = card.closest(opts.containerSelector);
                        if (container) {
                            return container;
                        }
                    }

                    return card.parentElement || null;
                }

                function selectCard(card, opts) {
                    if (!card) {
                        return;
                    }

                    var options = opts || {};
                    var cardSelector = options.cardSelector || '[data-selectable-card="1"]';
                    var container = getContainer(card, options);

                    if (container && cardSelector) {
                        var selectedCards = container.querySelectorAll(cardSelector + '.is-selected');
                        selectedCards.forEach(function (node) {
                            if (node !== card) {
                                applySelectedState(node, false);
                            }
                        });
                    }

                    applySelectedState(card, true);
                    runCallback(options.onSelect, card);
                }

                function shouldSkipClick(ev, opts) {
                    var options = opts || {};
                    var skipSelector = options.skipSelector || '[data-skip-template-card-click]';
                    if (!skipSelector || !ev || !ev.target || typeof ev.target.closest !== 'function') {
                        return false;
                    }

                    return !!ev.target.closest(skipSelector);
                }

                function triggerPrimaryAction(card, opts) {
                    if (!card) {
                        return false;
                    }

                    var options = opts || {};
                    var selector = options.primaryActionSelector || '[data-card-primary-action="1"]';
                    if (selector) {
                        var actionEl = card.querySelector(selector);
                        if (actionEl && typeof actionEl.click === 'function') {
                            actionEl.click();
                            return true;
                        }
                    }

                    if (typeof options.onPrimaryAction === 'function') {
                        runCallback(options.onPrimaryAction, card);
                        return true;
                    }

                    return false;
                }

                function handleClick(ev, card, opts) {
                    if (!card || shouldSkipClick(ev, opts)) {
                        return;
                    }

                    var wasSelected = card.classList.contains('is-selected');
                    selectCard(card, opts);
                    if (wasSelected) {
                        triggerPrimaryAction(card, opts);
                    }
                }

                function handleDoubleClick(ev, card, opts) {
                    if (!card || shouldSkipClick(ev, opts)) {
                        return;
                    }

                    selectCard(card, opts);
                    triggerPrimaryAction(card, opts);
                }

                window.__mhSelectableCard = {
                    selectCard: selectCard,
                    triggerPrimaryAction: triggerPrimaryAction,
                    handleClick: handleClick,
                    handleDoubleClick: handleDoubleClick,
                };
            })();
        </script>
        <?php

        return ob_get_clean();
    }
}
