<?php namespace Webien\Elementor\Widgets\TOC;

class Widget extends \Elementor\Widget_Base
{
    public function get_name()
    {
        return 'webien-toc';
    }

    public function get_title()
    {
        return __('Webien TOC', 'webien');
    }

    public function get_script_depends()
    {
        return [
            'webien-toc-waypoints',
            'webien-toc-waypoints-sticky',
            'webien-toc',
        ];
    }

    public function get_style_depends()
    {
        return [
            'webien-toc'
        ];
    }

    public function get_icon()
    {
        return 'eicon-sidebar';
    }

    public function get_categories()
    {
        return ['webien'];
    }

    protected function is_dynamic_content(): bool {
        return true;
    }

    protected function register_controls()
    {

        $this->start_controls_section(
            'section_label_content',
            [
                'label' => __('Innehåll', 'webien'),
                'tab' => \Elementor\Controls_Manager::TAB_CONTENT,
            ],

        );



        $this->add_control(
            'view',
            [
                'label' => __('Välj vy', 'webien'),
                'type' => \Elementor\Controls_Manager::SELECT,
                'options' => [
                    'toc' => __('Innehållsförteckning', 'webien'),
                    'menu' => __('Meny', 'webien'),
                ],
                'label_block' => true,
                'default' => 'toc',
                'separator' => 'after',
            ]
        );


        //-------------------------------------------------------------------------------//
        // TOC VIEW FUNCTIONALITY
        //-------------------------------------------------------------------------------//

        $this->add_control(
            'toc_content_container',
            [
                'label' => __('Innehållsyta', 'webien'),
                'description' => __('Ange unik selector (klass eller id) för den container som ska delas upp i kapitel.', 'webien'),
                'type' => \Elementor\Controls_Manager::TEXT,
                'default' => '.elementor-widget-theme-post-content',
                'placeholder' => '.elementor-widget-theme-post-content',
                'label_block' => true,
                'condition' => [
                    'view' => 'toc',
                ],
            ]
        );

        $this->add_control(
            'include_tags',
            [
                'label' => __('Rubriknivåer', 'webien'),
                'description' => __('Välj rubriknivåer som ska inkluderas.', 'webien'),
                'type' => \Elementor\Controls_Manager::SELECT2,
                'options' => [
                    'h1' => 'H1',
                    'h2' => 'H2',
                    'h3' => 'H3',
                    'h4' => 'H4',
                    'h5' => 'H5',
                    'h6' => 'H6',
                ],
                'multiple' => true,
                'label_block' => true,
                'default' => ['h2', 'h3'],
            ]
        );

        $this->add_control(
            'toc_content_container_exclude',
            [
                'label' => __('Exkludera innehållsyta', 'webien'),
                'description' => __('Ange unik selector (klass eller id) för den container som ska exkluderas innuti ovan innehållsyta. Ex. container som denna widget ligger i.', 'webien'),
                'placeholder' => '.sidebar',
                'type' => \Elementor\Controls_Manager::TEXT,
                'default' => '',
                'label_block' => true,
                'condition' => [
                    'view' => 'toc',
                ],
            ]
        );

        $this->add_control(
            'toc_hash_prefix',
            [
                'label' => __('Hash prefix', 'webien'),
                'description' => __('Lämna tom som standard. ', 'webien'),
                'type' => \Elementor\Controls_Manager::TEXT,
                'default' => '',
                'label_block' => true,
                'condition' => [
                    'view' => 'toc',
                ],
            ]
        );

        $this->add_control(
            'toc_trigger_offset',
            [
                'label' => __('Kapitel offset trigger', 'webien'),
                'description' => __('Ange hur långt ifrån toppen i scrollposition som aktivt kapitel ska ändras.', 'webien') . ' <a target="_blank" href="http://imakewebthings.com/waypoints/api/offset-option/">' . __('Mer info', 'webien') . '</a>',
                'placeholder' => '25%',
                'type' => \Elementor\Controls_Manager::TEXT,
                'default' => '25%',
                'label_block' => true,
                'separator' => 'before',
                'condition' => [
                    'view' => 'toc',
                ],

            ]
        );


        $this->add_control(
            'toc_dock_offset',
            [
                'label' => __('Dockning offset', 'webien'),
                'description' => __('Ange hur långt ifrån toppen kapitel ska dockas. Kompensera exempel för höjd på fixerad meny.', 'webien'),
                'placeholder' => '100px',
                'type' => \Elementor\Controls_Manager::TEXT,
                'default' => '100px',
                'label_block' => true,
                'condition' => [
                    'view' => 'toc',
                ],
            ]
        );


        $this->add_control(
            'sticky_container_toc',
            [
                'label' => __('Docka denna container', 'webien'),
                'type' => \Elementor\Controls_Manager::SWITCHER,
                'default' => 'yes',
                'separator' => 'before',
                'condition' => [
                    'view' => 'toc',
                ],
            ]
        );

        $this->add_control(
            'sticky_container_toc_offset',
            [
                'label' => __('Dockning offset', 'webien'),
                'description' => __('Ange hur långt ifrån toppen denna container ska dockas.', 'webien'),
                'placeholder' => '100px',
                'type' => \Elementor\Controls_Manager::TEXT,
                'default' => '100px',
                'condition' => [
                    'view' => 'toc',
                    'sticky_container_toc' => 'yes',
                ],
            ]
        );


        //-------------------------------------------------------------------------------//
        // MENU VIEW FUNCTIONALITY
        //-------------------------------------------------------------------------------//

        $this->add_control(
            'menu_type',
            [
                'label' => __('Välj källa', 'webien'),
                'type' => \Elementor\Controls_Manager::SELECT,
                'options' => [
                    'wp_menu' => __('Wordpress meny', 'webien'),
                    'page_structure' => __('Sidstruktur', 'webien'),
                ],
                'label_block' => true,
                'default' => 'page_structure',
                'condition' => [
                    'view' => 'menu',
                ],
            ]
        );

        $this->add_control(
            'wp_menu_id',
            [
                'label' => __('Välj meny', 'webien'),
                'type' => \Elementor\Controls_Manager::SELECT,
                'options' => $this->getWpMenus(),
                'label_block' => true,
                'condition' => [
                    'view' => 'menu',
                    'menu_type' => 'wp_menu',
                ],
            ]
        );


        $this->add_control(
            'page_structure_post_type',
            [
                'label' => __('Välj posttyp', 'webien'),
                'type' => \Elementor\Controls_Manager::SELECT,
                'options' => $this->getPostTypes(),
                'label_block' => true,
                'default' => 'page',
                'condition' => [
                    'view' => 'menu',
                    'menu_type' => 'page_structure',
                ],
            ]
        );


        $this->add_control(
            'menu_orderby',
            [
                'label' => __('Sortera efter', 'webien'),
                'type' => \Elementor\Controls_Manager::SELECT,
                'options' => [
                    'menu_order' => 'Menyordning',
                    'title' => 'Titel',
                    'date' => 'Datum',
                ],
                'label_block' => true,
                'default' => 'menu_order',
                'condition' => [
                    'view' => 'menu',
                    'menu_type' => 'page_structure',
                ],
            ]
        );


        $this->add_control(
            'menu_order',
            [
                'label' => __('Ordna', 'webien'),
                'type' => \Elementor\Controls_Manager::SELECT,
                'options' => [
                    'desc' => 'Fallande',
                    'asc' => 'Stigande',
                ],
                'label_block' => true,
                'default' => 'desc',
                'condition' => [
                    'view' => 'menu',
                    'menu_type' => 'page_structure',
                ],
            ]
        );


        $this->add_control(
            'menu_depth',
            [
                'label' => __('Menynivåer', 'webien'),
                'type' => \Elementor\Controls_Manager::NUMBER,
                'options' => $this->getWpMenus(),
                'default' => 2,
                'condition' => [
                    'view' => 'menu',
                ],
            ]
        );

        $this->add_control(
            'menu_expanded',
            [
                'label' => __('Utfälld från start', 'webien'),
                'type' => \Elementor\Controls_Manager::SWITCHER,
                'default' => 'yes',
                'separator' => 'before',
                'condition' => [
                    'view' => 'menu',
                ],
            ]
        );


        $this->add_control(
            'sticky_container_menu',
            [
                'label' => __('Docka meny', 'webien'),
                'type' => \Elementor\Controls_Manager::SWITCHER,
                'default' => 'yes',
                'condition' => [
                    'view' => 'menu',
                ],
            ]
        );

        $this->add_control(
            'sticky_container_menu_offset',
            [
                'label' => __('Dockning offset', 'webien'),
                'description' => __('Ange hur långt ifrån toppen menyn ska dockas.', 'webien'),
                'placeholder' => '100px',
                'type' => \Elementor\Controls_Manager::TEXT,
                'default' => '100px',
                'condition' => [
                    'view' => 'menu',
                ],
            ]
        );


        $this->add_control(
            'responsive_breakpoint',
            [
                'label' => __('Responsiv brytpunkt', 'webien'),
                'type' => \Elementor\Controls_Manager::SELECT,
                'options' => $this->getBreakpoints(),
                'default' => '768',
                'separator' => 'before',
                'condition' => [
                    'view' => 'toc',
                ],
            ]
        );


        $this->add_control(
            'use_external_menu',
            [
                'label' => __('Inkludera global menu', 'webien'),
                'type' => \Elementor\Controls_Manager::SWITCHER,
                'description' => __('Inkludera meny från extern källa.', 'webien'),
                'default' => 'yes',
                'separator' => 'before',
                'condition' => [
                    'view' => 'menu',
                ],
            ]
        );


        $this->add_control(
            'external_menu_coming_soon',
            [
                'type' => \Elementor\Controls_Manager::RAW_HTML,
                'raw' => '<h5 style="display:block;padding:15px;background-color:#000;border-radius: 5px;color: #fff;font-size: 14px;">Kommer snart..</h5>',
                'condition' => [
                    'view' => 'menu',
                    'use_external_menu' => 'yes',
                ],
            ]
        );


        $this->add_control(
            'external_menu_id',
            [
                'label' => __('Välj extern meny', 'webien'),
                'type' => \Elementor\Controls_Manager::SELECT,
                'options' => $this->getExternalMenus(),
                'label_block' => true,
                'default' => 'page',
                'condition' => [
                    'view' => 'menu',
                    'use_external_menu' => 'yes',
                ],
            ]
        );



        //-------------------------------------------------------------------------------//
        // DEBUG
        //-------------------------------------------------------------------------------//

        $this->add_control(
            'debug',
            [
                'label' => __('Debug läge', 'webien'),
                'type' => \Elementor\Controls_Manager::SWITCHER,
                'default' => 'no',
                'separator' => 'before',
            ]
        );



        $this->end_controls_section();


        //-------------------------------------------------------------------------------//
        // STYLES


        include(WEBIEN_PLUGIN_PATH . '/src/Elementor/Widgets/TOC/controls/toc.styles.php');
        include(WEBIEN_PLUGIN_PATH . '/src/Elementor/Widgets/TOC/controls/menu.styles.php');


    }

    protected function render()
    {
        $settings = $this->get_settings_for_display();
        $unique = substr(md5(uniqid(rand(), true)), 0, 10);

        // Add CSS for image path since it can be different depending on plugin path
        echo '<style>.chapter-heading .anchor { background-image: url(' . plugin_dir_url(__FILE__) . 'images/link.svg); }</style>';

        if ($settings['view'] === 'menu') {
            $menuItems = $this->getMenu($settings);
            $externalMenuItems = $this->getExternalMenu($settings);
            $jsSettings = [
                'menu' => $menuItems,
                'menuType' => $settings['menu_type'],
                'expanded' => $settings['menu_expanded'] === 'yes',
                'dockContainer' => $settings['sticky_container_menu'] === 'yes',
                'dockContainerOffset' => $settings['sticky_container_menu_offset'],
                'hasExternalMenu' => $settings['use_external_menu'] === 'yes',
                'externalMenu' => $externalMenuItems,
            ];

            // Add structure as JSON to be used in JS
            $script = 'window.webienTocMenu_' . $unique . '=' . json_encode($jsSettings) . ';';
            wp_add_inline_script('webien-toc', $script, 'before');
        }

        if ($settings['view'] === 'toc') {

            $jsSettings = [
                'contentArea' => $settings['toc_content_container'],
                'excludeArea' => $settings['toc_content_container_exclude'],
                'triggerOffset' => $settings['toc_trigger_offset'],
                'dockOffset' => $settings['toc_dock_offset'],
                'dockContainer' => $settings['sticky_container_toc'] === 'yes',
                'dockContainerOffset' => $settings['sticky_container_toc_offset'],
                'breakpoint' => $settings['responsive_breakpoint'] ?? 768,
                'tags' => $settings['include_tags'] ?? ['h2', 'h3'],
                'hashPrefix' => $settings['toc_hash_prefix'] ?? '',
            ];

            $script = 'window.webienTocSettings_' . $unique . '=' . json_encode($jsSettings) . ';';
            wp_add_inline_script('webien-toc', $script, 'before');

            $breakpoint = $settings['responsive_breakpoint'] ?? 768;
            $css = '<style>';
            $css .= '@media (min-width: ' . $breakpoint . 'px) {
                #webien-toc-widget-' . $unique . ' .narrow-view-btns,
                #webien-toc-widget-' . $unique . ' .narrow-view {
                    display: none;
                }
                #webien-toc-widget-' . $unique . ' .standard-view {
                    display: block;
                }
            }';
            $css .= '</style>';
            echo $css;
        }

        include __DIR__ . '/templates/view.' . $settings['view'] . '.php';


    }

    protected function getMenu($settings)
    {

        $menu = [];


        // ----------------- WP MENU

        if ($settings['menu_type'] === 'wp_menu' && isset($settings['wp_menu_id'])) {

            /**
             * This code will generate a simple array of menu items in hierarchical(parent-child) order.
             * This array will also contain child field as "true" if the item has child items array,
             * and custom active class if the link is active.
             */
            $menu_lists = array();
            $sub_parent = 0;

            $menu_items = wp_get_nav_menu_items((int)$settings['wp_menu_id']);

            if (empty($menu_items)) {
                return [];
            }

            foreach ($menu_items as $menu_item) {

                $id = $menu_item->ID;
                $title = $menu_item->title;
                $link = $menu_item->url;
                $menu_item_parent = $menu_item->menu_item_parent;

                // if menu item has no parent, means this is the top-menu.
                if (!$menu_item_parent) {
                    $menu_lists[$id]['child'] = false;
                    $menu_lists[$id]['childs'] = [];
                    $menu_lists[$id]['id'] = $id;
                    $menu_lists[$id]['title'] = $title;
                    $menu_lists[$id]['link'] = $link;

                    // add active field if current link and open url is same.
                    if (get_permalink() === $link) {
                        $menu_lists[$id]['active'] = 'current-menu-item';
                    }
                } else {
                    // if parent menu is set, means this is 2nd level menu
                    if (isset($menu_lists[$menu_item_parent])) {
                        $menu_lists[$menu_item_parent]['child'] = true;
                        $menu_lists[$menu_item_parent]['childs'][$id]['child'] = false;
                        $menu_lists[$menu_item_parent]['childs'][$id]['id'] = $id;
                        $menu_lists[$menu_item_parent]['childs'][$id]['title'] = $title;
                        $menu_lists[$menu_item_parent]['childs'][$id]['link'] = $link;

                        // add active field to current menu item and its parent menu item if current link and open url is same.
                        if (get_permalink() === $link) {
                            $menu_lists[$menu_item_parent]['active'] = 'current-child-item';
                            $menu_lists[$menu_item_parent]['childs'][$id]['active'] = 'current-menu-item';
                        }

                        $sub_parent = $menu_item_parent;

                    } elseif (isset($menu_lists[$sub_parent][$menu_item_parent])) {
                        // if parent menu is set and their parent menu is also set, means this is 3rd level menu
                        $menu_lists[$sub_parent]['childs'][$menu_item_parent]['child'] = true;
                        $menu_lists[$sub_parent]['childs'][$menu_item_parent][$id]['id'] = $id;
                        $menu_lists[$sub_parent]['childs'][$menu_item_parent][$id]['title'] = $title;
                        $menu_lists[$sub_parent]['childs'][$menu_item_parent][$id]['link'] = $link;

                        // add active field to current menu item and its parent menu item if current link and open url is same.
                        if (get_permalink() === $link) {
                            $menu_lists[$sub_parent]['childs']['active'] = 'current-menu-item';
                            $menu_lists[$sub_parent]['childs'][$menu_item_parent]['active'] = 'current-menu-item';
                            $menu_lists[$sub_parent]['childs'][$menu_item_parent][$id]['active'] = 'current-menu-item';
                        }
                    }
                }
            }


            $menu = $menu_lists;

        }

        //var_dump(json_encode($menu));


        // ----------------- PAGE STRUCTURE

        if ($settings['menu_type'] === 'page_structure' && isset($settings['page_structure_post_type'])) {

            $args = array(
                'post_type' => $settings['page_structure_post_type'],
                'posts_per_page' => -1,
                'orderby' => $settings['menu_orderby'],
                'order' => $settings['menu_order'],
                'post_status' => 'publish',
                'fields' => 'ids',
                'post_parent' => 0,
            );

            $posts = get_posts($args);

            $return = [];

            foreach ($posts as $post) {
                $return[] = $this->formatPostForMenu($post, $settings['page_structure_post_type']);
            }

            $menu = $return;
        }


        return $menu;
    }


    private function formatPostForMenu($postId, $postType)
    {
        $childs = [];

        $children = get_children(['post_type' => $postType, 'fields' => 'ids', 'post_parent' => $postId]);
        if ($children) {
            foreach ($children as $child) {
                $childs[] = $this->formatPostForMenu($child, $postType);
            }
        }

        $arr = [
            'id' => $postId,
            'title' => get_the_title($postId),
            'link' => get_permalink($postId),
            'active' => get_permalink() === get_permalink($postId) ? 'current-menu-item' : '',
        ];

        if (!empty($childs)) {
            $arr['child'] = true;
            $arr['childs'] = $childs;
        }
        return $arr;
    }


    protected function getWpMenus()
    {
        $menus = wp_get_nav_menus();
        $menuList = [];
        foreach ($menus as $menu) {
            $menuList[$menu->term_id] = $menu->name;
        }
        return $menuList;
    }

    protected function getExternalMenus()
    {
        $menuList = get_transient('webien_toc_external_menus') ?? [];
        // Check for transient. If none, then execute code and save the transient.
        if (empty ($menuList)) {
            // Get the menu list from external source
            $menuList = ['menu1' => 'Menu 1', 'menu2' => 'Menu 2'];
            // Save the transient
            set_transient('webien_toc_external_menus', json_encode($menuList), 12 * HOUR_IN_SECONDS);

            return $menuList;
        } else {
            return json_decode($menuList);
        }
    }

    protected function getExternalMenu($settings)
    {
        return [];

        /*
        $menuList = (array)$this->getExternalMenus();
        $menuItems = [];

        //if (isset($settings['external_menu_id'])) {

        foreach ($menuList as $menu) {
            // if($menu->id == $settings['external_menu_id']) {
            if ($menu->id == 99) {
                $menuItems = $menu->items;
            }
        }

        //}
        return $menuItems;
        */
    }


    protected function getPostTypes()
    {
        $postTypes = get_post_types(['public' => true], 'objects');
        $postTypeList = [];
        foreach ($postTypes as $postType) {
            $postTypeList[$postType->name] = $postType->label;
        }
        return $postTypeList;
    }


    protected function getBreakpoints()
    {
        // Get Elementor breakpoints
        $breakpoints = \Elementor\Plugin::$instance->breakpoints->get_breakpoints();


        $arr = [
            '0' => __('Ingen', 'webien'),
        ];

        foreach ($breakpoints as $breakpoint) {
            $arr[$breakpoint->get_value()] = $breakpoint->get_label() . ' (' . $breakpoint->get_value() . 'px)';
        }

        return $arr;
    }



    protected function _content_template()
    {

    }



}
