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

class Widget extends \Elementor\Widget_Base
{

    public function get_name()
    {
        return 'webien_reactive_list';
    }

    public function get_title()
    {
        return __('Reaktiv lista', 'webien');
    }

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

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

    public function get_script_depends() {
        return ['webien-reactive-list'];
    }

    public function get_style_depends() {
        return [];
    }

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

    protected function _register_controls()
    {
        $this->start_controls_section(
            'section_content',
            [
                'label' => __('Allmänt', 'webien'),
            ]
        );
        $this->add_control(
            'view',
            [
                'label' => __('Välj vy', 'webien'),
                'type' => \Elementor\Controls_Manager::SELECT,
                'label_block' => true,
                'options' => [
                    'full_list' => __('Alla poster från en posttyp', 'webien'),
                    'term_list' => __('Alla poster från en term', 'webien'),
                    'dynamic' => __('Enskilda poster', 'webien'),
                ],
                'default' => 'full_list',
            ]
        );
        $this->add_control(
            'posttype',
            [
                'label' => __('Välj posttyp', 'webien'),
                'type' => \Elementor\Controls_Manager::SELECT,
                'options' => $this->getPosttypes(),
                'label_block' => true,
                'condition' => [
                    'view' => ['full_list'],
                ],
            ]
        );


        $this->add_control(
            'use_separation',
            [
                'label'     => __( 'Separera lista med taxonomi' , 'webien' ),
                'description' => __('', 'webien'),
                'type'      => \Elementor\Controls_Manager::SWITCHER,
                'default'   => 'yes',
                'condition' => [
                    'view' => ['full_list'],
                ],
            ]
        );


        $this->add_control(
            'taxonomy',
            [
                'label' => __('Taxonomi för separation/filter', 'webien'),
                'description' => __('Taxonomin bör vara kopplad till posttypen.', 'webien'),
                'type' => \Elementor\Controls_Manager::SELECT,
                'options' => $this->getTaxonomies(),
                'label_block' => true,
                'condition' => [
                    //'use_separation' => ['yes'],
                    'view' => ['full_list'],
                ],
            ]
        );


        $this->add_control(
            'term_source',
            [
                'label' => __('Term', 'webien'),
                'type' => \Elementor\Controls_Manager::SELECT2,
                'options' => $this->getTermsTreeForSettings(),
                'label_block' => true,
                'condition' => [
                    'view' => ['term_list'],
                ],
            ]
        );


        $this->add_control(
            'use_sub_terms',
            [
                'label'     => __( 'Separera lista med subtermer' , 'webien' ),
                'description' => __('', 'webien'),
                'type'      => \Elementor\Controls_Manager::SWITCHER,
                'default'   => 'yes',
                'condition' => [
                    'view' => ['term_list'],
                ],
            ]
        );


        $this->add_control(
            'post_ids',
            [
                'label' => __('Post ID:n att inkludera', 'webien'),
                'description' => __('Kommaseparera eller välj dynamiskt.', 'webien'),
                'type' => \Elementor\Controls_Manager::TEXT,
                'label_block' => true,
                'condition' => ['view' => 'dynamic'],
                'dynamic' => [
                    'active' => true,
                ],
            ]
        );


        $this->add_control(
            'behavior',
            [
                'label' => __('Beteende', 'webien'),
                'description' => __('Vad ska hända när man klickar på en listitem?', 'webien'),
                'type' => \Elementor\Controls_Manager::SELECT,
                'options' => [
                    'expand' => __('Fäll ut innehåll', 'webien'),
                    'link' => __('Öppna länk (om finns)', 'webien'),
                    'download' => __('Ladda ner något (om finns)', 'webien'),
                ],
                'label_block' => true,
                'default' => 'expand',
                'separator' => 'before',
            ]
        );


        $this->add_control(
            'link_url',
            [
                'label' => __('Länkmål', 'webien'),
                'description' => __('Använd dynamiska fält.', 'webien'),
                'type' => \Elementor\Controls_Manager::URL,
                'label_block' => true,
                'condition' => ['behavior' => ['link', 'download']],
                'dynamic' => [
                    'active' => true,
                ],
            ]
        );


        $this->add_control(
            'content_source',
            [
                'label' => __('Källa för innehåll', 'webien'),
                'type' => \Elementor\Controls_Manager::SELECT,
                'options' => [
                    'post_content' => __('Postens innehåll', 'webien'),
                    'custom_field' => __('Anpassat fält', 'webien'),
                ],
                'label_block' => true,
                'condition' => [
                    'behavior' => ['expand'],
                ],
                'default' => 'post_content',
            ]
        );

        $this->add_control(
            'content_field_name',
            [
                'label' => __('Välj fält för innehåll', 'webien'),
                'type' => \Elementor\Controls_Manager::TEXT,
                'label_block' => true,
                'condition' => [
                    'content_source' => ['custom_field'],
                    'behavior' => ['expand'],
                ],
                'dynamic' => [
                    'active' => true,
                ],
            ]
        );


        $this->add_control(
            'contain_content',
            [
                'label'     => __( 'Framhäv innehåll' , 'webien' ),
                'description' => __('Framhäver innehållet mer visuellt.', 'webien'),
                'type'      => \Elementor\Controls_Manager::SWITCHER,
                'default'   => 'no',
                'condition' => [
                    'behavior' => ['expand'],
                ],
            ]
        );


        $this->add_control(
            'show_filters',
            [
                'label'     => __( 'Visa filter' , 'webien' ),
                'description' => __('Visar taxanomier som filter.', 'webien'),
                'type'      => \Elementor\Controls_Manager::SWITCHER,
                'default'   => 'no',
                'separator' => 'before',
            ]
        );

        $this->add_control(
            'use_search',
            [
                'label'     => __( 'Visa sök' , 'webien' ),
                'type'      => \Elementor\Controls_Manager::SWITCHER,
                'default'   => 'yes',
            ]
        );


        $this->add_control(
            'scroll_focus',
            [
                'label'     => __( 'Scrolla in i fokus' , 'webien' ),
                'type'      => \Elementor\Controls_Manager::SWITCHER,
                'default'   => 'yes',
            ]
        );


        $this->add_control(
            'schema_markup',
            [
                'label' => __('Schema markup', 'webien'),
                'description' => __('Vilken typ av schema markup som ska användas för innehållet.', 'webien'),
                'type' => \Elementor\Controls_Manager::SELECT,
                'options' => [
                    'none' => __('Ingen', 'webien'),
                    'faq' => __('FAQ', 'webien'),
                ],
                'label_block' => true,
                'condition' => [
                    'behavior' => ['expand'],
                ],
                'default' => 'none',
                'separator' => 'before',
            ]
        );



        $this->end_controls_section();

        // Start styling section
        $this->start_controls_section(
            'section_style',
            [
                'label' => __( 'Stil', 'webien' ),
                'tab' => \Elementor\Controls_Manager::TAB_STYLE,
            ]
        );

        $this->add_control(
            'list_icon_url',
            [
                'label' => esc_html__( 'Ikon', 'webien' ),
                'type' => \Elementor\Controls_Manager::ICONS,
                'default' => [
                    'value' => 'fas fa-arrow-right',
                    'library' => 'fa-solid',
                ],
                'condition' => [
                    'behavior' => ['link'],
                ],
            ]
        );

        $this->add_control(
            'list_icon_expand',
            [
                'label' => esc_html__( 'Ikon för expandering', 'webien' ),
                'type' => \Elementor\Controls_Manager::ICONS,
                'default' => [
                    'value' => 'fas fa-plus',
                    'library' => 'fa-solid',
                ],
                'condition' => [
                    'behavior' => ['expand'],
                ],
            ]
        );

        $this->add_control(
            'list_icon_unexpand',
            [
                'label' => esc_html__( 'Ikon för minimering', 'webien' ),
                'type' => \Elementor\Controls_Manager::ICONS,
                'default' => [
                    'value' => 'fas fa-minus',
                    'library' => 'fa-solid',
                ],
                'condition' => [
                    'behavior' => ['expand'],
                ],
            ]
        );

        $this->add_control(
            'list_icon_download',
            [
                'label' => esc_html__( 'Ikon', 'webien' ),
                'type' => \Elementor\Controls_Manager::ICONS,
                'default' => [
                    'value' => 'fas fa-download',
                    'library' => 'fa-solid',
                ],
                'condition' => [
                    'behavior' => ['download'],
                ],
            ]
        );

        $this->add_control(
            'icon_size',
            [
                'label' => __( 'Storlek på ikon', 'webien' ),
                'type' => \Elementor\Controls_Manager::SLIDER,
                'size_units' => [ 'px', '%', 'em', 'rem', 'custom' ],
                'range' => [
                    'px' => [
                        'min' => 5,
                        'max' => 100,
                        'step' => 1,
                    ],
                    '%' => [
                        'min' => 0,
                        'max' => 100,
                    ],
                ],
                'default' => [
                    'unit' => 'px',
                    'size' => 24,
                ],
                'selectors' => [
                    '{{WRAPPER}} .action-icon svg' => 'width: {{SIZE}}{{UNIT}};',
                ],
            ]
        );


        $this->end_controls_section();


    }



    protected function render()
    {
        $settings = $this->get_settings_for_display();

        $unique = substr(md5(uniqid(rand(), true)), 0, 10);


        $appSettings = $this->getAppSettings($settings);

        $posts = $this->getPosts($settings);

        $terms = $this->getTerms($settings);
        $isGroupedView = $this->shouldGroupPosts($settings);

        $schema = $this->getSchema($settings, $posts);

        $sidebar = false;


        $url = $_SERVER['SERVER_NAME'] . $_SERVER['REQUEST_URI'];
        if (strpos($url,'&action=elementor') !== false){
            $this->content_template();
        } else {
            include(__DIR__ . '/view.php');
        }
    }



    protected function getAppSettings($settings)
    {
        $appSettings = [
            'behavior' => $settings['behavior'],
            'search' => $settings['use_search'] === 'yes',
            'filters' => $settings['show_filters'] === 'yes',
            'scroll' => $settings['scroll_focus'] === 'yes',
            'hidden_group_heading' => null,
        ];

        if ($settings['view'] === 'term_list' && $settings['use_sub_terms'] === 'yes') {
            $activeTerm = $this->getActiveTermFromSettings($settings);
            $appSettings['hidden_group_heading'] = $activeTerm ? $activeTerm->name : null;
        }

        return $appSettings;
    }


    protected function getPosts($settings)
    {
        $args = [
            'post_status' => 'publish',
            'numberposts' => -1,
            'order' => 'DESC',
            'orderby' => 'date',
            'fields' => 'ids',
        ];

        $activeTerm = null;

        if($settings['view'] === 'full_list'){
            $args['post_type'] = $settings['posttype'];
        }

        if($settings['view'] === 'dynamic'){
            $args['post_type'] = 'any';
            $args['post__in'] = explode(',', $settings['post_ids']);
        }

        if($settings['view'] === 'term_list' && isset($settings['term_source'])){
            $args['post_type'] = 'any';
            $activeTerm = $this->getActiveTermFromSettings($settings);

            if (!$activeTerm) {
                return [];
            }

            $args['tax_query'] = [
                [
                    'taxonomy' => $activeTerm->taxonomy,
                    'field' => 'term_id',
                    'terms' => [$activeTerm->term_id],
                ],
            ];
        }

        $posts = get_posts($args);

        $arr = [];

        $single = count($posts) === 1;
        $shouldGroupPosts = $this->shouldGroupPosts($settings);
        $termsTaxonomy = '';

        if ($settings['view'] === 'full_list' && !empty($settings['taxonomy'])) {
            $termsTaxonomy = $settings['taxonomy'];
        }

        if ($settings['view'] === 'term_list' && $activeTerm) {
            $termsTaxonomy = $activeTerm->taxonomy;
        }

        foreach ($posts as $id) {

            $title = get_the_title($id);
            $subTitle = false;

            $descr = false;

            // Get content depending if its from custom field or post content
            if($settings['behavior'] === 'expand'){
                if($settings['content_source'] === 'custom_field'){
                    $field = $settings['content_field_name'];
                    if(empty($field)){
                        // It's probably dynamic (ACF) lets extract field name
                        if(isset($settings['__dynamic__']['custom_field_name'])){

                            $name = '/name="(.*?)"/m';
                            $setting = '/settings="(.*?)"/m';

                            // Get some matches from regex
                            preg_match_all($name, $settings['__dynamic__']['custom_field_name'], $name_matches, PREG_SET_ORDER, 0);
                            preg_match_all($setting, $settings['__dynamic__']['custom_field_name'], $setting_matches, PREG_SET_ORDER, 0);


                            // From ACF URL
                            if($name_matches[0][1] === 'acf-text') {
                                if(!empty($setting_matches)) {
                                    $obj = json_decode(urldecode($setting_matches[0][1]));
                                    if (isset($obj->key)) {
                                        $acf = explode(':', $obj->key);
                                        if(isset($acf[1])){
                                            $field = $acf[1];
                                        }
                                    }
                                }
                            }

                            // From Custom field
                            if($name_matches[0][1] === 'post-custom-field') {
                                if(!empty($setting_matches)){
                                    $obj = json_decode(urldecode($setting_matches[0][1]));
                                    if(isset($obj->custom_key)){
                                        $field = $obj->custom_key;
                                    }
                                }
                            }

                        }

                    }
                    $descr = get_field($field, $id);
                } else {
                    // Get post content
                    $descr = $this->cleanContent(get_post_field('post_content', $id));
                }
            }

            $descr = trim($descr);


            $link = false;
            if(in_array($settings['behavior'], ['link', 'download'])) {
                $link = $settings['link_url'];


                if(empty($link['url']) && isset($settings['__dynamic__']['link_url'])){
                    $name = '/name="(.*?)"/m';
                    $setting = '/settings="(.*?)"/m';

                    // Get some matches from regex
                    preg_match_all($name, $settings['__dynamic__']['link_url'], $name_matches, PREG_SET_ORDER, 0);
                    preg_match_all($setting, $settings['__dynamic__']['link_url'], $setting_matches, PREG_SET_ORDER, 0);

                    if($name_matches[0][1] === 'acf-url') {


                        if(!empty($setting_matches)) {
                            $obj = json_decode(urldecode($setting_matches[0][1]));
                            if (isset($obj->key)) {
                                $acf = explode(':', $obj->key);
                                if(isset($acf[1])){

                                    $val = get_field($acf[1], $id);
                                    // Sometimes this is just the ID number
                                    if(is_numeric($val)){
                                        $link['url'] = get_permalink($val);
                                    } else {
                                        $link['url'] = $val;
                                    }
                                }

                            }
                        }
                    }

                    // From Custom field
                    if($name_matches[0][1] === 'post-custom-field') {
                        if(!empty($setting_matches)){
                            $obj = json_decode(urldecode($setting_matches[0][1]));
                            if(isset($obj->custom_key)){
                                $key = $obj->custom_key;
                                $link['url'] = get_post_meta($id, $key, true);
                            }
                        }
                    }

                }

                // If download, always use _blank
                if($settings['behavior'] === 'download') {
                    $link['is_external'] = 'on';
                }

            }

            $typeTerms = [];
            if ($termsTaxonomy) {
                $typeTerms = get_the_terms($id, $termsTaxonomy) ?: [];
            }

            $groupTerm = isset($typeTerms[0]) ? $typeTerms[0] : false;

            if ($settings['view'] === 'term_list' && $settings['use_sub_terms'] === 'yes') {
                $groupTerm = $this->getSubTermGroupForPost($typeTerms, $activeTerm);
            }

            // Dont parse if no taxonomy
            if(!$groupTerm && $shouldGroupPosts){
                continue;
            }

            // Termname used for separation
            $termName = $groupTerm ? $groupTerm->name : 'xxx';
            $termLevel = $groupTerm ? $this->getTermLevel($groupTerm) : 0;

            // If using standard terms add them here
            $arrTerms = [];

            foreach ($typeTerms as $term) {
                // Set up necessary term info

                $obj = (object)[
                    'term_id' => $term->term_id,
                    'taxonomy' => $term->taxonomy,
                    'name' => $term->name,
                    'parent' => $term->parent,
                ];

                array_push($arrTerms, $obj);
            }

            // If we shall separate by terms continue with more advanced array, if not just return the list
            if(!$shouldGroupPosts){
                $arr['simpleList'][] = [
                    'id' => $id,
                    'termName' => $termName,
                    'groupLevel' => $termLevel,
                    'terms' => $arrTerms,
                    'title' => $title,
                    'subTitle' => $subTitle,
                    'descr' => $descr,
                    'open' => $single,
                    'icons' => $this->getIcons($settings),
                    'link' => $link,
                ];

            } else {

                $arr[$termName][] = [
                    'id' => $id,
                    'termName' => $termName,
                    'groupLevel' => $termLevel,
                    'title' => $title,
                    'subTitle' => $subTitle,
                    'descr' => $descr,
                    'terms' => $arrTerms,
                    'open' => false,
                    'icons' => $this->getIcons($settings),
                    'link' => $link,
                ];
            }

        }



        // Order array again after first character
        if ($settings['view'] === 'full_list' && $settings['use_separation'] === 'yes' && !empty($settings['taxonomy'])) {
            $arr = $this->sortGroupedPostsByTermHierarchy($arr, $settings['taxonomy']);
        } elseif ($settings['view'] === 'term_list' && $settings['use_sub_terms'] === 'yes' && $activeTerm) {
            $arr = $this->sortGroupedPostsByTermHierarchy($arr, $activeTerm->taxonomy, $activeTerm->term_id);
        } else {
            ksort($arr);
        }

        return $arr;

    }


    protected function getTermLevel($term)
    {
        $level = 0;
        $parentId = (int) $term->parent;

        while ($parentId > 0) {
            $parentTerm = get_term($parentId, $term->taxonomy);

            if (is_wp_error($parentTerm) || !$parentTerm) {
                break;
            }

            $level++;
            $parentId = (int) $parentTerm->parent;
        }

        return $level;
    }


    protected function sortGroupedPostsByTermHierarchy($groupedPosts, $taxonomy, $rootParentId = 0)
    {
        $terms = get_terms([
            'taxonomy' => [$taxonomy],
            'hide_empty' => true,
        ]);

        if (is_wp_error($terms) || empty($terms)) {
            ksort($groupedPosts);
            return $groupedPosts;
        }

        $termsById = [];
        $childrenByParent = [];

        foreach ($terms as $term) {
            $termsById[$term->term_id] = $term;
            $childrenByParent[$term->parent][] = $term->term_id;
        }

        foreach ($childrenByParent as &$childIds) {
            usort($childIds, function ($leftId, $rightId) use ($termsById) {
                return $this->compareTermNames($termsById[$leftId]->name, $termsById[$rightId]->name);
            });
        }
        unset($childIds);

        $orderedGroups = [];
        $seenKeys = [];

        if ($rootParentId > 0 && isset($termsById[$rootParentId])) {
            $rootTermName = $termsById[$rootParentId]->name;

            if (isset($groupedPosts[$rootTermName])) {
                $orderedGroups[$rootTermName] = $groupedPosts[$rootTermName];
                $seenKeys[$rootTermName] = true;
            }
        }

        $appendChildren = function ($parentId) use (&$appendChildren, $childrenByParent, $termsById, $groupedPosts, &$orderedGroups, &$seenKeys) {
            foreach ($childrenByParent[$parentId] ?? [] as $termId) {
                $termName = $termsById[$termId]->name;

                if (isset($groupedPosts[$termName]) && !isset($seenKeys[$termName])) {
                    $orderedGroups[$termName] = $groupedPosts[$termName];
                    $seenKeys[$termName] = true;
                }

                $appendChildren($termId);
            }
        };

        $appendChildren($rootParentId);

        foreach ($groupedPosts as $termName => $posts) {
            if (!isset($seenKeys[$termName])) {
                $orderedGroups[$termName] = $posts;
            }
        }

        return $orderedGroups;
    }


    protected function compareTermNames($left, $right)
    {
        return strcmp($this->normalizeTermNameForSort($left), $this->normalizeTermNameForSort($right));
    }


    protected function normalizeTermNameForSort($name)
    {
        $name = mb_strtolower($name);

        return strtr($name, [
            'å' => 'zza',
            'ä' => 'zzb',
            'ö' => 'zzc',
        ]);
    }



    function cleanContent($content) {
        // Remove gutenberg comments
        $content = preg_replace('/<!-- wp:.*?-->/', '', $content);
        $content = preg_replace('/<!-- \/wp:.*?-->/', '', $content);

        // remove \n
        $content = str_replace("\n", '', $content);

        // Remove empty paragraphs
        $content = preg_replace('/<p>(\s|&nbsp;)*<\/p>/', '', $content);

        return $content;
    }


    protected function getIcons($settings) {

        // Make sure the method "try_get_icon_html" exists
        if(!method_exists('\Elementor\Icons_Manager', 'try_get_icon_html')){
            return [
                'normal' => '',
                'active' => '',
            ];
        }


        if($settings['behavior'] === 'expand'){
            return [
                'normal' => \Elementor\Icons_Manager::try_get_icon_html( $settings['list_icon_expand'], [ 'aria-hidden' => 'true' ] ),
                'active' => \Elementor\Icons_Manager::try_get_icon_html( $settings['list_icon_unexpand'], [ 'aria-hidden' => 'true' ] ),
            ];
        } else if($settings['behavior'] === 'download'){
            return [
                'normal' => \Elementor\Icons_Manager::try_get_icon_html( $settings['list_icon_download'], [ 'aria-hidden' => 'true' ] ),
                'active' => \Elementor\Icons_Manager::try_get_icon_html( $settings['list_icon_download'], [ 'aria-hidden' => 'true' ] ),
            ];
        } else if($settings['behavior'] === 'link'){
            return [
                'normal' => \Elementor\Icons_Manager::try_get_icon_html( $settings['list_icon_url'], [ 'aria-hidden' => 'true' ] ),
                'active' => \Elementor\Icons_Manager::try_get_icon_html( $settings['list_icon_url'], [ 'aria-hidden' => 'true' ] ),
            ];
        }
    }




    protected function getTaxonomies() {
        $args = array(
            'public'   => true,
            '_builtin' => true

        );
        $output = 'objects'; // or objects
        $operator = 'or'; // 'and' or 'or'
        $taxonomies = get_taxonomies( $args, $output, $operator );

        $arr = [];
        foreach ($taxonomies as $taxonomy) {
            $arr[$taxonomy->name] = $taxonomy->labels->name . ' (' . $taxonomy->name . ')';
        }

        return $arr;

    }


    protected function getPosttypes() {
        $args = array(
            'public'   => true,
            '_builtin' => true

        );
        $output = 'objects'; // or objects
        $operator = 'or'; // 'and' or 'or'
        $post_types = get_post_types( $args, $output, $operator );

        $arr = [];
        foreach ($post_types as $pt) {
            $arr[$pt->name] = $pt->labels->singular_name . ' (' . $pt->name . ')';
        }

        return $arr;

    }



    protected function getTerms($settings)
    {
        if (empty($settings['taxonomy'])) {
            return [];
        }


        $terms = get_terms( [
            'taxonomy' => [$settings['taxonomy']],
            'hide_empty' => true,
        ] );

        $arr = [];

        foreach ($terms as $term) {

            $descr = get_field('descr', $term) ?? __('Fixa beskrivning..', 'webien');

            $arr[] = [
                'id' => $term->term_id,
                'name' => $term->name,
                'descr' => $descr,
                'slug' => $term->slug,
                'parent' => $term->parent,
                'tax' => $term->taxonomy,
            ];
        }

        return $arr;

    }


    function getSchema($settings, $posts) {


        // Get flat post array depending on setting
        if ($this->shouldGroupPosts($settings)) {
            $posts = array_values(array_filter($posts, 'is_array'));
            $posts = !empty($posts) ? array_merge(...$posts) : [];
        } else {
            $posts = $posts['simpleList'] ?? [];
        }

        $schema = false;

        if($settings['schema_markup'] === 'faq') {

            if(is_array($posts) && count($posts) > 0) {
                $schema = [
                    '@context' => 'https://schema.org',
                    '@type' => 'FAQPage',
                    'mainEntity' => [],
                ];

                foreach ($posts as $item) {

                    // Add <p> tage if descr is not allready wrapped in a tag, this is to make sure the schema is valid even if the content is just plain text
                    if(strpos($item['descr'], '<p>') === false){
                        $item['descr'] = '<p>' . $item['descr'] . '</p>';
                    }

                    $schema['mainEntity'][] = [
                        '@type' => 'Question',
                        'name' => $item['title'],
                        'acceptedAnswer' => [
                            '@type' => 'Answer',
                            'text' => $item['descr'],
                        ],
                    ];
                }
            }
        }


        if($schema){
            // Add script tag around and return full html for output
            return '<script type="application/ld+json">' . json_encode($schema) . '</script>';
        }

    }



    function getTermsTreeForSettings(){
        $taxonomies = get_taxonomies( ['public' => true], 'objects' );
        // for each taxonomy, add all terms
        $arr = [];
        foreach ($taxonomies as $taxonomy) {
            $terms = get_terms( [
                'taxonomy' => $taxonomy->name,
                'hide_empty' => false,
            ] );

            $termArr = [];
            foreach ($terms as $term) {
                $termArr[$term->term_id] = $term->name;
            }

            $arr[$taxonomy->name] = [
                'name' => $taxonomy->labels->name,
                'terms' => $termArr,
            ];
        }

        // Make a flat array with taxonomy name and term name for easier selection in settings
        $arrFlat = [
            'current' => __('Nuvarande term', 'webien'),
        ];
        foreach ($arr as $taxonomy => $data) {
            foreach ($data['terms'] as $termId => $termName) {
                $arrFlat[$taxonomy . '|' . $termId] = $data['name'] . ' → ' . $termName;
            }
        }


        return $arrFlat;
    }



    protected function content_template()
    {

    }


    protected function shouldGroupPosts($settings)
    {
        if ($settings['view'] === 'full_list') {
            return $settings['use_separation'] === 'yes' && !empty($settings['taxonomy']);
        }

        if ($settings['view'] === 'term_list') {
            return $settings['use_sub_terms'] === 'yes' && $this->getActiveTermFromSettings($settings);
        }

        return false;
    }


    protected function getActiveTermFromSettings($settings)
    {
        if ($settings['view'] !== 'term_list' || empty($settings['term_source'])) {
            return null;
        }

        if ($settings['term_source'] === 'current') {
            if (is_category() || is_tag() || is_tax()) {
                $term = get_queried_object();

                return $term instanceof \WP_Term ? $term : null;
            }

            return null;
        }

        $termSource = explode('|', $settings['term_source']);

        if (count($termSource) !== 2) {
            return null;
        }

        $term = get_term((int) $termSource[1], $termSource[0]);

        if (is_wp_error($term) || !$term) {
            return null;
        }

        return $term;
    }


    protected function getSubTermGroupForPost($terms, $activeTerm)
    {
        if (!$activeTerm || empty($terms)) {
            return null;
        }

        foreach ($terms as $term) {
            $groupTerm = $this->resolveDirectChildTerm($term, $activeTerm);

            if ($groupTerm) {
                return $groupTerm;
            }
        }

        foreach ($terms as $term) {
            if ((int) $term->term_id === (int) $activeTerm->term_id) {
                return $activeTerm;
            }
        }

        return null;
    }


    protected function resolveDirectChildTerm($term, $activeTerm)
    {
        if (!$term || !$activeTerm || $term->taxonomy !== $activeTerm->taxonomy) {
            return null;
        }

        if ((int) $term->parent === (int) $activeTerm->term_id) {
            return $term;
        }

        $parentId = (int) $term->parent;

        while ($parentId > 0) {
            $parentTerm = get_term($parentId, $term->taxonomy);

            if (is_wp_error($parentTerm) || !$parentTerm) {
                return null;
            }

            if ((int) $parentTerm->parent === (int) $activeTerm->term_id) {
                return $parentTerm;
            }

            $parentId = (int) $parentTerm->parent;
        }

        return null;
    }



}
