<?php

namespace DevOwl\RealCookieBanner\view\navmenu;

use DevOwl\RealCookieBanner\Vendor\DevOwl\Multilingual\NavMenuList;
use DevOwl\RealCookieBanner\base\UtilsProvider;
use DevOwl\RealCookieBanner\comp\language\Hooks;
use DevOwl\RealCookieBanner\Core;
use DevOwl\RealCookieBanner\view\Checklist;
use DevOwl\RealCookieBanner\view\checklist\Shortcode;
use Walker_Nav_Menu_Checklist;
use WP_Error;
use WP_Post;
// @codeCoverageIgnoreStart
\defined('ABSPATH') or die('No script kiddies please!');
// Avoid direct file request
// @codeCoverageIgnoreEnd
/**
 * Custom navigation menu links for the legal links.
 * @internal
 */
class NavMenuLinks
{
    use UtilsProvider;
    const METABOX_ID = 'rcb-nav-menu';
    const META_SUCCESS_MESSAGE_FIELD_ID = 'rcb-menu-item-success-message';
    const META_SUCCESS_MESSAGE_META_NAME = 'rcb-success-message';
    const NAVIGATION_ITEM_ID = 'rcb-nav-item';
    /**
     * C'tor.
     */
    private function __construct()
    {
        // Silence is golden.
    }
    /**
     * Get a list of available navigation menus so we can add a automatic "addition" process to our "Legal links" section.
     *
     * @param array $arr
     */
    public function revisionCurrent($arr)
    {
        $arr['nav_menus'] = (new NavMenuList(Core::getInstance()->getCompLanguage()))->get([$this, 'isMenuItem']);
        return $arr;
    }
    /**
     * Add existing links to our current menu.
     *
     * @param string $nav_menu_id
     * @return true|WP_Error
     */
    public function addLinksToMenu($nav_menu_id)
    {
        $compLanguage = Core::getInstance()->getCompLanguage();
        $nav_menu = (new NavMenuList($compLanguage))->getById($nav_menu_id, [$this, 'isMenuItem']);
        if ($nav_menu !== null) {
            $useLanguage = \count($nav_menu['languages']) > 0 ? $nav_menu['languages'][0]['code'] : null;
            $linkElements = $this->getLinkElements(\false, $useLanguage);
            $result = \true;
            $fnInsert = function () use($linkElements, $nav_menu, &$result) {
                foreach ($linkElements as $url => $element) {
                    $added = \wp_update_nav_menu_item($nav_menu['term_id'], 0, ['menu-item-title' => $element['linkText'], 'menu-item-url' => $url, 'menu-item-status' => 'publish']);
                    if (\is_wp_error($added)) {
                        $result = $added;
                        break;
                    } elseif (isset($element['meta'])) {
                        foreach ($element['meta'] as $key => $val) {
                            \update_post_meta($added, $key, $val);
                        }
                    }
                }
            };
            if ($compLanguage !== null && $compLanguage->isActive()) {
                $compLanguage->switchToLanguage($useLanguage, $fnInsert);
            } else {
                $fnInsert();
            }
            Checklist::getInstance()->toggle(Shortcode::IDENTIFIER, \true);
            return $result;
        } else {
            return new WP_Error('rcb_nav_menu_non_existing', \__('The navigation menu could not be found.', 'real-cookie-banner'));
        }
    }
    /**
     * Get the available link elements.
     *
     * @param boolean $onlyLinks
     * @param string $language
     */
    public function getLinkElements($onlyLinks = \false, $language = null)
    {
        if ($onlyLinks) {
            return ['#consent-change', '#consent-history', '#consent-revoke'];
        }
        $td = Hooks::getInstance()->createTemporaryTextDomain();
        $result = [];
        $fnCalculateResult = function ($temporaryTextDomain) use(&$result) {
            $targetLanguageTexts = $temporaryTextDomain->translate(function () {
                return [\_x('Change privacy settings', 'legal-text', 'real-cookie-banner'), \_x('Privacy settings history', 'legal-text', 'real-cookie-banner'), \_x('Revoke consents', 'legal-text', 'real-cookie-banner'), \_x('You have successfully revoked consent for services with its cookies and personal data processing. The page will be reloaded now!', 'legal-text', 'real-cookie-banner')];
            });
            $result = ['#consent-change' => ['label' => \_x('Change privacy settings', 'legal-text', 'real-cookie-banner'), 'linkText' => $targetLanguageTexts[0]], '#consent-history' => ['label' => \_x('Privacy settings history', 'legal-text', 'real-cookie-banner'), 'linkText' => $targetLanguageTexts[1]], '#consent-revoke' => ['label' => \_x('Revoke consents', 'legal-text', 'real-cookie-banner'), 'linkText' => $targetLanguageTexts[2], 'meta' => [self::META_SUCCESS_MESSAGE_META_NAME => $targetLanguageTexts[3]]]];
        };
        if ($language !== null) {
            $compLanguage = Core::getInstance()->getCompLanguage();
            $compLanguage->switchToLanguage($language, function ($locale, $currentLanguage, $temporaryTextDomain) use($fnCalculateResult, $td) {
                $fnCalculateResult($temporaryTextDomain ?? $td);
            });
        } else {
            $fnCalculateResult($td);
        }
        $td->teardown();
        return $result;
    }
    /**
     * Add custom meta fields to the nav menu field.
     *
     * @param int $item_id
     * @param object $item
     */
    public function wp_nav_menu_item_custom_fields($item_id, $item)
    {
        if ($this->isMenuItem($item) && $item->url === '#consent-revoke') {
            $compLanguage = Core::getInstance()->getCompLanguage();
            $useLanguage = $compLanguage !== null && $compLanguage->isActive() ? $compLanguage->getCurrentLanguageFallback() : null;
            $linkElements = $this->getLinkElements(\false, $useLanguage);
            $linkElement = $linkElements[$item->url];
            // Insert default values for newly created items
            if (!\metadata_exists('post', $item_id, self::META_SUCCESS_MESSAGE_META_NAME)) {
                foreach ($linkElement['meta'] as $key => $val) {
                    \update_post_meta($item_id, $key, $val);
                }
            }
            $successMessage = \get_post_meta($item_id, self::META_SUCCESS_MESSAGE_META_NAME, \true);
            echo \sprintf('<p class="description description-wide">
        <label for="%4$s-%1$d" >
            %2$s<br />
            <input type="text" class="widefat" id="%4$s-%1$d" 
                name="%4$s[%1$d]" value="%3$s"
            />
        </label>
    </p>', (int) $item_id, \esc_html__('Success message', 'real-cookie-banner'), \esc_attr(\is_scalar($successMessage) ? (string) $successMessage : ''), \esc_attr(self::META_SUCCESS_MESSAGE_FIELD_ID));
        }
    }
    /**
     * Save custom meta fields.
     *
     * @param int $menu_id
     * @param int $menu_item_db_id
     * @param array $args
     */
    public function wp_update_nav_menu_item($menu_id, $menu_item_db_id, $args)
    {
        // phpcs:disable WordPress.Security.NonceVerification.Missing -- navigation menu screen verifies nonce before save hooks fire.
        $successMessage = isset($_POST[self::META_SUCCESS_MESSAGE_FIELD_ID][$menu_item_db_id]) ? \sanitize_text_field(\wp_unslash($_POST[self::META_SUCCESS_MESSAGE_FIELD_ID][$menu_item_db_id])) : null;
        // phpcs:enable WordPress.Security.NonceVerification.Missing
        if ($successMessage !== null) {
            \update_post_meta($menu_item_db_id, self::META_SUCCESS_MESSAGE_META_NAME, $successMessage);
        }
        if (isset($args['menu-item-url']) && \in_array($args['menu-item-url'], $this->getLinkElements(\true), \true)) {
            Checklist::getInstance()->toggle(Shortcode::IDENTIFIER, \true);
        }
    }
    /**
     * Add the custom meta fields to the output navigation element.
     *
     * @param array $atts
     * @param WP_Post $item
     */
    public function nav_menu_link_attributes($atts, $item)
    {
        if ($this->isMenuItem($item)) {
            if ($item->url === '#consent-revoke') {
                $atts['data-success-message'] = \get_post_meta($item->ID, self::META_SUCCESS_MESSAGE_META_NAME, \true);
            }
            $atts['role'] = 'button';
        }
        return $atts;
    }
    /**
     * Accessibility: Broken same-page link -> we need to add a dummy element with the ID and the rest is done via JavaScript.
     *
     * @param string $item_output
     * @param WP_Post $item
     */
    public function walker_nav_menu_start_el($item_output, $item)
    {
        if ($this->isMenuItem($item)) {
            $item_output = \str_replace('</a>', \sprintf('<span id="%s" aria-hidden="true" %s></span></a>', \substr($item->url, 1), \join(' ', [
                // [Plugin Comp] Colibri and `spyScroll`
                'skip-scroll-spy="1"',
            ])), $item_output);
        }
        return $item_output;
    }
    /**
     * Register new metabox.
     */
    public function admin_head()
    {
        \add_meta_box(self::METABOX_ID, 'Real Cookie Banner', [$this, 'nav_menu_metabox'], 'nav-menus', 'side', 'default');
        // Create a script to automatically hide URL from the menu item
        echo '<script>
    jQuery(document).ready(function($) {
        const fnHide = function() {
            $(\'.edit-menu-item-url[value^="#consent"]\').parents(".field-url").hide();
        };
        fnHide();
        setInterval(fnHide, 1000);
    });
</script>';
    }
    /**
     * Output script to hide the "URL" input field in customizer.
     */
    public function customize_controls_head()
    {
        echo '<script>
    jQuery(document).ready(function($) {
        const fnHide = function() {
            $("input.edit-menu-item-url").filter(function() {
                return $(this).val().startsWith("#consent");
            }).parents("label").hide();
        };
        fnHide();
        setInterval(fnHide, 1000);
    });
</script>';
    }
    /**
     * Print the metabox.
     */
    public function nav_menu_metabox()
    {
        global $nav_menu_selected_id;
        $nav_items = [];
        foreach ($this->getLinkElements() as $value => $element) {
            $item = new \DevOwl\RealCookieBanner\view\navmenu\NavMenuLinkItem();
            $item->object_id = \esc_html($value);
            $item->ID = $item->object_id;
            $item->title = \esc_html($element['linkText']);
            $item->url = \esc_html($value);
            $nav_items[$element['label']] = $item;
        }
        $walker = new Walker_Nav_Menu_Checklist([]);
        echo \sprintf('<div id="rcb-links" class="rcblinksdiv">
    <div id="tabs-panel-rcb-links-all" class="tabs-panel tabs-panel-view-all tabs-panel-active">
        <ul id="rcb-linkschecklist" class="list:rcb-links categorychecklist form-no-clear">%s</ul>
    </div>
    <div class="button-controls">
        <span class="add-to-menu">
            <input type="submit" %s class="button-secondary submit-add-to-menu right" value="%s" name="add-rcb-links-menu-item" id="submit-rcb-links"/>
            <span class="spinner"></span>
       </span>
    </div>
</div>', \walk_nav_menu_tree(\array_map('wp_setup_nav_menu_item', $nav_items), 0, (object) ['walker' => $walker]), \disabled($nav_menu_selected_id, 0), \esc_attr(\__('Add to Menu', 'real-cookie-banner')));
    }
    /**
     * Correct "Custom link" to "Real Cookie Banner" type label.
     *
     * @param WP_Post $menu_item
     */
    public function wp_setup_nav_menu_item($menu_item)
    {
        if ($this->isMenuItem($menu_item)) {
            $menu_item->type_label = 'Real Cookie Banner';
        }
        return $menu_item;
    }
    /**
     * Register custom item types in customizer.
     *
     * @param array $item_types Menu item types.
     */
    public function register_customize_nav_menu_item_types($item_types)
    {
        $item_types[] = ['title' => 'Real Cookie Banner', 'type_label' => 'Real Cookie Banner', 'type' => self::METABOX_ID, 'object' => self::NAVIGATION_ITEM_ID];
        return $item_types;
    }
    /**
     * Register custom item type links in customizer.
     *
     * @param array $items
     * @param string $type
     * @param string $object
     * @param integer $page
     */
    public function register_customize_nav_menu_items($items = [], $type = '', $object = '', $page = 0)
    {
        if (self::NAVIGATION_ITEM_ID !== $object) {
            return $items;
        }
        if (0 < $page) {
            return $items;
        }
        foreach ($this->getLinkElements() as $id => $element) {
            $items[] = ['id' => \str_replace('#', '', $id), 'title' => $element['linkText'], 'type_label' => 'Real Cookie Banner', 'url' => $id];
        }
        return $items;
    }
    /**
     * Check if a given object of a menu item is a `NavMenuLinkItem`.
     *
     * @param WP_Post $menu_item
     */
    public function isMenuItem($menu_item)
    {
        return isset($menu_item->object, $menu_item->url) && $menu_item->object === 'custom' && \in_array($menu_item->url, $this->getLinkElements(\true), \true);
    }
    /**
     * New instance.
     *
     * @codeCoverageIgnore
     */
    public static function instance()
    {
        return new \DevOwl\RealCookieBanner\view\navmenu\NavMenuLinks();
    }
}
