<?php   

    // prevent direct file access
	if( !defined( 'ABSPATH' ) ) exit;
    
    class Pixe_Builder{
        
        // registered elements
        private static $elements = array();
        public static function register_element($class_name){
            if( class_exists($class_name) && is_subclass_of($class_name, 'Pixebuilder\Element\Item') ){
                $slug = $class_name::get_name();
                self::$elements[$slug] = $class_name;
            }
        }
        public static function get_element($type){
            if( !empty(self::$elements[$type]) ){
                return self::$elements[$type];
            } 
            return '';
        }
        public static function get_elements(){
            return self::$elements;
        }
        public static function get_elements_order(){
            global $pixe_builder;
            $type = empty($pixe_builder['type'])? '': $pixe_builder['type'];
            $part = empty($pixe_builder['part'])? '': $pixe_builder['part'];

            $order = array();
            $unset_elems = array();

            if( $type == 'template' ){
                $order = array(
                    'post' => esc_html__('Query Elements', 'pixebuilder'),
                    'basic' => esc_html__('Basic Elements', 'pixebuilder'),
                    'composite' => esc_html__('Composite Elements', 'pixebuilder'),
                    'woocommerce-item' => esc_html__('Woocommerce Items', 'pixebuilder'),
                    'woocommerce-single' => esc_html__('Woocommerce Single Product Items', 'pixebuilder'),
                );
            }else if( $type == 'template_part' && ($part == 'post_template' || $part == 'taxonomy_template') ){
                $order = array(
                    'post' => esc_html__('Query Elements', 'pixebuilder'),
                    'basic' => esc_html__('Basic Elements', 'pixebuilder'),
                    'composite' => esc_html__('Composite Elements', 'pixebuilder'),
                    'woocommerce-item' => esc_html__('Woocommerce Items', 'pixebuilder'),
                    'woocommerce-single' => esc_html__('Woocommerce Single Product Items', 'pixebuilder'),
                );

                if( $part == 'post_template' ){
                    $unset_elems = array('archive-title', 'archive-description', 'archive-meta');
                }else if( $part == 'taxonomy_template' ){
                    $unset_elems = array(
                        'author-image', 'author-info', 'comment-form', 'comment-number', 'custom-field',
                        'post-categories', 'post-comments', 'post-content', 'post-date', 'post-excerpt', 
                        'post-featured-image', 'post-id', 'post-navigation', 'post-time', 'post-title'
                    );
                }

            }else{
                $order = array(
                    'basic' => esc_html__('Basic Elements', 'pixebuilder'),
                    'composite' => esc_html__('Composite Elements', 'pixebuilder'),
                    'post' => esc_html__('Query Elements', 'pixebuilder'),
                    'woocommerce-item' => esc_html__('Woocommerce Items', 'pixebuilder'),
                    'woocommerce-single' => esc_html__('Woocommerce Single Product Items', 'pixebuilder'),
                );
            }

            $order = apply_filters('pixe_builder_elements_section', $order, $type, $part);

            if( !empty($unset_elems) ){
                foreach($unset_elems as $slug){
                    unset(self::$elements[$slug]);
                }
            }

            return $order;
        }

        // check if allow builder
        public static function can_use_builder($post){
            $general_settings = get_option('pixe_general', array());

            // check post type
            if( !empty($post) ){
                $allow_post_types = empty($general_settings['builder-post-types'])? array('post', 'page'): $general_settings['builder-post-types'];
                $post_type = get_post_type($post);
                if( !in_array($post_type, $allow_post_types) ){
                    return false;
                }
            }
            
            // check user role
            $user = wp_get_current_user();
            $allow_roles = empty($general_settings['builder-user-role'])? array('administrator', 'editor'): $general_settings['builder-user-role'];
            if( empty(array_intersect($allow_roles, $user->roles)) ){
                return false;
            }

            return true;
        }

        // init container
        private static $containers = array();
        public static function register_container($class_name){
            if( class_exists($class_name) && is_subclass_of($class_name, 'Pixe_Preset') ){
                self::$containers[] = $class_name;
            }
        }

        // get builder url
        public static function get_post_edit_url($post_id){
            return admin_url('post.php?action=edit_pixe_builder&post=' . $post_id);
        }
        public static function get_template_edit_url($id, $type, $part = '', $settings = ''){

            // convert settings data type
            if( !empty($settings) && !is_array($settings) ){
                $settings = json_decode($settings, true);
            }

            // return url
            $atts  = 'admin.php?action=edit_pixe_builder&pixe_type=' . $type . '&pixe_id=' . $id;
            $atts .= empty($part)? '': '&pixe_part=' . $part;

            // post template extra args
            if( $type == 'template_part' && ($part == 'post_template' || $part == 'taxonomy_template') ){
                if( !empty($settings['layout']) && $settings['layout'] == 'grid' ){
                    $atts .= '&layout=grid';
                }
            }
            return admin_url($atts);
        }

        // init object
        function __construct(){

            // admin editor
            add_action('admin_enqueue_scripts', array(&$this, 'load_builder_scripts'));
            add_action('admin_enqueue_scripts', array(&$this, 'dequeue_builder_script'), 100);
            add_action('admin_action_edit_pixe_builder', array(&$this, 'get_builder_page'));
        }

        // builder scripts
        function load_builder_scripts( $hook ){
            if( $hook == 'edit_pixe_builder' ){
                pixe_enqueue_admin_styles(array('utility', 'builder', 'preset'));
                pixe_enqueue_admin_scripts(array('jquery', 'wp-media', 'wp-editor', 'utility', 'builder', 'template-settings'));

                wp_localize_script('pixe-i18n', 'pixeData', $this->get_builder_script_data());
            }
        }
        function dequeue_builder_script( $hook ){
            if( $hook == 'edit_pixe_builder' ){

                // deregister woocommerce script for builder
                global $wp_styles, $wp_scripts;
                foreach( $wp_styles->queue as $handle ){
                    if( strpos( $handle, 'wc' ) === 0 || strpos( $handle, 'woocommerce' ) === 0 ){
                        wp_deregister_style($handle);
                    }
                }
                wp_deregister_script('woo-tracks');

                // deregister wordpress script for performance
                wp_dequeue_style('admin-bar');

                wp_dequeue_script('react');
                wp_dequeue_script('wp-commands');
                wp_dequeue_script('wp-core-commands');
                wp_dequeue_script('react-jsx-runtime');
                wp_dequeue_script('admin-bar');
                wp_dequeue_script('wp-auth-check');
                wp_dequeue_script('common');
                wp_dequeue_script('backbone');
                wp_dequeue_script('shortcode');
                wp_dequeue_script('underscore');
                wp_dequeue_script('clipboard');
            }
        }
        function get_builder_script_data(){
            global $pixe_site, $pixe_builder, $post;

            $ret = array(
                'site' => $pixe_site,
                'id' => $pixe_builder['id'],
                'type' => $pixe_builder['type'],
                'part' => empty($pixe_builder['part'])? '': $pixe_builder['part'],
                'templateLayout' => empty($pixe_builder['layout'])? '': $pixe_builder['layout'],
                'homeUrl' => home_url('/'),
                'ajaxUrl' => admin_url('admin-ajax.php'),
                'navMenuUrl' => admin_url('nav-menus.php'),
                'pageUrl' => admin_url('edit.php?post_type=page'),
                'adminUrl' => admin_url('admin.php'),
                'aiConnectorUrl' => admin_url('options-connectors.php'),
                'prebuiltTemplateDir' => PIXE_PREBUILT_TEMPLATE_DIR,
                'nonce' => wp_create_nonce('pixe-editor'),
                'thumbnailSizes' => pixe_get_thumbnail_list(),
                'builderStatus' => get_option('pixe-builder-status', array()), // builder status eg. sidebar locked 
                'wcSupport' => get_theme_support('pixe-woocommerce'),
                'ai' => pixe_get_builder_ai_data(),
                'stockImage' => pixe_get_builder_stock_image_data(),
            );

            // elements order
            $ret['elementOrder'] = self::get_elements_order();

            // post data
            if( $pixe_builder['type'] == 'post' && !empty($pixe_builder['id']) ){

                // autosave data
                $enable_autosave = (pixe_get_settings('enable-autosave') != 'no'); 
                if( $enable_autosave ){
                    $autosave = get_post_meta($pixe_builder['id'], '_autosave-pixe-builder-data', true);
                    if( !empty($autosave) ){
                        $post_date = empty($autosave['post_date_utc'])? '': $autosave['post_date_utc'];
                        $author = get_user_by('ID', $autosave['post_author']);
                        if( !empty($author->display_name) ){
                            $author_name = $author->display_name;
                            $author_thumbnail = get_avatar_url($author->ID, array('size' => 60));
                        }else{
                            $author_name = '';
                            $author_thumbnail = '';
                        }

                        $ret['autosave'] = array(
                            'id' => 'autosave',
                            'time' => $post_date,
                            'author' => $author_name,
                            'thumbnail' => $author_thumbnail
                        );
                    }
                }else{
                    $ret['autosave'] = 'off';
                }

                // post data
                $post_url = get_permalink($pixe_builder['id']);
                $ret['postUrl'] = $post_url;
                $ret['revisionUrl'] = add_query_arg(array('pixe_editor' => 'post', 'pixe_id' => $pixe_builder['id'], 'pixe_revision' => '#rid#'), $post_url);
                $ret['postStatus'] = get_post_status($pixe_builder['id']);
                $ret['returnUrl'] = get_edit_post_link($pixe_builder['id'], false);

                $post_type = get_post_type($pixe_builder['id']);
                if( !empty($post_type) ){
                    $ret['returnPostsUrl'] = admin_url('edit.php?post_type=' . $post_type);
                }

            }else{
                $ret['revisions'] = 'off';
                $ret['autosave'] = 'off';
                $ret['returnUrl'] = admin_url('admin.php?page=pixe_plugin_settings_template');
            }

            // post types
            $ret['postTypes'] = pixe_get_post_types();
            $ret['taxonomies'] = pixe_get_taxonomies();

            // preset
            $ret['iconPreset'] = pixe_get_icons();

            // blocks
            $ret['favouriteBlock'] = pixe_get_favourite_block();
            $ret['customBlocks'] = pixe_get_block_list('block');
            $ret['customPages'] = pixe_get_block_list('page');

            // template
            $ret['template'] = pixe_get_template_list('template');
            $ret['headerTemplate'] = pixe_get_template_list('template_part', 'header');
            $ret['footerTemplate'] = pixe_get_template_list('template_part', 'footer');
            $ret['popupTemplate'] = pixe_get_template_list('template_part', 'popup');
            $ret['syncedBlocks'] = pixe_get_template_list('template_part', 'synced_block');
            $ret['postTemplate'] = pixe_get_template_list('template_part', 'post_template');
            $ret['taxonomyTemplate'] = pixe_get_template_list('template_part', 'taxonomy_template');
            $ret['templateArea'] = pixe_get_template_area();
            $ret['defaultHeader'] = get_option('pixe_default_header', '');
            $ret['defaultFooter'] = get_option('pixe_default_footer', '');

            // container
            $ret['containers'] = array();
            foreach( self::$containers as $container ){
                $ret['containers'][] = array(
                    'icon' => $container::get_icon(),
                    'iconClass' => $container::get_icon_class(),
                    'value' => $container::get_value()
                );
            }

            // elements
            $ret['elements'] = array();
            foreach( self::$elements as $element ){
                $slug = $element::get_name();
                
                $ret['elements'][$slug] = array(
                    'type' => $element::get_type(),
                    'data' => $element::get_data(),
                    'isPro' => $element::is_pro(),
                    'title' => $element::get_title(),
                    'icon' => $element::get_icon(),
                    'default' => $element::get_default()
                );
            }

            // revision
            $ret['revisions'] = array();
            if( $pixe_builder['type'] == 'post' && !empty($pixe_builder['id']) ){

                // get result from cache first
                $cache_key = pixe_post_get_cache_key(array('select' => 'id,post_author,post_date', 'pixe_id' => $pixe_builder['id'], 'order' => 'id,desc'));
                $results = wp_cache_get($cache_key, 'pixebuilder');

                if( empty($results) ){
                    global $wpdb;
                    $results = $wpdb->get_results($wpdb->prepare("SELECT id, post_author, post_date_utc FROM {$wpdb->prefix}pixebuilder WHERE pixe_id = %d ORDER BY id DESC;", $pixe_builder['id'])); // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery
                    wp_cache_set($cache_key, $results, 'pixebuilder', DAY_IN_SECONDS);
                }
                
                if( !empty($results) ){
                    foreach( $results as $result ){
                        $author = get_user_by('ID', $result->post_author);
                        if( !empty($author->display_name) ){
                            $author_name = $author->display_name;
                            $author_thumbnail = get_avatar_url($author->ID, array('size' => 60));
                        }else{
                            $author_name = '';
                            $author_thumbnail = '';
                        }

                        $ret['revisions'][] = array(
                            'id' => $result->id,
                            'time' => empty($result->post_date_utc)? '': $result->post_date_utc,
                            'author' => $author_name,
                            'thumbnail' => $author_thumbnail
                        );
                    }
                }
            }

            $ret = apply_filters('pixe_builder_script_data', $ret);

            return $ret;
        }

        // builder content
        function get_builder_page(){
            global $pagenow, $pixe_builder;
            $pixe_builder = array();
            
            // post
            // phpcs:disable WordPress.Security.NonceVerification.Recommended -- Nonce not required: request performs read-only query.
            if( $pagenow == 'post.php' ){
                $pixe_builder['type'] = 'post';
                $pixe_builder['id'] = empty($_GET['post'])? '': intval(wp_unslash($_GET['post']));

                // allow on this post type
                if( !Pixe_Builder::can_use_builder($pixe_builder['id']) ) return;

                // check capability
                if( !current_user_can('edit_post', $pixe_builder['id']) ){
                    wp_die(esc_html__('Sorry, you are not allowed to edit this item.', 'pixebuilder'));
                }
            
            // custom
            }else if( !empty($_GET['pixe_type']) ){

                // template
                if( $_GET['pixe_type'] == 'template' ){
                    $pixe_builder['type'] = 'template';
                    $pixe_builder['id'] = empty($_GET['pixe_id'])? 'new': intval(wp_unslash($_GET['pixe_id']));

                // template part
                }else if( $_GET['pixe_type'] == 'template_part' ){
                    if( !empty($_GET['pixe_part']) && in_array($_GET['pixe_part'], array('header', 'footer', 'popup', 'synced_block', 'post_template', 'taxonomy_template')) ){
                        $pixe_builder['type'] = 'template_part';
                        $pixe_builder['part'] = sanitize_text_field(wp_unslash($_GET['pixe_part']));
                        $pixe_builder['id'] = empty($_GET['pixe_id'])? 'new': intval(wp_unslash($_GET['pixe_id']));

                        if( $pixe_builder['part'] == 'post_template' ){
                            $pixe_builder['layout'] = empty($_GET['layout'])? '': sanitize_text_field(wp_unslash($_GET['layout']));
                        }
                    }
                }

                // check capability
                if( !current_user_can('manage_options') ){
                    wp_die(esc_html__('Sorry, you are not allowed to edit this item.', 'pixebuilder'));
                }
            }
            // phpcs:enable WordPress.Security.NonceVerification.Recommended

            // invalid builder
            if( empty($pixe_builder['type']) ){
                wp_die(esc_html__('You attempted to edit an item that does not exist. Perhaps it was deleted?', 'pixebuilder'));
            }

            // print builder
            global $current_screen, $hook_suffix;
            $hook_suffix = 'edit_pixe_builder';
            $builder_status = get_option('pixe-builder-status', array());
            $body_class = (empty($builder_status['lock-settings-panel']) || $builder_status['lock-settings-panel'] == 'no')? '': 'pixe-settings-active';
            
            header('Content-Type: ' . get_option('html_type') . '; charset=' . get_option('blog_charset'));
            
            global $is_IE;
            if( $is_IE ){
                header( 'X-UA-Compatible: IE=edge' );
            }

            // phpcs:disable WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedHooknameFound -- Use wordpress hooks to create custom admin editor area
?><!DOCTYPE html>
<html <?php do_action( 'admin_xml_ns' ); language_attributes(); ?> >
    <head>
        <meta http-equiv="Content-Type" content="<?php bloginfo('html_type'); ?>; charset=<?php echo esc_attr(get_option('blog_charset')); ?>" />
        <title><?php echo sprintf(esc_html('Edit %s : Pixe Builder', 'pixebuilder'), esc_html(get_post_type())); ?></title>
        <?php
            do_action('admin_enqueue_scripts', $hook_suffix);
            do_action("admin_print_styles-{$hook_suffix}");
            do_action('admin_print_styles');
            do_action("admin_print_scripts-{$hook_suffix}");
            do_action('admin_print_scripts');
            do_action("admin_head-{$hook_suffix}"); 
            do_action('admin_head');
        ?>
    </head>
    <body class="wp-admin wp-core-ui pixe-builder <?php echo esc_attr($body_class); ?>">
        <?php
            pixe_register_tmce();

            // page builder goes here
            $this->get_builder_content();
            
            // footer section
            do_action('admin_footer', '');
            do_action("admin_print_footer_scripts-{$hook_suffix}");
            do_action('admin_print_footer_scripts');
            do_action("admin_footer-{$hook_suffix}");
        ?>
    </body>
</html><?php
            // phpcs:enable WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedHooknameFound
            exit;
        }

        // get editor content
        function get_builder_content(){
            global $pixe_builder;

            $pixe_builder['part'] = empty($pixe_builder['part'])? '': $pixe_builder['part'];
            $editor_url = Pixe_Editor::get_editor_url($pixe_builder['id'], $pixe_builder['type'], $pixe_builder['part']);
?>
<!-- settings area -->
<div class="pixe-admin-settings-panel" id="pixe-admin-settings-panel" ></div>

<!-- toolbar -->
<div class="pixe-admin-toolbar" id="pixe-admin-toolbar" ></div>

<!-- top bar -->
<div class="pixe-admin-top-bar" id="pixe-admin-top-bar" >
    <div class="pixe-logo" >
        <svg width="17" height="23" viewBox="0 0 17 23" fill="none" ><path d="M4.60597 0C6.90692 0 6.90692 0 6.90692 0V6.90459L2.01674 6.90465L0.00348091 6.90459C0.00348091 6.90459 0.00348091 6.90459 0.00348091 4.60306C0.00348091 0 3.97707 0 4.60597 0Z" fill="#BFBFBF"/><path d="M-9.53674e-07 9.19995H6.89999C6.89999 9.19995 6.90574 16.0953 6.90574 20.6984C6.90574 22.9999 5.16061 22.9999 4.60479 22.9999C0.536257 22.9999 0.00230282 22.9999 0.00230282 22.9999L-9.53674e-07 9.19995Z" fill="white"/><path d="M9.2021 0C9.2021 0 11.5065 0 13.8063 0C16.1055 0 16.1055 1.2533 16.1055 2.30003C16.1055 6.90005 16.1055 10.2675 16.1055 13.8C16.1055 16.1403 14.556 16.1109 13.8046 16.1109C11.5031 16.1109 9.2021 16.1109 9.2021 16.1109V0Z" fill="white"/></svg>
    </div>
    <div class="pixe-admin-top-bar-item" id="pixe-admin-top-bar-item" ></div>
</div>
                
<!-- iframes -->
<div class="pixe-builder-iframe-container" >
    <iframe id="pixe-builder-iframe" class="pixe-builder-iframe" src="<?php echo esc_attr($editor_url) ?>" ></iframe>
</div>
<?php 
        }

    }

    if( is_admin() ){
        new Pixe_Builder();
    }
