<?php

/**
 * FAQ template are selected in this file.
 *
 * @package Flexible_FAQs
 */
namespace WPGO_Plugins\Flexible_Faqs;

/**
 * FAQ templates.
 */
class FAQ_Templates
{
    /**
     * Render a single set of FAQs.
     *
     * @param array $args Shortcode/block args.
     * @return String Faq content for single FAQs set formatted as proper HTML.
     */
    public static function render_single_faq( $args, $default_args )
    {
        // Get Q/A arrays from post meta.
        $questions = get_post_meta( $args['id'], '_wpgo_faq_cpt_questions' );
        $answers = get_post_meta( $args['id'], '_wpgo_faq_cpt_answers' );
        $disabled = array();
        // Modify template name to be a callable function.
        $args['template'] = str_replace( '-', '_', $args['template'] ) . '_template';
        ob_start();
        // Start recording output.
        // @todo Add inline faq styles in header after plugin CSS enqueued?
        echo  self::add_inline_header_styles( $args, $default_args ) ;
        // Call template function specified in $args.
        
        if ( method_exists( __NAMESPACE__ . '\\FAQ_Templates_Markup', $args['template'] ) ) {
            $faq_markup = call_user_func(
                __NAMESPACE__ . '\\FAQ_Templates_Markup::' . $args['template'],
                $args['id'],
                $args,
                $questions,
                $answers,
                $disabled
            );
            // May not be an array if returned with warning message (e.g. When no FAQs defined).
            if ( is_array( $faq_markup ) ) {
                // Only render markup for the FAQ set if there is at least one valid FAQ item (i.e. non empty).
                
                if ( count( $questions[0] ) !== count( $faq_markup[1] ) ) {
                    echo  $faq_markup[0] ;
                } else {
                    echo  self::get_no_valid_faqs_found( $args['id'] ) ;
                }
            
            }
        } else {
            echo  'Single FAQ template not found! Please check the specified template is correct.' ;
        }
        
        $faq_content = ob_get_contents();
        // Get output contents.
        ob_end_clean();
        // End recording output and flush buffer.
        return $faq_content;
    }
    
    /**
     * Render a group (multiple sets) of FAQs.
     *
     * @param array $args Shortcode/block args.
     * @return String Faq content for group of FAQs set formatted as proper HTML.
     */
    public static function render_faq_group( $args, $default_args )
    {
        // Ignore custom title when FAQ groups are rendered. Otherwise the same custom title will be shown for each set of FAQs.
        unset( $args['custom_title'] );
        // Modify template name to be a callable function.
        $args['template'] = str_replace( '-', '_', $args['template'] ) . '_template';
        $faq_group_class = '';
        $accordion_mode = '';
        ob_start();
        // Start recording output.
        // @todo Add inline faq styles in header after plugin CSS enqueued?
        echo  self::add_inline_header_styles( $args, $default_args ) ;
        $faq_group_query = self::get_query( $args );
        ?>
<div id="<?php 
        echo  $args['unique_id'] ;
        ?>" class="faq-group-container group group-id-<?php 
        echo  $args['group'] ;
        echo  $faq_group_class ;
        ?>"<?php 
        echo  $accordion_mode ;
        ?>>
		<?php 
        
        if ( $faq_group_query->have_posts() ) {
            // Used for indexing the current set of FAQs within the group.
            $group_index = 1;
            $faq_sets_rendered = 0;
            while ( $faq_group_query->have_posts() ) {
                $faq_group_query->the_post();
                $post_id = get_the_ID();
                $questions = get_post_meta( $post_id, '_wpgo_faq_cpt_questions' );
                $answers = get_post_meta( $post_id, '_wpgo_faq_cpt_answers' );
                $disabled = array();
                // Call template function specified in $args.
                
                if ( method_exists( __NAMESPACE__ . '\\FAQ_Templates_Markup', $args['template'] ) ) {
                    $faq_markup = call_user_func(
                        __NAMESPACE__ . '\\FAQ_Templates_Markup::' . $args['template'],
                        $post_id,
                        $args,
                        $questions,
                        $answers,
                        $disabled,
                        $group_index
                    );
                    // May not be an array if returned with warning message (e.g. When no FAQs defined).
                    if ( is_array( $faq_markup ) ) {
                        // Only render markup for the FAQ set if there is at least one valid FAQ item (i.e. non empty).
                        
                        if ( count( $questions[0] ) !== count( $faq_markup[1] ) ) {
                            $faq_sets_rendered++;
                            echo  $faq_markup[0] ;
                        }
                    
                    }
                } else {
                    echo  'Group FAQ template not found! Please check the specified template is correct.' ;
                }
                
                $group_index++;
            }
            // If no FAQ sets rendered then display warning message.
            if ( 0 === $faq_sets_rendered ) {
                echo  self::get_no_valid_group_faqs_found( $args['group'] ) ;
            }
            // Reset the global $the_post as this query will have stomped on it.
            wp_reset_postdata();
        } else {
            echo  self::get_no_group_posts( $args ) ;
        }
        
        ?>
</div>
		<?php 
        $faq_content = ob_get_contents();
        // Get output contents.
        ob_end_clean();
        // End recording output and flush buffer.
        return $faq_content;
    }
    
    /**
     * Build faq wrapper styles.
     *
     * @param Array  $args An array of supplied arguments.
     * @param Array  $default_args An array of default arguments.
     * @param String $pre Prefix for printing internal style.
     * @return String CSS statements for faq styling.
     */
    public static function build_wrapper_styles( $args, $default_args, $pre )
    {
        $styles = '';
        $styles1 = '';
        
        if ( !empty($args['faq_border']) && $default_args['faq_attributes']['faq_border'] !== $args['faq_border'] ) {
            $faq_border1 = Utility::build_css_from_border_object(
                $args['faq_border'],
                false,
                false,
                false,
                $args
            );
            $faq_border2 = Utility::build_css_from_border_object(
                $args['faq_border'],
                true,
                true,
                false,
                $args
            );
            $faq_border3 = Utility::build_css_from_border_object(
                $args['faq_border'],
                true,
                false,
                false,
                $args
            );
            
            if ( !empty($args['faq_border']) && 'accordion_expand_template' === $args['template'] ) {
                $styles1 = $pre . ' .flexible-faq-wrapper { ' . $faq_border1 . '; border-bottom: 0px; }';
                $styles1 .= $pre . ' .flexible-faq-wrapper:last-of-type { ' . $faq_border2 . '; margin-bottom: 0; }';
            } else {
                $styles .= ' ' . $faq_border3 . ';';
            }
            
            // if (!empty($args['faq_border']) && $args['template'] === 'accordion_expand_template') {
            // $styles1 = $pre . " .flexible-faq-wrapper { border: " . $args['faq_border'] . "; border-bottom: 0px; }";
            // $styles1 .= $pre . " .flexible-faq-wrapper:last-of-type { border-bottom: " . $args['faq_border'] . "; margin-bottom: 0; }";
            // } else {
            // $styles .= ' border: ' . $args['faq_border'] . ';';
            // }
        }
        
        if ( !empty($styles) ) {
            $styles = $pre . '.flexible-faq-wrapper {' . $styles . " }\n";
        }
        return $styles1 . $styles;
    }
    
    /**
     * Build .faq-question styles for <style> tag.
     *
     * @param Array  $args An array of supplied arguments.
     * @param Array  $default_args An array of default arguments.
     * @param String $pre Prefix for printing internal style.
     * @return String CSS statement for faq question styling.
     */
    public static function question_styles( $args, $default_args, $pre )
    {
        $styles = '';
        $font_weight = '';
        return $styles;
    }
    
    /**
     * Inner question styles for <style> tag.
     *
     * @param Array  $args An array of supplied arguments.
     * @param Array  $default_args An array of default arguments.
     * @param String $pre Prefix for printing internal style.
     * @return String CSS statements for faq styling.
     */
    public static function inner_question_styles( $args, $default_args, $pre )
    {
        $styles = '';
        $styles1 = '';
        $styles2 = '';
        $end = "; }\n";
        // Build .faq-inner-question styles.
        if ( !empty($args['q_color']) && $default_args['faq_attributes']['q_color'] !== $args['q_color'] ) {
            $styles .= 'color: ' . $args['q_color'] . ';';
        }
        if ( !empty($args['q_bg_color']) && $default_args['faq_attributes']['q_bg_color'] !== $args['q_bg_color'] ) {
            $styles .= 'background-color: ' . $args['q_bg_color'] . ';';
        }
        if ( !empty($styles) ) {
            $styles = $pre . '.faq-inner-question {' . $styles . " }\n";
        }
        return $styles . $styles1 . $styles2;
    }
    
    /**
     * Inner answer styles.
     *
     * @param array  $args Shortcode/block args.
     * @param Array  $default_args An array of default arguments.
     * @param string $pre CSS class prefix.
     * @return String CSS statement for faq answers styling.
     */
    public static function inner_answer_styles( $args, $default_args, $pre )
    {
        $bg_styles = '';
        $styles = '';
        $link_styles = '';
        $answer_styles = '';
        $p_styles = '';
        // Build styles.
        
        if ( !empty($args['a_color']) && $default_args['faq_attributes']['a_color'] !== $args['a_color'] ) {
            $styles .= 'color: ' . $args['a_color'] . ';';
            $link_styles .= 'color: ' . $args['a_color'] . ';';
            $link_styles .= 'font-weight: bold;';
        }
        
        if ( !empty($styles) ) {
            $styles = $pre . '.faq-inner-answer {' . $styles . " }\n";
        }
        if ( !empty($bg_styles) ) {
            $bg_styles = $pre . '.flexible-faq.faq-answer {' . $bg_styles . " }\n";
        }
        if ( !empty($p_styles) ) {
            $styles .= $pre . '.faq-inner-answer p {' . $p_styles . "}\n";
        }
        if ( !empty($answer_styles) ) {
            $styles .= $pre . '.faq-inner-answer {' . $answer_styles . "}\n";
        }
        
        if ( !empty($link_styles) ) {
            $link_styles = $pre . '.faq-inner-answer a {' . $link_styles . " }\n";
            $styles .= $link_styles . "\n";
        }
        
        $styles .= $bg_styles . "\n";
        return $styles;
    }
    
    /**
     * Expand/collapse styles.
     *
     * @param array  $args Shortcode/block args.
     * @param Array  $default_args An array of default arguments.
     * @param string $pre CSS class prefix.
     * @return String Styles for FAQ expand/collapse icon.
     */
    public static function icon_styles( $args, $default_args, $pre )
    {
        $styles = '';
        // Build styles.
        // Icon color values.
        $icon_colors = array( $args['icon_expand_color'], $args['icon_expand_color'] );
        // Rotate icon styles.
        if ( !(true === $args['rotate_icon']) ) {
            $styles .= $pre . ".faq-expand-img { transform: rotateZ(0deg); }\n";
        }
        // Icon color styles.
        if ( !empty($icon_colors[0]) && $default_args['faq_attributes']['icon_expand_color'] !== $args['icon_expand_color'] ) {
            $styles .= $pre . '.faq-expand-img.closed .icon-color { fill: ' . $icon_colors[0] . "; }\n";
        }
        return $styles;
    }
    
    /**
     * Convert values from 4 input fields to valid CSS value.
     *
     * @todo This function should probably be in the JS block code.
     *
     * @param String $json_obj JSON.stringified JS object.
     * @param Array  $args Supplied Arguments.
     * @return String CSS statement for faq styling.
     */
    public static function build_css_from_four_input_boxes( $json_obj, $args )
    {
        $css_obj = json_decode( $json_obj );
        // If for any reason the parsed JSON string doesn't evaluate to an object (it should) then return no CSS.
        if ( !is_object( $css_obj ) ) {
            return '';
        }
        if ( property_exists( $css_obj, 'literal' ) ) {
            return $css_obj->literal;
        }
        // @TODO don't think we need this anymore as blanks are now filled in React component.
        // Or keep in as a fail safe?
        $one = ( empty($css_obj->one) ? '0' : $css_obj->one );
        $two = ( empty($css_obj->two) ? '0' : $css_obj->two );
        $three = ( empty($css_obj->three) ? '0' : $css_obj->three );
        $four = ( empty($css_obj->four) ? '0' : $css_obj->four );
        $unit = ( !isset( $css_obj->unit ) || empty($css_obj->unit) ? 'px' : $css_obj->unit );
        // Calculate unit for each value.
        $unit1 = ( '0' === $one ? '' : $unit );
        $unit2 = ( '0' === $two ? '' : $unit );
        $unit3 = ( '0' === $three ? '' : $unit );
        $unit4 = ( '0' === $four ? '' : $unit );
        
        if ( isset( $css_obj->mode ) ) {
            if ( '1' === $css_obj->mode ) {
                return $one . $unit1;
            }
            
            if ( '2' === $css_obj->mode ) {
                // If both '0' then just return '0' with no unit.
                if ( '0' === $one && '0' === $two ) {
                    return '0';
                }
                return $one . $unit1 . ' ' . $two . $unit2;
            }
        
        }
        
        // If all four are '0' then just return '0' with no unit.
        if ( '0' === $one && '0' === $two && '0' === $three && '0' === $four ) {
            return '0';
        }
        return $one . $unit1 . ' ' . $two . $unit2 . ' ' . $three . $unit3 . ' ' . $four . $unit4;
    }
    
    /**
     * Outer wrapper classes.
     *
     * @param Array $args Array of supplied arguments.
     * @return String Class names for the outer FAQs wrapper element.
     */
    public static function outer_wrapper_classes( $args )
    {
        $classes = '';
        if ( !empty($classes) ) {
            $classes = ' ' . $classes;
        }
        return $classes;
    }
    
    /**
     * Separator between FAQ items.
     *
     * @param Array   $args Array of supplied arguments.
     * @param Integer $key Received key value.
     * @param Array   $questions An array of questions in the FAQ set.
     * @param Boolean $force_last_item Is it last item?.
     * @return String HTML markup for FAQs separator.
     */
    public static function faq_separator(
        $args,
        $key,
        $questions,
        $faq_index,
        $last = false
    )
    {
        // Display 'faq_separator' if true and we're not rendering the last faq item.
        
        if ( true === $args['faq_separator'] ) {
            // Are we rendering the first FAQ item?
            if ( 0 === $faq_index ) {
                // If so then decide whether to show an FAQ separator before the first item.
                
                if ( 'both' === $args['faq_separator_mode'] || 'before' === $args['faq_separator_mode'] ) {
                    return '<div class="faq-separator"></div>';
                } else {
                    return '';
                }
            
            }
            // Are we rendering the last FAQ item?
            if ( $last ) {
                // If so then decide whether to show an FAQ separator after the last item.
                
                if ( 'both' === $args['faq_separator_mode'] || 'after' === $args['faq_separator_mode'] ) {
                    return '<div class="faq-separator"></div>';
                } else {
                    return '';
                }
            
            }
            return '<div class="faq-separator"></div>';
        }
        
        return '';
    }
    
    /**
     * Separator HTML between Q and A.
     *
     * @param Array  $args An array of supplied arguments.
     * @param String $location location of separator (inside or outside).
     * @return String HTML markup for QA separator.
     */
    public static function q_a_separator( $args, $location )
    {
        // Build html.
        
        if ( true === $args['q_a_separator'] ) {
            $separator_html = '<div class="q-a-separator"></div>';
            // Render the Q/A separator as the first child of .faq-inner-answer or the immediately previous sibling of .faq-inner-answer.
            
            if ( 'inside' === $args['q_a_separator_location'] && 'inside' === $location ) {
                return $separator_html;
            } elseif ( 'outside' === $args['q_a_separator_location'] && 'outside' === $location ) {
                return $separator_html;
            }
            
            return '';
        }
        
        return '';
    }
    
    /**
     * Generate icon HTML.
     *
     * @param Array $args An array of supplied arguments.
     * @return String SVG icon HTML markup.
     */
    public static function get_icon( $args, $faq_index )
    {
        
        if ( method_exists( __NAMESPACE__ . '\\Svg_Icons', $args['icon'] ) ) {
            $icon_cb = __NAMESPACE__ . '\\Svg_Icons::' . $args['icon'];
            $icon = call_user_func( $icon_cb, $args, $faq_index );
            return '<span class="faq-question-expand">' . $icon . '</span>';
        }
        
        // Default to arrow1.
        $icon_cb = __NAMESPACE__ . '\\Svg_Icons::arrow1';
        $icon = call_user_func( $icon_cb, $args, $faq_index );
        return '<span class="faq-question-expand">' . $icon . '</span>';
    }
    
    /**
     * Provides HTML for faq title.
     *
     * @param Integer $id Unique ID of FAQs set (CPT).
     * @param Array   $args An array of suplied arguments.
     * @return String HTML markup for FAQs title.
     */
    public static function get_faq_title( $id, $args )
    {
        $title_text = '';
        $title_tag = 'h2';
        // $args['faq_group_toggle'] ? 'h2' : 'h3'; // @TODO if we have a group then make faq groups use <h3>
        $open = '<' . $title_tag . ' class="faq-title">';
        $close = '</' . $title_tag . '>';
        if ( empty($title_text) ) {
            $title_text = get_the_title( $id );
        }
        return $open . $title_text . $close;
    }
    
    /**
     * Add inline header styles.
     *
     * @param Array $args An array of supplied arguments.
     * @param Array $default_args An array of default arguments.
     * @return String Formatted styles.
     */
    public static function add_inline_header_styles( $args, $default_args )
    {
        // FAQ instance CSS id prefix so styles target a specific FAQ.
        $pre = '#' . $args['unique_id'] . ' ';
        $end = "; }\n";
        $styles = '';
        // .flexible-faq-wrapper
        $styles .= self::question_styles( $args, $default_args, $pre );
        $styles .= self::build_wrapper_styles( $args, $default_args, $pre );
        $styles .= self::inner_question_styles( $args, $default_args, $pre );
        $styles .= self::inner_answer_styles( $args, $default_args, $pre );
        $styles .= self::icon_styles( $args, $default_args, $pre );
        // Add inline styles after main plugin stylesheet or return empty string if no styles generated.
        
        if ( !empty(trim( $styles )) ) {
            $styles = '/* Flexible FAQ generated styles for: #' . $args['unique_id'] . " */\n" . $styles;
            return '<style>' . $styles . '</style>';
        } else {
            return '';
        }
        
        // wp_add_inline_style('flexible-faq-css', $styles); //.
    }
    
    /**
     * Run a custom query on CPT.
     *
     * @param Array $args An array of supplied arguments.
     */
    public static function get_query( $args )
    {
        return new \WP_Query( array(
            'post_type'           => 'wpgo_faq',
            'post_status'         => 'publish',
            'ignore_sticky_posts' => 1,
            'tax_query'           => array( array(
            'taxonomy' => 'wpgo_faq_group',
            'field'    => 'id',
            'terms'    => $args['group'],
        ) ),
        ) );
    }
    
    /**
     * Error message if FAQ posts ID specified in shortcode is not published.
     *
     * @param Array $args An array of supplied arguments.
     * @return String Error message formatted as HTML.
     */
    public static function get_not_published_faq( $args )
    {
        return '<p>' . sprintf( __( 'Warning! This set of FAQs (ID: %d) is not set to published. Please update to published status in order to view the FAQs.', 'flexible-faqs' ), $args['id'] ) . '</p>';
    }
    
    /**
     * Error message if no FAQs associated with group ID are found.
     *
     * @param Array $args An array of supplied arguments.
     * @return String error message formatted as HTML.
     */
    public static function get_no_group_posts( $args )
    {
        // @todo This isn't showing up in the POT translation file.
        return '<p>' . __( 'Warning! No FAQs associated with group ID: ' . $args['group'] . ' found. Please enter a valid group ID that has active FAQs added to it.', 'flexible-faqs' ) . '</p>';
    }
    
    /**
     * Error message if no valid FAQ items are found in a single set of FAQs.
     *
     * @return String error message formatted as HTML.
     */
    public static function get_no_valid_faqs_found( $id )
    {
        // @todo This isn't showing up in the POT translation file.
        return '<p>' . __( 'Warning! All FAQ items in this set (ID: ' . $id . ') appear to be empty. Please make sure at least one FAQ item in the set is not disabled, and has content added for the question and answer fields.', 'flexible-faqs' ) . '</p>';
    }
    
    /**
     * Error message if no valid FAQ items are found in an entire group of FAQs.
     *
     * @return String error message formatted as HTML.
     */
    public static function get_no_valid_group_faqs_found( $group_id )
    {
        // @todo This isn't showing up in the POT translation file.
        return '<p>' . __( 'Warning! All FAQ items in this group (ID: ' . $group_id . ') appear to be empty. Please make sure at least one FAQ item in the group is not disabled, and has content added for the question and answer fields.', 'flexible-faqs' ) . '</p>';
    }
    
    /**
     * Error message if no group ID is provided.
     *
     * @param Integer $id Unique ID of FAQs set or group.
     * @return String error message formatted as HTML.
     */
    public static function get_no_faqs_found( $id )
    {
        // @todo this isn't showing up in the POT translation file
        
        if ( !empty($id) ) {
            return '<p>' . __( 'Warning! No FAQs found for post ID: ' . $id . '. Please check the shortcode ID attribute is correct, and the post contains at least one FAQ item.', 'flexible-faqs' ) . '</p>';
        } else {
            return '<p>' . __( 'Warning! No FAQ post ID found. Please enter a non-empty valid FAQ post ID.', 'flexible-faqs' ) . '</p>';
        }
    
    }

}
/* End of class definition */