<?php

/**
 * The shortcode used display FAQ in the page.
 *
 * @package Flexible_FAQs
 */
namespace WPGO_Plugins\Flexible_Faqs;

/**
 * FAQ shortcode class.
 */
class FAQ_Shortcode
{
    /**
     * Store static class instance.
     *
     * @var $instance
     */
    protected static  $instance ;
    /**
     * Common root paths/directories.
     *
     * @var $module_roots
     */
    protected  $module_roots ;
    /**
     * Main class constructor.
     *
     * @param Array  $module_roots Root plugin path/dir.
     * @param Array  $custom_plugin_data Plugin data.
     * @param Object $utilities_fw Plugin framework utility methods.
     */
    public function __construct( $module_roots, $custom_plugin_data, $utilities_fw )
    {
        $this->module_roots = $module_roots;
        $this->custom_plugin_data = $custom_plugin_data;
        $this->utilities_fw = $utilities_fw;
        $this->text_expand_shortcode_default_atts = $this->custom_plugin_data->shortcode_text_expand_attribute_defaults;
        $this->box_expand_shortcode_default_atts = $this->custom_plugin_data->shortcode_box_expand_attribute_defaults;
        $this->enq_pfx = $this->custom_plugin_data->enqueue_prefix;
        $this->accordion_expand_shortcode_default_atts = $this->custom_plugin_data->shortcode_accordion_expand_attribute_defaults;
        $this->raw_text_expand_attributes = $this->custom_plugin_data->raw_text_expand_attribute_defaults;
        $this->raw_box_expand_attributes = $this->custom_plugin_data->raw_box_expand_attribute_defaults;
        $this->raw_accordion_expand_attributes = $this->custom_plugin_data->raw_accordion_expand_attribute_defaults;
        $this->faq_options = get_option( $this->custom_plugin_data->db_option_prefix . '_options', array() );
        // Shortcode.
        add_shortcode( 'flexible-faqs', array( &$this, 'render_shortcode_wrapper' ) );
        // Register block/shortcode scripts ready for enqueueing.
        add_action( 'wp_enqueue_scripts', array( &$this, 'register_faq_scripts' ) );
    }
    
    /**
     * Create an instance of self.
     *
     * @param Object $module_roots The base properties and configurations of the plugin.
     * @param Object $custom_plugin_data The customized properties and configurations of the plugin.
     * @return Object.
     */
    public static function create_instance( $module_roots, $custom_plugin_data, $utilities_fw )
    {
        if ( !self::$instance ) {
            self::$instance = new FAQ_Shortcode( $module_roots, $custom_plugin_data, $utilities_fw );
        }
        return self::$instance;
    }
    
    /**
     * Returns the current instance of this class if exists.
     *
     * @return Object.
     */
    public static function get_instance()
    {
        if ( !self::$instance ) {
            die( 'Error: Class instance hasn\'t been created yet.' );
        }
        return self::$instance;
    }
    
    /**
     * Register front end scripts.
     *
     * Doing this here so we can add only to pages that contain an FAQ shortcode/block.
     * This means we don't have to scan post content manually.
     */
    public function register_faq_scripts()
    {
        $frontend_js = $this->utilities_fw->get_enqueue_version( '/assets/js/flexible-faqs.js', $this->custom_plugin_data->plugin_data['Version'] );
        wp_register_script(
            $this->enq_pfx . '-plugin-js',
            $frontend_js['uri'],
            array( 'jquery', 'wp-hooks' ),
            $frontend_js['ver'],
            true
        );
        $frontend_css = $this->utilities_fw->get_enqueue_version( '/assets/css/flexible-faqs.css', $this->custom_plugin_data->plugin_data['Version'] );
        wp_enqueue_style(
            $this->enq_pfx . '-plugin-css',
            $frontend_css['uri'],
            array(),
            $frontend_css['ver']
        );
        // Register scripts and styles. These will only be enqueued if shortcode is added to a page.
        // @TODO make sure this jQuery isn't enqueued twice (e.g. need to make the handle the same as the other one)
        // $flexible_faqs_css_rel = '/assets/css/flexible-faqs.css';
        // $flexible_faqs_css_url = plugins_url($flexible_faqs_css_rel, $this->module_roots['file']);
        // $flexible_faqs_css_ver = filemtime($this->module_roots['dir'] . $flexible_faqs_css_rel);
        // wp_register_style('flexible-faq-css', $flexible_faqs_css_url, [], $flexible_faqs_css_ver);
        // wp_enqueue_style('flexible-faq-css', $flexible_faqs_css_url, [], $flexible_faqs_css_ver);
        // This will be done via PHP now for shortcodes and blocks
        // $loc = array(
        // 'plugin_dir' => plugins_url('', __DIR__),
        // );
        // wp_localize_script('wpgo-faq-frontend-js', 'wpgo_faq_data', $loc);
        // if (!empty($options['txt_font1'])) {
        // wp_register_style('wpgo-faq-font1', esc_url($options['txt_font1']), array('flexible-faq-css'));
        // }
        // if (!empty($options['txt_font2'])) {
        // wp_register_style('wpgo-faq-font2', esc_url($options['txt_font2']), array('flexible-faq-css'));
        // }
        // if (!empty($options['txt_font3'])) {
        // wp_register_style('wpgo-faq-font3', esc_url($options['txt_font3']), array('flexible-faq-css'));
        // }
        // if (!empty($options['txt_font4'])) {
        // wp_register_style('wpgo-faq-font4', esc_url($options['txt_font4']), array('flexible-faq-css'));
        // }
    }
    
    /**
     * Render FAQs from block attributes.
     *
     * @param Array $attributes An array of attributes passed to shortcode when being used in the page.
     * @return String HTML markup FAQs.
     */
    public function render_block_wrapper( $attributes )
    {
        // Manually set this to true as we're rendering a block.
        $attributes['gutenberg_bl'] = true;
        return $this->render_faqs( $attributes );
    }
    
    /**
     * Render FAQs from shortcode attributes.
     *
     * @param Array $attributes An array of attributes passed to shortcode when being used in the page.
     * @return String HTML markup FAQs.
     */
    public function render_shortcode_wrapper( $attributes )
    {
        // If any shortcode attributes specified then manually set 'gutenberg_bl' this to false in case it has been manually set to true.
        if ( is_array( $attributes ) ) {
            $attributes['gutenberg_bl'] = false;
        }
        return $this->render_faqs( $attributes );
    }
    
    /**
     * [faq] or [flexible-faq] FAQ shortcode function.
     *
     * Example usage: [faq id="123"] or [faq group="123"] or [flexible-faq id="123"] or [flexible-faq group="123"]
     * Where id is a single faq id and group is an faq group id.
     *
     * @param Array $attributes An array of attributes passed to shortcode when being used in the page.
     * @return String HTML markup FAQs set or group.
     */
    public function render_faqs( $attributes )
    {
        // If $attributes are coming from a shortcode parse here.
        
        if ( !(isset( $attributes['gutenberg_bl'] ) && true === $attributes['gutenberg_bl']) ) {
            // @todo probably a good idea to add the following array to class-constants.php, and pass through to this class, so the list of templates is available to all future shortcodes
            // Whitelist templates in-case they were entered wrong in the shortcode.
            $templates = array( 'text-expand', 'box-expand', 'accordion-expand' );
            
            if ( isset( $attributes['template'] ) && !in_array( $attributes['template'], $templates ) ) {
                $attributes['template'] = 'text-expand';
                // Default to text expand template.
            }
            
            // Get attributes from the shortcode.
            // Get default FAQ theme attributes.
            
            if ( isset( $attributes['template'] ) ) {
                if ( 'text-expand' === $attributes['template'] ) {
                    $shortcode_attributes = $this->text_expand_shortcode_default_atts;
                }
                if ( 'box-expand' === $attributes['template'] ) {
                    $shortcode_attributes = $this->box_expand_shortcode_default_atts;
                }
                if ( 'accordion-expand' === $attributes['template'] ) {
                    $shortcode_attributes = $this->accordion_expand_shortcode_default_atts;
                }
            } else {
                // use 'text-expand' template if none specified.
                $shortcode_attributes = $this->text_expand_shortcode_default_atts;
            }
            
            $shortcode_theme_attributes = $shortcode_attributes['default']['faq_attributes'];
            // If user has set an FAQ theme then merge this with default BEFORE we merge with user specified shortcode attributes.
            if ( isset( $attributes['theme'] ) ) {
                // test user specified theme exists.
                if ( isset( $shortcode_attributes[$attributes['theme']] ) && 'default' !== $attributes['theme'] ) {
                    $shortcode_theme_attributes = array_merge( $shortcode_theme_attributes, $shortcode_attributes[$attributes['theme']]['faq_attributes'] );
                }
            }
            // Merge FAQ theme with rest of attributes set by user.
            $atts = shortcode_atts( $shortcode_theme_attributes, $attributes, 'flexible-faqs' );
            // @TODO don't think this is needed now? Did a test and all shortcode attr. seem accounted for
            // might be empty string if no shortcode attributes specified
            // if (is_array($attributes)) {
            // $atts = array_merge($atts, $attributes);
            // }
        } else {
            // Attributes come from an editor block.
            $atts = $attributes;
            // @TODO should be able to delete this now as it's handled directly in the block - leave until sure though
            // if ($atts['faq_group_toggle'] === false) {
            // render single FAQ post rather than group of posts
            // $atts['group'] = '';
            // }
            // If we're rendering via a block then check the post/group drop down is pointing at a value before attempting to render any FAQs.
            
            if ( true === $atts['faq_group_toggle'] ) {
                $group_arr = (array) json_decode( $atts['faqGroupId'] );
                if ( empty($group_arr) ) {
                    return 'No FAQ groups selected.';
                }
            } else {
                $post_arr = (array) json_decode( $atts['faqPostId'] );
                if ( empty($post_arr) ) {
                    return 'No FAQs selected.';
                }
            }
        
        }
        
        // @TODO when blocks are working test if attr. come through as proper booleans. If so the move this loop inside the first conditional above as it may be unnecessary for blocks.
        // Run converter function for boolean shortcode attributes as 'true' & 'false' are evaluated as string by default.
        foreach ( $atts as $key => $value ) {
            if ( 'true' === $value ) {
                $atts[$key] = true;
            }
            if ( 'false' === $value ) {
                $atts[$key] = false;
            }
        }
        // Output factory default label and description (only used internally).
        
        if ( true === $atts['_factory_labels'] ) {
            
            if ( 'text-expand' === $atts['template'] ) {
                if ( isset( $this->raw_text_expand_attributes[$atts['theme']]['label'] ) ) {
                    $atts['custom_title'] = $this->raw_text_expand_attributes[$atts['theme']]['label'];
                }
                if ( isset( $this->raw_text_expand_attributes[$atts['theme']]['description'] ) ) {
                    $atts['description'] = $this->raw_text_expand_attributes[$atts['theme']]['description'];
                }
            }
            
            
            if ( 'box-expand' === $atts['template'] ) {
                if ( isset( $this->raw_box_expand_attributes[$atts['theme']]['label'] ) ) {
                    $atts['custom_title'] = $this->raw_box_expand_attributes[$atts['theme']]['label'];
                }
                if ( isset( $this->raw_box_expand_attributes[$atts['theme']]['description'] ) ) {
                    $atts['description'] = $this->raw_box_expand_attributes[$atts['theme']]['description'];
                }
            }
            
            
            if ( 'accordion-expand' === $atts['template'] ) {
                if ( isset( $this->raw_accordion_expand_attributes[$atts['theme']]['label'] ) ) {
                    $atts['custom_title'] = $this->raw_accordion_expand_attributes[$atts['theme']]['label'];
                }
                if ( isset( $this->raw_accordion_expand_attributes[$atts['theme']]['description'] ) ) {
                    $atts['description'] = $this->raw_accordion_expand_attributes[$atts['theme']]['description'];
                }
            }
        
        }
        
        // ===================================
        // Unique identifier to avoid conflicts if using multiple faqs on the same page. e.g. faq-5d026c6168954.
        // Setting this here so can't be manually overidden by user.
        $atts['unique_id_raw'] = uniqid();
        $atts['unique_id'] = 'faq-' . $atts['unique_id_raw'];
        // Format some of the attributes.
        
        if ( !empty($atts['faq_group_class']) ) {
            $atts['faq_group_class'] .= ' ' . $atts['faq_group_class'];
            // Add space.
        }
        
        // ===================================
        // The following script doesn't get loaded on the block editor, and so is added separately via another function.
        // But, for the frontend the following method is useful as it means we don't have to manually scan content for blocks/shortcodes.
        wp_enqueue_script( $this->enq_pfx . '-plugin-js' );
        wp_enqueue_script( $this->enq_pfx . '-plugin-js-pro' );
        // ===================================
        // @TODO when faq blocks are in place only do this when NOT rendering a block. i.e. is a shortcode
        // Enqueue the previously registered scripts and styles for the front end FAQs
        // wp_enqueue_script('wpgo-faq-cpt-js');
        // wp_enqueue_style('flexible-faq-css');
        // FAQ_Templates::add_inline_header_styles($atts);
        
        if ( 'text-expand' === $atts['template'] ) {
            $default_atts = $this->raw_text_expand_attributes['default'];
        } elseif ( 'accordion-expand' === $atts['template'] ) {
            $default_atts = $this->raw_accordion_expand_attributes['default'];
        } else {
            // Use box expand defaults.
            $default_atts = $this->raw_box_expand_attributes['default'];
        }
        
        // Render FAQ groups or single list of FAQ items.
        return ( !empty($atts['group']) ? FAQ_Templates::render_faq_group( $atts, $default_atts ) : FAQ_Templates::render_single_faq( $atts, $default_atts ) );
        // The 'group' arg takes priority over 'id'.
        // if (!empty($atts['group'])) {
        // return FAQ_Templates::render_faq_group($atts);
        // }
        // If no group ID specified then try to render single faq, otherwise display error message.
        // return FAQ_Templates::render_single_faq($atts);
    }
    
    /**
     * Render [faq] shortcode for a specified faq group.
     *
     * @param Array $args The arguments received in shortcode usage.
     * @param Array $default_args An array of default argument to use when not provided in shortcode.
     * @return String Contents returned by a call to a static method of FAQ_Templates class.
     */
    public function render_faq_group( $args, $default_args )
    {
        // @todo Not currently used. Delete this function?
        return;
        $args['order'] = ( $args['rnd'] ? 'rand' : 'date' );
        $np = ( -1 === (int) $args['num'] ? true : false );
        $args['np'] = $np;
        // 1. Get template from customizer setting.
        // $customizer_template = WPGO_Customize_FAQ_Templates::get_option( 'wpgo_drp_default_faq_template' );
        // 2. Use shortcode template attribute if set. This has priority over 1.
        // if( !empty( $template ) ) {
        // @todo Need to test here whether the entered template is in the specified global FAQ template array (yet to be created).
        // @todo If not then set $template = '';
        // $customizer_template = $template;
        // }
        // $question = get_post_meta( $id, '_wpgo_faq_cpt_question', true );
        // $answer  =     get_post_meta( $id, '_wpgo_faq_cpt_answer', true );
        // $html = "<p>Q: " . $question . "</p>";
        // $html .= "<p>A: " . $answer . "</p>";
        // return $html;
        return FAQ_Templates::render_faq_group( $args, $default_args );
    }
    
    /**
     * Render [faq] shortcode for single faq.
     *
     * @param Array $args The arguments received in shortcode usage.
     * @param Array $default_args An array of default argument to use when not provided in shortcode.
     * @return String Contents returned by a call to a static method of FAQ_Templates class.
     */
    public function render_single_faq( $args, $default_args )
    {
        // @todo delete this function?
        // 1. Get template from customizer setting
        // $customizer_template = WPGO_Customize_FAQ_Templates::get_option( 'wpgo_drp_default_faq_template' );
        // 2. Override template with post meta setting?
        // $tmp = get_post_meta( $id, '_wpgo_faq_templates_drp', true );
        // if ( ! ( empty( $tmp ) || $tmp == 'none' ) ) {
        // $customizer_template = $tmp;
        // }
        // 3. Use shortcode template attribute if set. This has priority over 1. and 2.
        // if( !empty( $template ) ) {
        // @todo Need to test here whether the entered template is in the specified global FAQ template array (yet to be created).
        // @todo If not then set $template = '';
        // $customizer_template = $template;
        // }
        // $question = get_post_meta( $id, '_wpgo_faq_cpt_question', true );
        // $answer  =     get_post_meta( $id, '_wpgo_faq_cpt_answer', true );
        // $html = "<p>Q: " . $question . "</p>";
        // $html .= "<p>A: " . $answer . "</p>";
        // return $html;
        return FAQ_Templates::render_single_faq( $args, $default_args );
    }

}