<?php

global $intense_shortcodes;

require_once INTENSE_PLUGIN_FOLDER . '/inc/shortcodes/shortcode.php';
require_once INTENSE_PLUGIN_FOLDER . '/inc/shortcodes/ajax.php';

class Intense_Shortcodes {
    private $shortcodes = array();

    function __construct() {
        global $intense_visions_options;

        add_action( 'media_buttons', array( __CLASS__, 'button' ), 1000 );

        include_once( ABSPATH . 'wp-admin/includes/plugin.php' );
        if ( is_plugin_active( 'js_composer/js_composer.php' ) && is_admin() ) {
            if ( defined ( 'WPB_VC_VERSION' ) && version_compare( WPB_VC_VERSION, '4.3.2', '>=' ) ) {                
                add_action( 'vc_before_init', array( 'Intense_Shortcodes', 'map_visual_composer' ) );
            } else if ( is_admin() ) {
                add_action( 'after_setup_theme', array( 'Intense_Shortcodes', 'map_visual_composer' ) );
            }
        }

        add_filter( 'the_content', array( 'Intense_Shortcodes', 'cleaner' ) );
        add_filter( 'widget_text', array( 'Intense_Shortcodes', 'cleaner' ) );

        $this->shortcodes = Intense_Shortcodes::get_list();
        $this->add_shortcodes();

        do_action( 'intense/shortcodes', $this->shortcodes );
    }

    public static function get_search_paths( ) {
        $search_paths = array(
            'intense' => INTENSE_PLUGIN_FOLDER . '/shortcodes/'
        );

        $search_paths = apply_filters( 'intense/shortcodes/search_paths', $search_paths );

        return $search_paths;
    }

    public static function load_shortcodes() {
        global $intense_shortcode_list;

        $intense_shortcode_list = array();

        $search_paths = Intense_Shortcodes::get_search_paths();

        foreach ($search_paths as $path_key => $path) {
            $path_directories = scandir($path);

            foreach ($path_directories as $shortcode_directory) {
                if ($shortcode_directory === '.' or $shortcode_directory === '..') continue;

                if (is_dir($path . $shortcode_directory)) {
                    $shortcode_files = scandir( $path . $shortcode_directory );

                    foreach ($shortcode_files as $key => $shortcode_file) {
                        if ($shortcode_file === '.' or $shortcode_file === '..') continue;

                        if ( substr( $shortcode_file, -strlen( "shortcode.php" )) == "shortcode.php" ) {
                            $shortcode_class_name = str_replace( '-shortcode.php', '', $shortcode_file );
                            $shortcode_class_name = ucwords( str_replace( '-', ' ', $shortcode_class_name ) );
                            $shortcode_class_name = 'Intense_' . str_replace( ' ', '_', $shortcode_class_name );
                            $intense_shortcode_list[ $shortcode_class_name ][ 'path' ] = $path . $shortcode_directory . '/' . $shortcode_file;
                            $intense_shortcode_list[ $shortcode_class_name ][ 'directory' ] = $shortcode_directory;

                            if (version_compare(phpversion(), '5.3.0', '<')) {
                                require_once $intense_shortcode_list[ $shortcode_class_name ][ 'path' ];
                            }
                        }

                        if ( substr( $shortcode_file, -strlen( ".scss" )) == ".scss" || substr( $shortcode_file, -strlen( ".css" )) == ".css" ) {
                            $shortcode_class_name = str_replace( '.scss', '', $shortcode_file );
                            $shortcode_class_name = ucwords( str_replace( '-', ' ', $shortcode_class_name ) );
                            $shortcode_class_name = 'Intense_' . str_replace( ' ', '_', $shortcode_class_name );

                             if ( !isset( $intense_shortcode_list[ $shortcode_class_name ][ 'css' ] ) ) {
                                $intense_shortcode_list[ $shortcode_class_name ][ 'css' ] = array();
                            }

                            $intense_shortcode_list[ $shortcode_class_name ][ 'css' ][] = $path . $shortcode_directory . '/' . $shortcode_file;
                        }

                        if ( substr( $shortcode_file, -strlen( "cpt.php" )) == "cpt.php" ) {
                            $shortcode_class_name = str_replace( '-cpt.php', '', $shortcode_file );
                            $shortcode_class_name = ucwords( str_replace( '-', ' ', $shortcode_class_name ) );
                            $shortcode_class_name = 'Intense_' . str_replace( ' ', '_', $shortcode_class_name );
                            require $path . $shortcode_directory . '/' . $shortcode_file;
                            $intense_shortcode_list[ $shortcode_class_name ][ 'cpt' ] = $shortcode_cpt;
                        }
                    }
                }
            }
        }
    }

    public static function get_shortcode_css_paths( ) {
        global $intense_shortcode_list;

        $css_paths = array();

        foreach ( $intense_shortcode_list as $shortcode_class => $shortcode_info ) {
            if ( isset( $shortcode_info['css'] ) ) {
                $css_paths[ $shortcode_info['directory'] ] = array();
                foreach ( $shortcode_info['css'] as $key => $css_path) {
                    $css_paths[ $shortcode_info['directory'] ][] = $css_path;
                }
            }
        }

        return $css_paths;
    }

    public static function get_full_list() {
        global $intense_shortcode_list;

        $shortcodes = array();

        foreach ( $intense_shortcode_list as $key => $value ) {
            $shortcodes[ strtolower( $key ) ] = $key;
        }

        include_once( ABSPATH . 'wp-admin/includes/plugin.php' );
        if ( !is_plugin_active( 'device-mockups/device-mockups.php' ) ) {
            unset( $shortcodes[ 'intense_device_mockups' ] );
            unset( $shortcodes[ 'intense_device_mockup' ] );
        }

        return $shortcodes;
    }

    public static function get_list() {
        //if ( false === ( $shortcodes = wp_cache_get( 'intense_shortcode_list' ) ) ) {
            global $intense_post_types, $intense_visions_options, $intense_shortcode_list;

            $shortcodes = array();

            $active_shortcodes = $intense_visions_options['intense_active_shortcodes'];
            $shortcodes = Intense_Shortcodes::get_full_list();

            foreach ($shortcodes as $key => $value) {
                if ( empty( $active_shortcodes[ strtolower( $key ) ] ) || ! $active_shortcodes[ strtolower( $key ) ] ) {
                    unset( $shortcodes[ $key ] );
                }

                if ( !empty( $intense_shortcode_list[ $value ]['cpt'] ) && ! $intense_post_types->is_type_enabled( $intense_shortcode_list[ $value ]['cpt'] ) ) {
                    unset( $shortcodes[ $key ] );
                }
            }

            include_once( ABSPATH . 'wp-admin/includes/plugin.php' );
            if ( !is_plugin_active( 'device-mockups/device-mockups.php' ) ) {
                unset( $shortcodes[ 'intense_device_mockups' ] );
                unset( $shortcodes[ 'intense_device_mockup' ] );
            }

        //     wp_cache_set( 'intense_shortcode_list', $shortcodes );
        //}

        return $shortcodes;
    }

    /**
     * Enqueue assets needed for editor
     */
    public static function enqueue_dialog_scripts() {
        intense_register_all_assets();
        intense_add_script( 'typewatch' );
        intense_add_script( 'minicolors' );
        intense_add_script( 'smooth-scroll' );
        intense_add_script( 'magnific-popup' );
        intense_add_script( 'selectize' );
        intense_add_script( 'bootstrap-tab' );

        intense_add_style( 'selectize' );
        intense_add_style( 'intense.dialogs' );
        intense_add_style( 'magnific-popup' );
        intense_add_style( 'intense-custom-css' );
        intense_add_style( 'minicolors' );
    }

    /**
     * Used for sorting the list of shortcodes
     *
     * @param Intense_Shortcode $a the first item to compare
     * @param Intense_Shortcode $b the second item to compare
     * @return int    0, 1, -1
     */
    public static function shortcode_compare( $a, $b ) {
        $a = new $a;
        $b = new $b;

        $title_a = strtolower( $a->title );
        $title_b = strtolower( $b->title );


        if ( $title_a == $title_b ) {
            return 0;
        }

        return ( $title_a > $title_b ) ? +1 : -1;
    }

   /**
     * Used for sorting the list of shortcodes
     *
     * @param Intense_Shortcode $a the first item to compare
     * @param Intense_Shortcode $b the second item to compare
     * @return int    0, 1, -1
     */
    public static function shortcode_category_compare( $a, $b ) {
        $a = new $a;
        $b = new $b;

        $category_a = strtolower( $a->category );
        $category_b = strtolower( $b->category );
        $title_a = strtolower( $a->title );
        $title_b = strtolower( $b->title );

        if ( $category_a == $category_b ) {
            if ( $title_a == $title_b ) {
                return 0;
            }

            return ( $title_a > $title_b ) ? +1 : -1;
        } else {
            if ( $category_a == $category_b ) {
                return 0;
            }
            return ( $category_a > $category_b ) ? +1 : -1;
        }
    }

    /**
     * Adds all the shortcodes to WordPress
     * @param string $suffix allows you to set an additional suffix to the end of the shortcode. Useful for registering the shortcodes multiple times so they can be embeded within each other
     */
    public function add_shortcodes( $suffix = '' ) {
        foreach ( $this->shortcodes as $key => $class_name ) {
            if ( version_compare( PHP_VERSION, '5.3.0', '>=' ) ) {
                //create a function to use for the shortcode
                //this is very goofy which means it is for performance (for better memory management)
                $closure = intense_get_shortcode_closure( $key );

                add_shortcode( $key . $suffix, $closure );
            } else if ( version_compare( PHP_VERSION, '5.3.0', '<' ) ) {
                $shortcode = new $class_name;
                add_shortcode( $key . $suffix, array( $shortcode, 'shortcode' ) );
            }
        }
    }

    public function run_shortcode( $shortcode, $atts = null, $content = null ) {
         if ( !empty ( $this->shortcodes[ $shortcode ] ) ) {
            $class_name = $this->shortcodes[ $shortcode ];
            $shortcode = new $class_name;

            return $shortcode->shortcode( $atts, $content );
        } else {
            return "<span style='background: red; color: #fff; font-size: 12px; padding: 10px;'>[Oops: the " . $shortcode . ' shortcode is disabled or missing. Check the shortcode options section for Intense to make sure it is turned on.]</span> ';
        }
    }

    public function get_shortcode_css( $shortcode, $atts = null ) {
        if ( !empty ( $this->shortcodes[ $shortcode ] ) ) {
            $class_name = $this->shortcodes[ $shortcode ];
            $shortcode = new $class_name;

            if ( is_array( $atts ) ) $atts['get_css'] = true;

            return $shortcode->shortcode( $atts );
        }

        return '';
    }

     public function get_shortcode( $key ) {
        $class_name = $this->shortcodes[ $key ];
        return new $class_name;
     }


    public static function map_visual_composer() {
        global $intense_visions_options;

        $hideShortcodes = $intense_visions_options['intense_hide_shortcodes_in_vc'];

        if ( $hideShortcodes === '0' ) {            
            //Visual Composer Shortcode Mappings            
            if ( function_exists( "vc_map" ) ) {
                require_once INTENSE_PLUGIN_FOLDER . '/inc/shortcodes/composer/parameter-types.php';

                intense_add_style( 'intense.visualcomposer' );

                $shortcodes = Intense_Shortcodes::get_list();

                ksort( $shortcodes );

                foreach ( $shortcodes as $key => $class_name ) {
                    $shortcode = new $class_name;
                    $shortcode->map_visual_composer();
                }
            }           
        }
    }

    public function to_json() {
        $data = array();

        uasort( $this->shortcodes, array( $this, "shortcode_compare" ) );

        foreach ( $this->shortcodes as $key => $class_name ) {
            $shortcode = new $class_name;

            if ( !isset( $value->hidden ) || !$value->hidden ) {
                $data[] = array(
                    'group' => $shortcode->category,
                    'icon' => $shortcode->icon,
                    'url' => "action=intense_shortcode_dialog_action&shortcode=" . $key,
                    'shortcode_title' => $shortcode->title,
                    'shortcode' => $key
                );
            }
        }

        return json_encode( $data );
    }

    public function to_documentation() {
        $output = '';

        uasort( $this->shortcodes, array( $this, "shortcode_compare" ) );

        $shortcodes = $this->shortcodes;

        foreach ( $shortcodes as $key => $class_name ) {
            $shortcode = new $class_name;
            $output .= $shortcode->to_documentation();
        }

        return $output;
    }

    public static function button( $args = array() ) {
        global $intense_visions_options;

        $user = wp_get_current_user();
        $roles = $intense_visions_options['intense_show_shortcodes_button'];
        $snippetroles = $intense_visions_options['intense_show_snippets_button'];
        $user_role = reset($user->roles);
        $showShortcodesButton = 1;
        $showSnippetsButton = 1;

        if ( !empty( $user_role ) && isset( $roles ) && is_array( $roles ) && array_key_exists( $user_role, $roles ) && empty( $roles[$user_role] ) ) {            
            $showShortcodesButton = 0;
        }

        if ( !empty( $user_role ) && isset( $snippetroles ) && is_array( $snippetroles ) && array_key_exists( $user_role, $snippetroles ) && empty( $snippetroles[$user_role] ) ) {
            $showSnippetsButton = 0;
        }

        $shortcodeButton = '<a class="intense-shortcode button" data-mfp-src="#intense-shortcode-selector" href="javascript:void(0);">' .
            '<i class="dashicons dashicons-intense-intense-logo"></i> ' . __( 'Shortcodes', 'intense' ) .
            '</a>';
        $snippetButton = '<a class="intense-snippet button" data-mfp-src="#intense-snippet-selector" href="javascript:void(0);">' .
            '<i class="dashicons dashicons-intense-scissors"></i> ' . __( 'Snippets', 'intense' ) .
            '</a>';

        if ( !is_super_admin() && $showShortcodesButton == 0 ) {
            $shortcodeButton = '';
        }

        if ( !is_super_admin() && $showSnippetsButton == 0 ) {
            $snippetButton = '';
        }

        $args = wp_parse_args( $args, array(
                'echo'      => true
            ) );

        add_action( 'wp_footer', array( __CLASS__, 'dialog' ) );
        add_action( 'admin_footer', array( __CLASS__, 'dialog' ) );

        intense_add_script( 'intense.shortcodes' );

        $output = $shortcodeButton . $snippetButton;

        wp_enqueue_media();

        Intense_Shortcodes::enqueue_dialog_scripts();

        if ( $args['echo'] ) echo $output;

        return $output;
    }

    public static function dialog( ) {
        $output = '';

        ob_start();
        require INTENSE_PLUGIN_FOLDER . '/inc/shortcodes/dialog.php';
        $output = ob_get_contents();
        ob_end_clean();
        echo $output;
    }

    public function render_skin_settings() {
        $output = '';

        ob_start();
        require INTENSE_PLUGIN_FOLDER . '/inc/shortcodes/skin-settings.php';
        $output = ob_get_contents();
        ob_end_clean();
        echo $output;
    }

    /**
     * Remove extra p and br tags
     * See: http://www.wpexplorer.com/clean-up-wordpress-shortcode-formatting/
     */
    public static function cleaner( $content ) {
        return strtr( $content, array (
                '<p>[' => '[',
                ']</p>' => ']',
                ']<br />' => ']'
            ) );
    }
}

add_shortcode( 'intense_shortcode_docs', 'intense_shortcode_docs_shortcode' );
function intense_shortcode_docs_shortcode( $atts = null, $content = null ) {
    global $intense_shortcodes;

    extract( shortcode_atts( array(
                'shortcode' => null
            ), $atts ) );

    if ( !empty( $shortcode ) ) {
        $shortcode = $intense_shortcodes->get_shortcode( $shortcode );

        return $shortcode->to_documentation();
    } else {
        return $intense_shortcodes->to_documentation();
    }
}

if ( INTENSE_DEBUG ) {
    add_shortcode( 'intense_default_skin_json', 'intense_default_skin_json_shortcode' );
    function intense_default_skin_json_shortcode( $atts = null, $content = null ) {
        global $intense_shortcodes;

        $skin = new Intense_Skin( 'default', 'Default', array() );

        $shortcodes = $intense_shortcodes->get_list();

        foreach( $shortcodes as $key => $class_name ) {
            $shortcode = $intense_shortcodes->get_shortcode( $key );
            $defaults = $shortcode->get_shortcode_defaults( null, null, true );

            $skin->set_shortcode_defaults( strtolower( get_class( $shortcode ) ), array_filter( $defaults, 'intense_filter_skin_defaults' ) );
        }

        // $shortcode = $intense_shortcodes->get_shortcode( 'intense_alert' );

        // $defaults = $shortcode->get_shortcode_defaults( null, null, true );

        // echo '<pre>'; print_r($defaults); echo '</pre>';

        // $skin->set_shortcode_defaults( strtolower( get_class( $shortcode ) ), array_filter( $defaults, 'intense_filter_skin_defaults' ) );

        unset( $skin->can_edit );
        unset( $skin->source_location );

        return '<pre><code>' . json_encode( $skin, JSON_PRETTY_PRINT ) . '</code></pre>';
    }

    function intense_filter_skin_defaults( $var ) {
        return isset( $var );
    }
}

/**
 * WrappedClosure allows for serializing of closure without blowing up
 */
class WrappedClosure {
    private $closure = NULL;
    protected $reflection = NULL;

    public function __construct($function){
        if ( ! $function instanceOf Closure)
            throw new InvalidArgumentException();
        $this->closure = $function;
        $this->reflection = new ReflectionFunction($function);
    }

    /**
     * When the instance is invoked, redirect invocation to closure.
     */
    public function __invoke(){
        $args = func_get_args();
        return $this->reflection->invokeArgs($args);
    }

    // do nothing on serialization
    public function __sleep(){return array();}

    // do nothing on serialization
    public function __wakeup(){}
}

/**
 * Helper function for running shortcodes
 *
 * @param string  $shortcode the shortcode to run including intense_
 * @param array   $atts      the attributes
 * @param string  $content   content
 * @return string            the html for the shortcode
 */
function intense_run_shortcode( $shortcode, $atts = null, $content = null ) {
    global $intense_shortcodes;

    return $intense_shortcodes->run_shortcode( $shortcode, $atts, $content );
}

/**
 * Helper function for getting shortcode CSS styles
 *
 * @param string  $shortcode the shortcode to run including intense_
 * @param array   $atts      the attributes
 * @return string            the CSS styles for the shortcode
 */
function intense_get_shortcode_css( $shortcode, $atts = null ) {
    global $intense_shortcodes;

    return $intense_shortcodes->get_shortcode_css( $shortcode, $atts );
}

/**
 * Helper function that styles an element to look like it is created by Intense
 * @param  string $id    the id used to find the button (optional)
 * @param  string $class the CSS class used to find the button (optional)
 * @param  array  $extra_atts extra attributes to send to the button for styling
 */
function intense_style_foreign_element( $shortcode, $selector, $atts = array() ) {
    $css_info = intense_get_shortcode_css( $shortcode, $atts );

    if ( !empty( $selector ) && is_array( $css_info ) ) {
        echo "
        <script>
            jQuery(function() {
                var $ = jQuery;            
                $('" . $selector . "').not('.intense').addClass('" . $css_info['base_classes'] . ' ' . $css_info['extra_classes'] . "');                
                $( document ).ajaxComplete( function() { $('" . $selector . "').not('.intense').addClass('" . $css_info['base_classes'] . ' ' . $css_info['extra_classes'] . "'); } );
            });
        </script>";
    }

    if ( !empty ( $css_info['css'] ) ) {
        echo '<style>' . $css_info['css'] . '</style>';
    }
}

function intense_style_foreign_class( $shortcode, $class = null, $extra_atts = array() ) {
    $atts = array_merge( array(
        'class' => $class
    ), $extra_atts );

    intense_style_foreign_element( $shortcode, '.' . $class, $atts );
}

function intense_style_foreign_id( $shortcode, $id = null, $extra_atts = array() ) {
    $atts = array_merge( array(
        'id' => $id
    ), $extra_atts );

    intense_style_foreign_element( $shortcode, '#' . $id, $atts );
}

function intense_style_foreign_tag( $shortcode, $tag = null, $extra_atts = array() ) {
    intense_style_foreign_element( $shortcode, $tag, $extra_atts );
}

if (version_compare(phpversion(), '5.3.0', '>=')) {
  require_once INTENSE_PLUGIN_FOLDER . '/inc/autoload.php';
}

if ( class_exists('FLBuilderModel') ) {
    add_action( 'admin_bar_menu', 'intense_builder_layout_style_dependencies');

    function intense_builder_layout_style_dependencies( $deps ) {
      if( FLBuilderModel::is_builder_active() ) {
        intense_register_all_assets();

        Intense_Shortcodes::dialog();

        intense_add_script( 'typewatch' );
        intense_add_script( 'minicolors' );
        intense_add_script( 'smooth-scroll' );
        intense_add_script( 'magnific-popup' );
        intense_add_script( 'selectize' );
        intense_add_script( 'bootstrap-tab' );

        intense_add_style('selectize');
        intense_add_style('magnific-popup');
        intense_add_style('intense-custom-css');
        intense_add_style('minicolors');
        intense_add_style('intense.dialogs');
        intense_add_style( 'intense.adminicons' );

        echo '<style>
            .intense.shortcode-list {
                padding: 0 !important;
            }

            #intense-shortcode-selector input[type=text], 
            #intense-shortcode-selector input[type=password], 
            #intense-shortcode-selector input[type=email], 
            #intense-shortcode-selector input[type=tel], 
            #intense-shortcode-selector input[type=date], 
            #intense-shortcode-selector input[type=month], 
            #intense-shortcode-selector input[type=week], 
            #intense-shortcode-selector input[type=time], 
            #intense-shortcode-selector input[type=number], 
            #intense-shortcode-selector input[type=search], 
            #intense-shortcode-selector textarea {
                display: initial !important;
            }
        </style>';

        // $deps[] = 'dashicons';
        // $deps[] = 'admin-bar';
        // $deps[] = 'media-views';
        // $deps[] = 'wp-admin';
        // $deps[] = 'wp-auth-check';
        // $deps[] = 'wp-color-picker';
        // $deps[] = 'buttons';
        // $deps[] = 'editor-buttons';
      }
    }
}