<?php

    // prevent direct file access
	if( !defined( 'ABSPATH' ) ) exit;

    // settings
    function pixe_get_main_settings($type, $default = array()){
        $settings = get_option('pixe_main', array());
        if( !empty($settings[$type]) ){
            return $settings[$type];
        }else{
            return $default;
        }
    }
    function pixe_get_tool_settings($type, $default = array()){
        $settings = get_option('pixe_tools', array());
        if( !empty($settings[$type]) ){
            return $settings[$type];
        }else{
            return $default;
        }
    }

    // get ai data for editor
    function pixe_get_builder_ai_data(){
        $ai = get_option('pixe_ai', array());

        return array(
            'providers' => pixe_list_wp_ai_providers(),
            'default-language' => empty($ai['default-language'])? '': $ai['default-language']
        );
    }
    function pixe_list_wp_ai_providers(){
        $providers = array();

        if( function_exists('wp_get_connectors') ){
            $connectors = wp_get_connectors();
            if( !empty($connectors) ) {
                foreach( $connectors as $key => $settings ){
                    if( WordPress\AiClient\AiClient::isConfigured($key) ){
                        $providers[] = $key;
                    }
                }
            }
        }

        return $providers;
    }

    // get unspalsh data
    function pixe_get_builder_stock_image_data(){
        $stock_image = get_option('pixe_stock_image', array());
        return !empty($stock_image['api-key']);
    }

    // get editor part name
    function pixe_get_part_name($type, $part, $id){
        if( $type == 'template' ){
            return 'tp';
        }else if( $type == 'template_part' ){
            switch($part){
                case 'header':
                    return 'hd' . esc_attr($id);
                    break;
                case 'footer':
                    return 'ft' . esc_attr($id);
                    break;
                case 'post_template':
                    return 'pt' . esc_attr($id);
                    break;
                case 'synced_block':
                    return 'sb' . esc_attr($id);
                    break;
                case 'taxonomy_template':
                    return 'tt' . esc_attr($id);
                    break;
                default:
                    return esc_attr($part . $id);
                    break;
            }
        }else{
            return 'main';
        }
    }

    // get current term
    function pixe_get_query_term(){
        global $pixe_terms;
        
        $term = false;
        if( !empty($pixe_terms) && !empty(current($pixe_terms)) ){
            $term = current($pixe_terms);
        }else if( is_tax() ){
            $term = get_queried_object();
        }

        return $term;
    }

    // get error messages
    function pixe_get_error_message($type, $echo = false){
        $ret = '';

        if( !$echo ){
            ob_start();
        }

        switch($type){  
            case 'error': esc_html_e('Error!', 'pixebuilder'); break;
            case 'nonce-head': esc_html_e('Session expired', 'pixebuilder'); break;
            case 'nonce-message': esc_html_e('Please refresh the page and try again.', 'pixebuilder'); break;
            case 'nonce': esc_html_e('Session expired. Please refresh the page and try again.', 'pixebuilder'); break;
            case 'refresh': esc_html_e('Please refresh the page and try again.', 'pixebuilder'); break;
            case 'permission-head': esc_html_e('Permission Denied', 'pixebuilder'); break;
            case 'permission-message': esc_html_e('You do not have permission to perform this action.', 'pixebuilder'); break;
            case 'permission-upload-message': esc_html_e('You do not have permission to upload files.', 'pixebuilder'); break;
            case 'invalid-format-head': esc_html_e('Invalid Data Format', 'pixebuilder'); break;
            case 'invalid-format-message': esc_html_e('Please refresh the page and try again.', 'pixebuilder'); break;
        }

        if( !$echo ){
            $ret = ob_get_clean();

            return $ret;
        }
    }

    // check if have posts without resetting the loop 
    function pixe_have_posts($query){
        if( !empty($query) && $query->current_post + 1 < $query->post_count ){
		    return true;
        }
        return false;
    }

    // print escape css
    function pixe_print_esc_css($css){
        if( !empty($css) ){
            echo wp_strip_all_tags($css); // phpcs:ignore WordPress.Security.EscapeOutput -- CSS is sanitized and intended for raw style output.
        }
    }

    // array walk sanitize function
    function pixe_sanitize_builder_data(&$item , $key){
        switch($key){
            case 'title':
            case 'text':
            case 'content':
            case 'svg':
                $item = wp_kses($item, pixe_get_allowed_content());
                break;

            default:
                $item = sanitize_textarea_field($item);
        }
    }  

    // deep sanitizing function
    function pixe_kses_post($fields){
        if( !current_user_can('unfiltered_html') ){ 
            if( !empty($fields) ){
                foreach( $fields as $key => $value ){
                    if( is_array($value) ){
                        $fields[$key] = pixe_kses_input($value);
                    }else{
                        $fields[$key] = wp_kses_post($value);
                    }
                }
            }
        }

        return $fields;
    }
    function pixe_deep_sanitize_text_field($value){
        if( is_array($value) ){
            return array_map('pixe_deep_sanitize_text_field', $value);
        }

        return sanitize_text_field($value);
    }
    function pixe_deep_sanitize_textarea_field($value){
        if( is_array($value) ){
            return array_map('pixe_deep_sanitize_textarea_field', $value);
        }

        return sanitize_textarea_field($value);
    }
    function pixe_deep_absint($value){
        if( is_array($value) ){
            return array_map('pixe_deep_absint', $value);
        }

        return absint($value);
    }
    function pixe_deep_kses($value){
        if( current_user_can('unfiltered_html') ){
            return $value;
        }

        if( is_array($value) ){
            return array_map('pixe_deep_kses', $value);
        }
        
        if( is_string($value) ){
            return wp_kses($value, pixe_get_allowed_content());
        }

        return $value;
    }
    function pixe_get_allowed_content(){
        return array(
            'h1' => array('class' => array(),'style' => array()),
            'h2' => array('class' => array(),'style' => array()),
            'h3' => array('class' => array(),'style' => array()),
            'h4' => array('class' => array(),'style' => array()),
            'h5' => array('class' => array(),'style' => array()),
            'h6' => array('class' => array(),'style' => array()),
            'p' => array('class' => array(),'style' => array()),
            'div' => array('class' => array(),'style' => array()),
            'span' => array('class' => array(),'style' => array()),
            'ul' => array('class' => array(),'style' => array()),
            'ol' => array('class' => array(),'style' => array()),
            'li' => array('class' => array(),'style' => array()),
            'pre' => array('class' => array(),'style' => array()),
            'code' => array('class' => array(),'style' => array()),
            'a' => array(
                'href'  => array(),
                'title' => array(),
                'class' => array(),
                'style' => array(),
            ),
            'img'    => array(
                'src'    => array(),
                'alt'    => array(),
                'width'  => array(),
                'height' => array(),
                'class'  => array(),
                'style'  => array(),
                'srcset' => array(),
                'sizes' => array(),
            ),
            'video' => array(
                'autoplay' => array(), 
                'muted' => array(), 
                'loop' => array(), 
                'playsinline' => array(), 
                'class' => array()
            ),
            'source' => array(
                'src' => array(), 
                'type' => array()
            ),
            'br' => array(),
            'b' => array(),
            'i' => array(
                'class' => array()
            ),
            'strong' => array(),
            'em'     => array(),
            'u'      => array(),
            'del'    => array(),

            // table
            'table'    => array(),
            'thead'    => array(),
            'tbody'    => array(),
            'tfoot'    => array(),
            'tr'    => array(),
            'td'    => array(),
            'th'    => array(),

            // for svg
            'svg'  => array(
                'class'               => array(),
                'aria-hidden'         => array(),
                'aria-labelledby'     => array(),
                'role'                => array(),
                'xmlns'               => array(),
                'width'               => array(),
                'height'              => array(),
                'style'               => array(),
                'fill'                => array(),
                'viewbox'             => array(), 
                'preserveaspectratio' => array(),
            ),
            'mask' => array(
                'width'               => array(),
                'height'              => array(),
                'x'                   => array(),
                'y'                   => array(),
                'style'               => array(),
                'id'                  => array(),
                'maskunits'           => array(),
            ),
            'g' => array(
                'mask'      => array(),
                'fill'      => array(),
                'class'     => array(),
                'transform' => array(),
            ),
            'path' => array(
                'd'               => array(),
                'fill'            => array(),
                'stroke'          => array(),
                'stroke-width'    => array(),
                'stroke-linecap'  => array(),
                'stroke-linejoin' => array(),
                'class'           => array(),
                'opacity'         => array(),
                'transform'       => array(),
                'fill-rule'       => array(),
                'clip-rule'       => array(),
            ),
            'circle' => array(
                'cx'     => array(),
                'cy'     => array(),
                'r'      => array(),
                'fill'   => array(),
                'stroke' => array(),
                'stroke-width' => array(),
            ),
            'rect'   => array(
                'x'      => array(),
                'y'      => array(),
                'width'  => array(),
                'height' => array(),
                'fill'   => array(),
                'rx'     => array(),
                'ry'     => array(),
            ),
            'defs'   => array(),
            'lineargradient' => array(
                'id' => array(),
                'x1' => array(), 
                'y1' => array(), 
                'x2' => array(), 
                'y2' => array(),
                'gradientunits' => array()
            ),
            'radialgradient' => array(
                'id' => array(),
                'cx' => array(), 
                'cy' => array(), 
                'r' => array(),
            ),
            'stop'   => array(
                'offset'       => array(),
                'stop-color'   => array(),
                'stop-opacity' => array(),
            ),
            // 'use'    => array(
            //     'href'   => array(),
            //     'xlink:href' => array(),
            // ),
        );
    }
    add_filter('safe_style_css', 'pixe_safe_style_css');
    function pixe_safe_style_css($styles) {
        $styles[] = 'mask-type'; // for svg
        return $styles;
    }

    // return css style
    function pixe_get_css($type, $data, $display_type = true){
        if( empty($data) ) return '';
        $value = '';
        
        switch($type){
            case 'background-image':
                if( !empty($data['url']) ){
                    $value .= 'background-image: url("' . esc_attr($data['url']) . '");';
                }else if( !empty($data['id']) ){
                    $image_url = wp_get_attachment_image_src($data['id']);
                    $value .= 'background-image: url("' . esc_attr($image_url) . '");';
                }
                break;
            case 'background-color':
                $color = pixe_get_color($data);
                if( in_array($color['type'], array('color', 'preset')) ){
                    $value .= 'background-color:' . esc_attr($color['css']) . ';';
                }else if( $color['type'] == 'gradient' ){
                    $value .= 'background-image:' . esc_attr($color['css']) . ';';
                }
                break;
            case 'background-position':
            case 'object-position':
                $raw_value = '';
                if( is_string($data) ){
                    $raw_value = $data;
                }elseif( !empty($data['position']) ){
                    if( $data['position'] == 'custom' ){
                        $raw_value .= (!empty($data['pos-x'])? $data['pos-x']:'0') . ' ' . (!empty($data['pos-y'])? $data['pos-y']:'0');
                    }else{
                        if( empty($data['pos-x']) && empty($data['pos-y']) ){
                            $raw_value .= str_replace('-', ' ', $data['position']);
                        }else{
                            $x = '50%';
                            $y = '50%';
                            if( strpos($data['position'], 'top') !== false ){ $y = ''; }
                            if( strpos($data['position'], 'bottom' ) !== false ){ $y = '100%'; }
                            if( strpos($data['position'], 'left') !== false ){ $x = ''; }
                            if( strpos($data['position'], 'right') !== false ){ $x = '100%'; }
                            if( !empty($data['pos-x']) ){ $x = $x ? "calc($x + {$data['pos-x']})" : $data['pos-x']; }
                            if( !empty($data['pos-y']) ){ $y = $y ? "calc($y + {$data['pos-y']})" : $data['pos-y']; }
                            $x = empty($x)? '0': $x;
                            $y = empty($y)? '0': $y;
                            $raw_value .= "$x $y";
                        }
                    }
                }

                if (!empty($raw_value) && !empty($display_type)) {
                    $value = "$type: $raw_value;";
                } else {
                    $value = $raw_value;
                }
        }

        return $value;
    }
    function pixe_get_color($color){
        if( is_string($color) ){
            return array(
                'type' => 'color',
                'css' => $color
            );
        }else if( !empty($color['type']) && $color['type'] == 'preset' && !empty($color['name']) ){
            return array(
                'type' => 'preset',
                'css' => 'var(--pixe--color--' . $color['name'] . ')'
            );
        }else if( !empty($color['type']) && in_array($color['type'], array('gradient', 'radial')) ){
            $css = '';
            if( $color['type'] == 'radial' ){
                $css .= 'radial-gradient(circle';
            }else if( !empty($color['angle']) ){
                $css .= 'linear-gradient(' . $color['angle'] . 'deg';
            }else{
                $css .= 'linear-gradient(90deg';
            }

            foreach( $color as $percent => $value ){
                if( !is_numeric($percent) ) continue;
                $css .= ', ' . $value . ' ' . $percent . '%';
            }
            $css .= ')';

            return array(
                'type' => 'gradient',
                'css' => $css
            );
        }else{
            return array( 'type' => '' );
        }
    }

    // fisher yates shuffle with seed
    function pixe_shuffle(array &$array, $seed = -1){
        if( $seed == -1 ){ shuffle($array); return; } 

        mt_srand($seed); // phpcs:ignore WordPress.WP.AlternativeFunctions.rand_seeding_mt_srand -- Use for shuffle non-sensitive array with pagination
        $n = count($array);
        for($i = $n - 1; $i > 0; $i--){
            $j = mt_rand(0, $i); // phpcs:ignore WordPress.WP.AlternativeFunctions.rand_mt_rand -- Use for shuffle non-sensitive array with pagination
            [$array[$i], $array[$j]] = [$array[$j], $array[$i]]; // Swap elements
        }
        mt_srand(); // phpcs:ignore WordPress.WP.AlternativeFunctions.rand_seeding_mt_srand -- Reset seed after used
    }

    // union array by value
    function pixe_union($a1, $a2){
        return array_unique(array_merge($a1, $a2));
    }
    function pixe_union_styles($a1, $a2){
        if( empty($a1) ){ return $a2; }

        $devices = array('desktop', 'tablet', 'mobile');

        foreach( $devices as $device ){
            if( !empty($a2[$device]) ){
                if( empty($a1[$device]) ){
                    $a1[$device] = '';
                }
                $a1[$device] .= $a2[$device];
            }
        }

        return $a1;
    }

    // check if admin ajax request
    function pixe_is_admin(){
        global $pixe_is_admin;
        return empty($pixe_is_admin)? false: true;
    }

    function pixe_get_settings($type, $default_value = ''){
        $settings = array(
            'enable-autosave' => '',
            // 'autosave_duration' => 120,
            // 'revision' => true,
            'revision-amount' => 10,
            'content-width' => '1140px'
        );

        if( empty($settings[$type]) ){
            return $default_value;
        }else{
            return $settings[$type];
        }
    }

    function pixe_get_post_types(){
        global $pixe_post_types;
        if( !empty($pixe_post_types) ) return $pixe_post_types;

        $wp_post_types = get_post_types(array(), 'objects');

        // unset uninterested post types
        $system_types = array(
            'attachment', 
            'revision', 
            'nav_menu_item', 
            'custom_css',
            'customize_changeset',
            'oembed_cache',
            'user_request',
            'wp_block',
            'wp_template',
            'wp_template_part',
            'wp_global_styles',
            'wp_navigation',
            'wp_font_family',
            'wp_font_face',

            // woocommerce
            'product_variation', 
            'shop_order', 
            'shop_coupon', 
            'shop_order_refund', 
            'shop_order_placehold'
        );
        foreach($system_types as $type){
            unset($wp_post_types[$type]);
        }

        // set post type data
        $pixe_post_types = array();
        foreach($wp_post_types as $slug => $object){
            $pixe_post_types[$slug] = $object->labels->singular_name;
        }

        return $pixe_post_types;
    }

    function pixe_get_taxonomies(){
        $ret = array();
        $wp_tax_types = get_taxonomies(array(), 'objects');

        // unset uninterested taxonomies
        $system_types = array(
            'nav_menu', 
            'link_category', 
            'post_format', 
            'wp_theme', 
            'wp_template_part_area', 
            'wp_pattern_category', 
            'product_type', 
            'product_visibility', 
            'product_shipping_class',
            'pos_product_visibility',
            'pa_color', 
            'pa_size'
        );
        
        foreach( $wp_tax_types as $slug => $object ){
            if( in_array($slug, $system_types) ) continue;

            $ret[$slug] = $object->labels->singular_name;
        }

        return $ret;
    }

    // get device width
    function pixe_device_width($device){
        $layout = pixe_get_main_settings('layout');
        switch($device){
            case 'tablet': 
                return empty($layout['tablet-breakout'])? 999: intval($layout['tablet-breakout']);
            case 'mobile':
                return empty($layout['mobile-breakout'])? 767: intval($layout['mobile-breakout']);
        }
        return '';
    }
    function pixe_device_css($device = '', $css = '', $echo = false){
        if( empty($device) || empty($css) ) return '';

        if( !$echo ){
            ob_start();
        }

        $device_width = pixe_device_width($device);
        if( $css == 'media-tag' ){
            echo '@media only screen and (max-width: ' . esc_html($device_width) . 'px){'; 
        }else{
            echo '@media only screen and (max-width: ' . esc_html($device_width) . 'px){';
            pixe_print_esc_css($css);
            echo '}';
        }
    
        if( !$echo ){
            $ret = ob_get_clean();

            return $ret;
        }
    }

    // change name to slug
    function pixe_to_slug( $name ){
        $name = trim($name);
        $name = strtolower($name);
        $name = preg_replace('/[^a-z0-9 -]/', '', $name); // remove any non-alphanumeric characters
        $name = preg_replace('/\s+/', '-', $name); // replace spaces with hyphens
        $name = preg_replace('/-+/', '-', $name); // remove consecutive hyphens

        return $name;
    }

    // for print data attributes
    function pixe_get_atts( $settings ){
        if( empty($settings) ) return '';

        $ret = '';
        foreach( $settings as $slug => $data ){
            if( empty($data) ) continue;
            if( is_array($data) ){  
                $data = json_encode($data); 
            }
            if( $data == 'empty' ){
                $ret .= esc_attr($slug) . ' ';
            }else{
                $ret .= esc_attr($slug) . '="' . esc_attr($data) . '" ';
            }
        } 
        return $ret;
    }
    function pixe_print_div_open($settings){
        echo '<' . (empty($settings['tag'])? 'div': esc_html($settings['tag'])) . ' ';

        // print class
        echo empty($settings['class'])? '': 'class="' . esc_attr($settings['class']) . '" ';
        
        // print data atts
        if( !empty($settings['data-atts']) ){
            foreach($settings['data-atts'] as $slug => $data ){
                if( empty($data) && $data !== '0' && $data !== 0 ) continue;

                if( is_array($data) ){  
                    $data = json_encode($data); 
                }
                if( $data == 'empty' ){
                    echo 'data-' . esc_html($slug) . ' ';
                }else{
                    echo 'data-' . esc_html($slug) . '="' . esc_attr($data) . '" ';
                }
            }
        }

        echo '>';
    }
    function pixe_get_data_atts( $settings ){
        if( empty($settings) ) return '';

        $ret = '';
        foreach( $settings as $slug => $data ){
            if( empty($data) && $data !== '0' && $data !== 0 ) continue;
            if( is_array($data) ){  
                $data = json_encode($data); 
            }
            if( $data == 'empty' ){
                $ret .= 'data-' . esc_attr($slug) . ' ';
            }else{
                $ret .= 'data-' . esc_attr($slug) . '="' . esc_attr($data) . '" ';
            }
        } 
        return $ret;
    }

    function pixe_controls_preset_css( $dep ){
        if( !is_array($dep) ) return ''; 
        
        $controls = pixe_get_controls();
        $types = array('bullet', 'navigation', 'touch-navigation', 'pagination');

        $css = '';
        $tablet_css = '';
        $mobile_css = '';
        
        foreach( $types as $type ){
            if( !empty($dep[$type]) ){
                foreach( $dep[$type] as $slug ){
                    $control_type = $type;
                    if( $control_type == 'touch-navigation' ) $control_type = 'touch';
                    if( empty($controls[$control_type][$slug]['style']) ) continue;

                    $preset_style = $controls[$control_type][$slug]['style'];
                    $css .= empty($preset_style['desktop'])? '': $preset_style['desktop'];
                    $tablet_css .= empty($preset_style['tablet'])? '': $preset_style['tablet'];
                    $mobile_css .= empty($preset_style['mobile'])? '': $preset_style['mobile'];
                }
            }
        }

        return $css . pixe_device_css('tablet', $tablet_css) . pixe_device_css('mobile', $mobile_css);
    }

    // get color preset
    function pixe_color_preset_css(){
        $css = '';
        $colors = pixe_get_colors();

        $active_preset = empty($colors['active-preset'])? 'default': $colors['active-preset'];
        if( !empty($colors['preset'][$active_preset]) ){
            $preset_color = $colors['preset'][$active_preset];
        }else if( !empty($colors['preset']['default']) ){
            $preset_color = $colors['preset'][$active_preset];
        }
        
        if( !empty($preset_color['style']) ){
            $css = ':root{' . $preset_color['style'] . '}';
        }

        return $css;
    }

    // get typo styles
    function pixe_custom_font_css($presets){
        if( !is_array($presets) ) return '';
        $typo = pixe_get_typo();

        $css = '';
        foreach( $presets as $preset ){
            if( empty($typo['customFont'][$preset]) ) continue;

            foreach( $typo['customFont'][$preset] as $custom_font ){
                if( !empty($custom_font['style']) ){
                    $css .= $custom_font['style'];
                }
            }
        }

        return $css;
    }
    function pixe_typo_preset_css($presets){
        if( !is_array($presets) ) return '';
        $typo = pixe_get_typo();

        $css = '';
        $tablet_css = '';
        $mobile_css = '';

        // foreach preset
        foreach( $presets as $preset ){
            if( empty($typo['preset'][$preset]['style']) ) continue;

            $preset_style = $typo['preset'][$preset]['style'];
            $css .= empty($preset_style['desktop'])? '': $preset_style['desktop'];
            $tablet_css .= empty($preset_style['tablet'])? '': $preset_style['tablet'];
            $mobile_css .= empty($preset_style['mobile'])? '': $preset_style['mobile'];
        }
        
        return $css . pixe_device_css('tablet', $tablet_css) . pixe_device_css('mobile', $mobile_css);
    }
    function pixe_buttons_preset_css($presets){
        if( !is_array($presets) ) return '';
        $buttons = pixe_get_button_preset();

        $css = '';
        $tablet_css = '';
        $mobile_css = '';

        // foreach preset
        foreach( $presets as $preset ){
            if( empty($buttons['preset'][$preset]['style']) ) continue;

            $preset_style = $buttons['preset'][$preset]['style'];
            $css .= empty($preset_style['desktop'])? '': $preset_style['desktop'];
            $tablet_css .= empty($preset_style['tablet'])? '': $preset_style['tablet'];
            $mobile_css .= empty($preset_style['mobile'])? '': $preset_style['mobile'];
        }

        return $css . pixe_device_css('tablet', $tablet_css) . pixe_device_css('mobile', $mobile_css);
    }

    // for print style attributes 
    function pixe_get_style_atts( $settings, $style_tag = true ){
        if( empty($settings) ) return '';

        $ret = '';
        foreach( $settings as $slug => $data ){
            if( empty($data) ) continue;

            switch($slug){
                case 'background-image':
                    if( !empty($data['id']) ){
                        $bg_url = wp_get_attachment_image_url($data['id'], 'full');
                        $ret .= 'background-image: url(\'' . esc_url($bg_url) .  '\');';
                    }
                    break;

                case 'opacity':
                    $data = (intval($data) / 100);
                    $ret .= 'opacity: ' . esc_attr($data) . ';';
                    break;

                case 'blend':
                    if( !empty($data) ){
                        $ret .= 'mix-blend-mode:' . esc_attr($data) . ';';
                    } 
                    break;

                default: 
                    $ret .= esc_attr($slug) . ': ' . esc_attr($data) . ';';
                    break;
            }
        }
        if( $style_tag && !empty($ret) ){
            $ret = 'style="' . $ret . '" ';
        }
        return $ret;
    }

    // get unit
    function pixe_get_unit($value){
        if( empty($value) ) return '';
        
        if( trim($value) == 'auto' ){
            return 'auto';
        }else if( strpos($value, 'px') !== false ){
            return 'px';
        }else if( strpos($value, '%') !== false ){
            return '%';
        }else if( strpos($value, 'rem') !== false ){
            return 'rem';
        }else if( strpos($value, 'em') !== false ){
            return 'em';
        }else if( strpos($value, 'vw') !== false ){
            return 'vw';
        }else if( strpos($value, '/') !== false ){
            return 'col';
        }
        return '';
    }

    // get file extension
    function pixe_get_extension($url){
        if( empty($url) ) return '';
        
        $url = explode('#', $url)[0];
        $url = explode('?', $url)[0];

        $urls = explode('.', $url);
        return trim(end($urls));
    }

    // register tmce editor for uses in admin pages
    function pixe_register_tmce(){
        ob_start();
        wp_editor('', 'pixe-tmce');
        return ob_get_clean();
    }

    // enqueue desire script 
    // called this function within admin_enqueue_scripts hook
    function pixe_enqueue_admin_scripts( $scripts ){

        foreach( $scripts as $script ){
            switch( $script ){
                case 'jquery':
                    wp_enqueue_script('jquery');
                    wp_enqueue_script('jquery-effects-core');
                    break;

                case 'wp-editor':
                    wp_enqueue_editor();
                    wp_enqueue_style('editor-buttons');
                    break;

                case 'wp-media':
                    wp_enqueue_media();
                    break;
                    
                case 'builder':
                    wp_enqueue_script('jquery-ui-core');
                    wp_enqueue_script('jquery-ui-sortable');
                    wp_enqueue_script('pixe-prebuilt-page', PIXE_URL . '/admin/js/prebuilt-page.min.js', array(), PIXE_VERSION, true);
                    wp_enqueue_script('pixe-prebuilt-block', PIXE_URL . '/admin/js/prebuilt-block.min.js', array(), PIXE_VERSION, true);
                    wp_enqueue_script('pixe-builder', PIXE_URL . '/admin/js/builder.js', array('jquery'), PIXE_VERSION, true);
                    wp_enqueue_script('pixe-builder-input', PIXE_URL . '/admin/js/builder-input.js', array('jquery'), PIXE_VERSION, true);
                    wp_enqueue_script('pixe-google-font', PIXE_URL . '/admin/js/google-font.min.js', array('jquery'), PIXE_VERSION, true);
                    wp_enqueue_script('pixe-block-settings', PIXE_URL . '/admin/js/block-settings.js', array('jquery'), PIXE_VERSION, true);
                    wp_enqueue_script('pixe-control-settings', PIXE_URL . '/admin/js/control-settings.js', array('jquery'), PIXE_VERSION, true);
                    wp_enqueue_script('pixe-color-settings', PIXE_URL . '/admin/js/color-settings.js', array('jquery'), PIXE_VERSION, true);
                    wp_enqueue_script('pixe-typo-settings', PIXE_URL . '/admin/js/typo-settings.js', array('jquery'), PIXE_VERSION, true);
                    wp_enqueue_script('pixe-icon-settings', PIXE_URL . '/admin/js/icon-settings.js', array('jquery'), PIXE_VERSION, true);
                    wp_enqueue_script('pixe-button-settings', PIXE_URL . '/admin/js/button-settings.js', array('jquery'), PIXE_VERSION, true);
                    wp_enqueue_script('pixe-variable-settings', PIXE_URL . '/admin/js/variable-settings.js', array('jquery'), PIXE_VERSION, true);

                    // for script translation
                    wp_set_script_translations('pixe-builder-input', 'pixebuilder', PIXE_LOCAL_URL . '/languages');
                    wp_set_script_translations('pixe-builder', 'pixebuilder', PIXE_LOCAL_URL . '/languages');

                    do_action('pixe_enqueue_builder_scripts');
                    break;

                case 'editor':
                    wp_enqueue_script('jquery-ui-datepicker');
                    wp_enqueue_script('pixe-editor', PIXE_URL . '/admin/js/editor.js', array('jquery'), PIXE_VERSION, true);
                    wp_enqueue_script('pixe-editor-settings', PIXE_URL . '/admin/js/editor-settings.js', array('jquery'), PIXE_VERSION, true);
                    wp_enqueue_script('pixe-item-util', PIXE_URL . '/admin/js/util-item.js', array('jquery'), PIXE_VERSION, true);
                    wp_enqueue_script('pixe-inline-edit', PIXE_URL . '/admin/js/inline-edit.js', array('jquery'), PIXE_VERSION, true);
                    wp_enqueue_script('pixe-history', PIXE_URL . '/admin/js/history.js', array('jquery'), PIXE_VERSION, true);
                    wp_enqueue_script('pixe-dragdrop', PIXE_URL . '/admin/js/dragdrop.js', array('jquery'), PIXE_VERSION, true);
                    wp_enqueue_script('pixe-wrapper', PIXE_URL . '/admin/js/wrapper.js', array('jquery'), PIXE_VERSION, true);
                    wp_enqueue_script('pixe-collection', PIXE_URL . '/admin/js/collection.js', array('jquery'), PIXE_VERSION, true);
                    wp_enqueue_script('pixe-column', PIXE_URL . '/admin/js/column.js', array('jquery'), PIXE_VERSION, true);
                    wp_enqueue_script('pixe-item', PIXE_URL . '/admin/js/item.js', array('jquery'), PIXE_VERSION, true);
                    do_action('pixe_enqueue_editor_scripts');
                    break;

                case 'utility':
                    // enqueue script
                    wp_enqueue_script('pixe-i18n', PIXE_URL . '/admin/js/i18n.js', array('wp-i18n'), PIXE_VERSION, true);
                    wp_enqueue_script('pixe-util', PIXE_URL . '/admin/js/util.js', array('jquery'), PIXE_VERSION, true);
                    wp_enqueue_script('pixe-input-util', PIXE_URL . '/admin/js/util-input.js', array('jquery'), PIXE_VERSION, true);
                    wp_enqueue_script('pixe-preset-util', PIXE_URL . '/admin/js/util-preset.js', array('jquery'), PIXE_VERSION, true);
                    wp_enqueue_script('pixe-style-selector', PIXE_URL . '/admin/js/style-selector.js', array('jquery'), PIXE_VERSION, true);
                    wp_enqueue_script('pixe-callback-util', PIXE_URL . '/admin/js/util-callback.js', array('jquery'), PIXE_VERSION, true);
                    wp_enqueue_script('dom-purify', PIXE_URL . '/plugins/dompurify/dompurify.min.js', array(), PIXE_VERSION, true);
                    
                    // for script translation
                    wp_set_script_translations('pixe-i18n', 'pixebuilder', PIXE_LOCAL_URL . '/languages');
                    do_action('pixe_enqueue_utility_scripts');
                    break;

                case 'sortable':
                    wp_enqueue_script('jquery-ui-core');
                    wp_enqueue_script('jquery-ui-sortable');
                    break;
                
                case 'color-preset':
                    wp_enqueue_script('pixe-color-settings', PIXE_URL . '/admin/js/color-settings.js', array('jquery'), PIXE_VERSION, true);
                    break;
                
                case 'typo-preset':
                    wp_enqueue_media();
                    wp_enqueue_script('pixe-google-font', PIXE_URL . '/admin/js/google-font.min.js', array('jquery'), PIXE_VERSION, true);
                    wp_enqueue_script('pixe-typo-settings', PIXE_URL . '/admin/js/typo-settings.js', array('jquery'), PIXE_VERSION, true);
                    break;
                
                case 'variable-preset':
                    wp_enqueue_script('pixe-variable-settings', PIXE_URL . '/admin/js/variable-settings.js', array('jquery'), PIXE_VERSION, true);
                    break;

                case 'site-settings':
                    wp_enqueue_script('pixe-prebuilt-page', PIXE_URL . '/admin/js/prebuilt-page.min.js', array(), PIXE_VERSION, true);
                    wp_enqueue_script('pixe-block-settings', PIXE_URL . '/admin/js/block-settings.js', array('jquery'), PIXE_VERSION, true);
                    break;

                case 'template-settings':
                    wp_enqueue_script('pixe-prebuilt-template', PIXE_URL . '/admin/js/prebuilt-template.min.js', array(), PIXE_VERSION, true);
                    wp_enqueue_script('pixe-template-settings', PIXE_URL . '/admin/js/template-settings.js', array('jquery'), PIXE_VERSION, true);
                    break;
                    
                case 'plugin-option':
                    wp_enqueue_script('pixe-plugin-option', PIXE_URL . '/admin/js/plugin-option.js', array('jquery'), PIXE_VERSION, true);
                    wp_enqueue_script('pixe-variable-settings', PIXE_URL . '/admin/js/variable-settings.js', array('jquery'), PIXE_VERSION, true);

                    do_action('pixe_enqueue_plugin_option_scripts');
                    break;

                case 'html2canvas':
                    wp_enqueue_script('html2canvas', PIXE_URL . '/plugins/html2canvas/html2canvas.min.js', array('jquery'), PIXE_VERSION, true);
                    break;
            }
        }

        do_action('pixe_enqueue_admin_scripts', $scripts);
    } // pixe_enqueue_admin_scripts

    function pixe_enqueue_admin_styles( $styles ){

        foreach( $styles as $style ){
            switch( $style ){

                case 'builder':
                    wp_enqueue_style('pixe-builder', PIXE_URL . '/admin/css/builder.css', array(), PIXE_VERSION);
                    pixe_enqueue_icons(array('font-awesome', 'material-symbols', 'lucide'));
                    break;

                case 'editor':
                    wp_enqueue_style('pixe-editor', PIXE_URL . '/admin/css/editor.css', array(), PIXE_VERSION);
                    pixe_enqueue_icons(array('font-awesome', 'material-symbols', 'lucide'));
                    break;

                case 'preset':
                    wp_enqueue_style('pixe-preset', PIXE_URL . '/admin/css/preset.css', array(), PIXE_VERSION);
                    break;

                case 'settings':
                    wp_enqueue_style('pixe-settings', PIXE_URL . '/admin/css/settings.css', array(), PIXE_VERSION);
                    break;
                    
                case 'utility':
                    wp_enqueue_style('pixe-utility', PIXE_URL . '/admin/css/util.css', array(), PIXE_VERSION);
                    break;
            }
        }

    } // pixe_enqueue_admin_styles

    // icons
    function pixe_enqueue_icons( $icons ){
        foreach( $icons as $icon ){
            switch( $icon ){
                case 'font-awesome':
                    wp_deregister_style('font-awesome');
                    wp_enqueue_style('font-awesome', PIXE_URL . '/plugins/fontawesome/fontawesome.min.css', array(), PIXE_VERSION);
                    break;
                
                case 'material-symbols':
                    wp_enqueue_style('material-symbols', PIXE_URL . '/plugins/materialsymbol/outlined.min.css', array(), PIXE_VERSION);
                    break;
                
                case 'lucide':
                    wp_enqueue_style('lucide', PIXE_URL . '/plugins/lucide/lucide.css', array(), PIXE_VERSION);
                    break;
            }
        }
    }

    // enqueue lightbox script
    function pixe_enqueue_lightbox(){
        $lightbox = apply_filters('pixe_enqueue_lightbox', 'glightbox');

        if( $lightbox == 'glightbox' ){
            wp_enqueue_style('glightbox', PIXE_URL . '/plugins/glightbox/dist/css/glightbox.min.css', array(), PIXE_VERSION);
            wp_enqueue_style('glightbox-plyr', PIXE_URL . '/plugins/glightbox/dist/css/plyr.css', array(), PIXE_VERSION);
            wp_enqueue_script('glightbox', PIXE_URL . '/plugins/glightbox/dist/js/glightbox.min.js', array('jquery'), PIXE_VERSION, array('in_footer' => true, 'strategy'  => 'defer'));
            wp_enqueue_script('glightbox-plyr', PIXE_URL . '/plugins/glightbox/dist/js/plyr.js', array('jquery'), PIXE_VERSION, array('in_footer' => true, 'strategy'  => 'defer'));
        }
    }

    // get list of menus
    function pixe_get_menu_list(){
        $menus = wp_get_nav_menus();
        $ret = array(
            '' => 'None'
        );

        if( !empty($menus) ){
            foreach($menus as $menu) {
                $ret[$menu->slug] = $menu->name;
            }
        }

        return $ret;
    }

    // list of all user roles
    function pixe_get_user_role_list(){
        global $wp_roles;
        $roles = $wp_roles->roles;

        $ret = array();
        foreach( $roles as $role_key => $role ){
            $ret[$role_key] = $role['name'];
        }

        return $ret;
    }

    // widget area list
	function pixe_get_widget_area(){
        global $wp_registered_sidebars;

        $ret = array();
        if( !empty($wp_registered_sidebars) && is_array($wp_registered_sidebars) ){
            foreach( $wp_registered_sidebars as $sidebar_id => $value ) {
                $ret[$sidebar_id] = $value['name'];
            }
        }

        return $ret;
    }

    // retrieve all posts from each post type
	function pixe_get_post_list($post_type, $extra = ''){
        $amount = 1000;
        $post_list = get_posts(array(
            'post_type' => $post_type, 
            'numberposts' => $amount
        ));

        $ret = array();
        if( !empty($post_list) ){
            foreach( $post_list as $post ){
                $ret[$post->ID] = $post->post_title;
                if( $extra == 'id' ){
                    $ret[$post->ID] .= ' - ' . $post->ID;
                }
            }
        }
            
        return $ret;
    }
	function pixe_get_post_taxonomy_list($post_type){
        $ret = array();
        $taxes = get_object_taxonomies($post_type, 'objects');
        
        foreach($taxes as $slug => $object){
            if($slug == 'post_format') continue;
            $ret[$slug] = $object->label;
        }
        
        return $ret;
    }
	function pixe_get_post_category_list($taxonomy){
        $ret = array();
        $categories = get_terms(array(
            'taxonomy' => $taxonomy,
            'hide_empty' => false
        ));

        foreach( $categories as $category ){
            $ret[$category->slug] = $category->name;
        }
        
        return $ret;
    }

    // get list of thumbnail sizes
	function pixe_get_thumbnail_list(){
        $ret = array();
        $thumbnails = get_intermediate_image_sizes();
        foreach( $thumbnails as $thumbnail ) {
            if( !empty($GLOBALS['_wp_additional_image_sizes'][$thumbnail]) ){
                $width = $GLOBALS['_wp_additional_image_sizes'][$thumbnail]['width'];
                $height = $GLOBALS['_wp_additional_image_sizes'][$thumbnail]['height'];
            }else{
                $width = get_option($thumbnail . '_size_w', '');
                $height = get_option($thumbnail . '_size_h', '');
            }
            $ret[$thumbnail] = $thumbnail . ' ' . $width . '-' . $height;
        }
        return $ret;
    }

    function pixe_get_cache_version($type){
        $version = get_option('pixe_cache_version', array());
        return empty($version[$type])? 1: $version[$type];
    }
    function pixe_increase_cache_version($type){
        $version = get_option('pixe_cache_version', array());
        if( !is_array($version) ){
            $version = array();
        }

        $version[$type] = empty($version[$type])? 2: absint($version[$type]) + 1;
        update_option('pixe_cache_version', $version, true);
    }
