<?php
/**
 * @author : Jegtheme
 */

namespace JNews\Module\Block;

use JNews\Module\ModuleViewAbstract;
use JNews\Util\Cache;

abstract class BlockViewAbstract extends ModuleViewAbstract {
	public function render_module( $attr, $column_class ) {
		$heading       = $this->render_header( $attr );
		$name          = str_replace( 'jnews_block_', '', $this->class_name );
		$style_output  = jnews_header_styling( $attr, $this->unique_id . ' ' );
		$style_output .= jnews_module_custom_color( $attr, $this->unique_id . ' ', $name );
		$content       = $this->render_output( $attr, $column_class );
		$style         = ! empty( $style_output ) ? "<style scoped>{$style_output}</style>" : '';
		$script        = $this->render_script( $attr, $column_class );

		return "<div {$this->element_id($attr)} class=\"jeg_postblock_{$name} jeg_postblock jeg_module_hook jeg_pagination_{$attr['pagination_mode']} {$column_class} {$this->unique_id} {$this->get_vc_class_name()} {$this->color_scheme()} {$attr['el_class']}\" data-unique=\"{$this->unique_id}\">
					{$heading}
					{$content}
					{$style}
					{$script}
				</div>";
	}

	public function render_module_out_call( $result, $column_class ) {
		$name = str_replace( 'jnews_block_', '', $this->class_name );

		$content = ! empty( $result ) ? $this->render_column( $result, $column_class ) : $this->empty_content();

		$this->generate_unique_id();

		return "<div class=\"jeg_postblock_{$name} jeg_postblock {$column_class}\">
					<div class=\"jeg_block_container\">
						{$content}
					</div>
				</div>";
	}

	public function get_content_before( $attr ) {
		return apply_filters( 'jnews_module_block_container_extend_before', '', $attr );
	}

	public function get_content_after( $attr ) {
		return apply_filters( 'jnews_module_block_container_extend_after', '', $attr );
	}

	public function get_navigation_before( $attr ) {
		return apply_filters( 'jnews_module_block_navigation_extend_before', '', $attr );
	}

	public function get_navigation_after( $attr ) {
		return apply_filters( 'jnews_module_block_navigation_extend_after', '', $attr );
	}

	public function get_current_page() {
		$page  = get_query_var( 'page' ) ? get_query_var( 'page' ) : 1;
		$paged = get_query_var( 'paged' ) ? get_query_var( 'paged' ) : 1;

		return max( $page, $paged );
	}

	/**
	 * Render Navigation
	 *
	 * @param $attr
	 * @param bool|false $next
	 * @param bool|false $prev
	 * @param int        $total_page
	 *
	 * @return string
	 */
	public function render_navigation( $attr, $next = false, $prev = false, $total_page = 1 ) {
		$output           = '';
		$additional_class = $next || $prev ? '' : 'inactive';

		if ( $attr['pagination_mode'] === 'nextprev' ) {
			$next = $next ? '' : 'disabled';
			$prev = $prev ? '' : 'disabled';

			$prev_text = '<i class="fa fa-angle-left"></i>';
			$next_text = '<i class="fa fa-angle-right"></i>';

			if ( $attr['pagination_nextprev_showtext'] ) {
				$additional_class .= ' showtext';
				$prev_text         = '<i class="fa fa-angle-left"></i> ' . jnews_return_translation( 'Prev', 'jnews', 'prev' );
				$next_text         = jnews_return_translation( 'Next', 'jnews', 'next' ) . '  <i class="fa fa-angle-right"></i>';
			}

			$output =
				"<div class=\"jeg_block_nav {$additional_class}\">
                    <a href=\"#\" aria-label=\"" . esc_html__( 'View previous page posts', 'jnews' ) . "\" class=\"prev {$prev}\" title=\"" . jnews_return_translation( 'Previous', 'jnews', 'previous' ) . "\">{$prev_text}</a>
                    <a href=\"#\" aria-label=\"" . esc_html__( 'View next page posts', 'jnews' ) . "\" class=\"next {$next}\" title=\"" . jnews_return_translation( 'Next', 'jnews', 'next' ) . "\">{$next_text}</a>
                </div>";
		}

		if ( $attr['pagination_mode'] === 'loadmore' || $attr['pagination_mode'] === 'scrollload' ) {
			$next   = $next ? '' : 'disabled';
			$output =
				"<div class=\"jeg_block_loadmore {$additional_class}\">
                    <a href=\"#\" class='{$next}' data-load='" . jnews_return_translation( 'Load More', 'jnews', 'load_more' ) . "' data-loading='" . jnews_return_translation( 'Loading...', 'jnews', 'loading' ) . "'> " . jnews_return_translation( 'Load More', 'jnews', 'load_more' ) . '</a>
                </div>';
		}

		// this is only for default link method
		if ( $attr['pagination_mode'] === 'nav_1' || $attr['pagination_mode'] === 'nav_2' || $attr['pagination_mode'] === 'nav_3' ) {
			if ( $total_page > 1 ) {
				$page   = $this->get_current_page();
				$output = $this->render_normal_navigation( $attr, $total_page, $page );
			}
		}

		$output = apply_filters( 'jnews_module_block_search_navigation', $output, $attr, $next, $prev, $total_page );

		return $output;
	}

	/**
	 * Render Normal Navigation
	 *
	 * @param $args
	 * @param $total
	 * @param int   $current
	 *
	 * @return string
	 */
	public function render_normal_navigation( $args, $total, $current = 1 ) {
		global $wp_rewrite;

		// Setting up default values based on the current URL.
		$pagenum_link = html_entity_decode( get_pagenum_link() );
		$url_parts    = explode( '?', $pagenum_link );

		// Append the format placeholder to the base URL.
		$pagenum_link = trailingslashit( $url_parts[0] ) . '%_%';

		// URL base depends on permalink settings.
		$format  = $wp_rewrite->using_index_permalinks() && ! strpos( $pagenum_link, 'index.php' ) ? 'index.php/' : '';
		$format .= $wp_rewrite->using_permalinks() ? user_trailingslashit( $wp_rewrite->pagination_base . '/%#%', 'paged' ) : '?paged=%#%';

		$defaults = array(
			'base'               => $pagenum_link,
			'format'             => $format,
			'total'              => $total,
			'current'            => $current,
			'show_all'           => false,
			'prev_next'          => true,
			'prev_text'          => jnews_return_translation( 'Prev', 'jnews', 'prev' ),
			'next_text'          => jnews_return_translation( 'Next', 'jnews', 'next' ),
			'end_size'           => 1,
			'mid_size'           => 1,
			'type'               => 'plain',
			'add_args'           => array(), // array of query args to add
			'add_fragment'       => '',
			'before_page_number' => '',
			'after_page_number'  => '',
		);

		$args = wp_parse_args( $args, $defaults );

		if ( ! is_array( $args['add_args'] ) ) {
			$args['add_args'] = array();
		}

		// Merge additional query vars found in the original URL into 'add_args' array.
		if ( isset( $url_parts[1] ) ) {
			// Find the format argument.
			$format_args  = $url_query_args = array();
			$format       = explode( '?', str_replace( '%_%', $args['format'], $args['base'] ) );
			$format_query = isset( $format[1] ) ? $format[1] : '';
			wp_parse_str( $format_query, $format_args );

			// Find the query args of the requested URL.
			wp_parse_str( $url_parts[1], $url_query_args );

			// Remove the format argument from the array of query arguments, to avoid overwriting custom format.
			foreach ( $format_args as $format_arg => $format_arg_value ) {
				unset( $url_query_args[ $format_arg ] );
			}

			$args['add_args'] = array_merge( $args['add_args'], urlencode_deep( $url_query_args ) );
		}

		// Who knows what else people pass in $args
		$total = (int) $args['total'];
		if ( $total < 2 ) {
			return;
		}
		$current  = (int) $args['current'];
		$end_size = (int) $args['end_size']; // Out of bounds?  Make it the default.
		if ( $end_size < 1 ) {
			$end_size = 1;
		}
		$mid_size = (int) $args['mid_size'];
		if ( $mid_size < 0 ) {
			$mid_size = 2;
		}
		$add_args   = $args['add_args'];
		$r          = '';
		$page_links = array();
		$dots       = false;

		if ( $args['prev_next'] && $current && 1 < $current ) :
			$link = str_replace( '%_%', 2 == $current ? '' : $args['format'], $args['base'] );
			$link = str_replace( '%#%', $current - 1, $link );
			if ( $add_args ) {
				$link = add_query_arg( $add_args, $link );
			}
			$link .= $args['add_fragment'];

			/**
			 * Filters the paginated links for the given archive pages.
			 *
			 * @param string $link The paginated link URL.
			 *
			 * @since 3.0.0
			 */
			$page_links[] = '<a class="page_nav prev" aria-label="' . esc_html__( 'Show previous pagination', 'jnews' ) . '" href="' . esc_url( apply_filters( 'paginate_links', $link ) ) . '"><span class="navtext">' . $args['prev_text'] . '</span></a>';
		endif;
		for ( $n = 1; $n <= $total; $n++ ) :
			if ( $n == $current ) :
				$page_links[] = "<span class='page_number active'>" . $args['before_page_number'] . number_format_i18n( $n ) . $args['after_page_number'] . '</span>';
				$dots         = true;
			elseif ( $args['show_all'] || ( $n <= $end_size || ( $current && $n >= $current - $mid_size && $n <= $current + $mid_size ) || $n > $total - $end_size ) ) :
					$link = str_replace( '%_%', 1 == $n ? '' : $args['format'], $args['base'] );
					$link = str_replace( '%#%', $n, $link );
				if ( $add_args ) {
					$link = add_query_arg( $add_args, $link );
				}
					$link .= $args['add_fragment'];

					/** This filter is documented in wp-includes/general-template.php */
					$page_links[] = "<a class='page_number' href='" . esc_url( apply_filters( 'paginate_links', $link ) ) . "'>" . $args['before_page_number'] . number_format_i18n( $n ) . $args['after_page_number'] . '</a>';
					$dots         = true;
				elseif ( $dots && ! $args['show_all'] ) :
					$page_links[] = '<span class="page_number dots">' . '&hellip;' . '</span>';
					$dots         = false;
			endif;
		endfor;
		if ( $args['prev_next'] && $current && ( $current < $total || - 1 == $total ) ) :
			$link = str_replace( '%_%', $args['format'], $args['base'] );
			$link = str_replace( '%#%', $current + 1, $link );
			if ( $add_args ) {
				$link = add_query_arg( $add_args, $link );
			}
			$link .= $args['add_fragment'];

			/** This filter is documented in wp-includes/general-template.php */
			$page_links[] = '<a class="page_nav next" aria-label="' . esc_html__( 'Show next pagination' , 'jnews' ) . '" href="' . esc_url( apply_filters( 'paginate_links', $link ) ) . '"><span class="navtext">' . $args['next_text'] . '</span></a>';
		endif;

		switch ( $args['type'] ) {
			case 'array':
				return $page_links;

			case 'list':
				$r .= "<ul class='page-numbers'>\n\t<li>";
				$r .= join( "</li>\n\t<li>", $page_links );
				$r .= "</li>\n</ul>\n";
				break;

			default:
				$nav_class = 'jeg_page' . $args['pagination_mode'];
				$nav_align = 'jeg_align' . $args['pagination_align'];
				$nav_text  = $args['pagination_navtext'] ? '' : 'no_navtext';
				$nav_info  = $args['pagination_pageinfo'] ? '' : 'no_pageinfo';

				$paging_text = sprintf( jnews_return_translation( 'Page %s of %s', 'jnews', 'page_s_of_s' ), $current, $total );

				$r = join( "\n", $page_links );
				$r = "<div class=\"jeg_navigation jeg_pagination {$nav_class} {$nav_align} {$nav_text} {$nav_info}\">
                <span class=\"page_info\">{$paging_text}</span>
                {$r}
            </div>";
				break;
		}

		return $r;
	}

	/**
	 * Get page link url
	 *
	 * @param $i
	 *
	 * @return string
	 */
	public function get_page_link_url( $i ) {
		global $wp_rewrite;
		$pagenum_link = html_entity_decode( get_pagenum_link() );
		$url          = '' == get_option( 'permalink_structure' ) ? add_query_arg( 'paged', $i, $pagenum_link ) : trailingslashit( $pagenum_link ) . user_trailingslashit( "$wp_rewrite->pagination_base/" . $i, 'single_paged' );
		return 1 == $i ? $pagenum_link : $url;
	}

	/**
	 * @param $attr
	 *
	 * @return string
	 */
	public function render_header( $attr ) {
		if ( defined( 'POLYLANG_VERSION' ) ) {
			$attr['first_title']        = jnews_return_polylang( $attr['first_title'] );
			$attr['second_title']       = jnews_return_polylang( $attr['second_title'] );
			$attr['header_filter_text'] = jnews_return_polylang( $attr['header_filter_text'] );
		}

		// Heading
		$subtitle      = ! empty( $attr['second_title'] ) ? "<strong>{$attr['second_title']}</strong>" : '';
		$header_class  = "jeg_block_{$attr['header_type']}";
		$heading_title = $attr['first_title'] . $subtitle;

		if ( ! empty( $heading_title ) ) {
			$heading_icon  = empty( $attr['header_icon'] ) ? '' : "<i class='" . ( count( explode( ' ', $attr['header_icon'] ) ) !== 1 ? '' : 'fa ' ) . "{$attr['header_icon']}'></i>";
			$heading_title = "<span>{$heading_icon}{$attr['first_title']}{$subtitle}</span>";
			$heading_title = ! empty( $attr['url'] ) ? "<a href='{$attr['url']}'>{$heading_title}</a>" : $heading_title;
			$heading_title = "<h3 class=\"jeg_block_title\">{$heading_title}</h3>";
		}

		// Sub Cat Filtering
		$sub_cat = '';

		// filter category
		if ( ( ! isset( $attr['post_type'] ) || ( isset( $attr['post_type'] ) && 'post' === $attr['post_type'] ) ) && isset( $attr['header_filter_category'] ) ) {
			$categories = trim( $attr['header_filter_category'] );
			if ( ! empty( $categories ) ) {
				$categories = explode( ',', $categories );
				$categories = is_array( $categories ) ? $categories : array( $categories );

				// Need to cache category first
				Cache::get_categories();

				foreach ( $categories as $category ) {
					$cat = get_category( trim( $category ) );
					if ( ! empty( $cat ) && ! is_wp_error( $cat ) ) {
						$sub_cat .= '<li><a class="subclass-filter" href="' . get_category_link( $cat->term_id ) . "\" data-type='category' data-id='{$cat->term_id}'>{$cat->name}</a></li>";
					}
				}
			}
		}

		// filter author
		if ( isset( $attr['header_filter_author'] ) ) {
			$authors = trim( $attr['header_filter_author'] );
			if ( ! empty( $authors ) ) {
				$authors = explode( ',', $authors );
				$authors = is_array( $authors ) ? $authors : array( $authors );

				foreach ( $authors as $author ) {
					$author_id   = trim( $author );
					$author_url  = get_author_posts_url( $author_id );
					$author_name = get_the_author_meta( 'display_name', $author_id );
					$sub_cat    .= "<li><a class=\"subclass-filter\" href=\"{$author_url}\" data-type='author' data-id='{$author_id}'>{$author_name}</a></li>";
				}
			}
		}

		// filter tag
		if ( ( ! isset( $attr['post_type'] ) || ( isset( $attr['post_type'] ) && 'post' === $attr['post_type'] ) ) && isset( $attr['header_filter_tag'] ) ) {
			$tags = trim( $attr['header_filter_tag'] );
			if ( ! empty( $tags ) ) {
				$tags = explode( ',', $tags );
				$tags = is_array( $tags ) ? $tags : array( $tags );

				// Need to cache tag first
				Cache::get_tags();

				foreach ( $tags as $tag ) {
					$tag_object = get_tag( trim( $tag ) );
					if ( $tag_object ) {
						$sub_cat .= '<li><a class="subclass-filter" href="' . get_tag_link( $tag_object->term_id ) . "\" data-type='tag' data-id='{$tag_object->term_id}'>{$tag_object->name}</a></li>";
					}
				}
			}
		}
		if ( isset( $attr['post_type'] ) && 'post' !== $attr['post_type'] ) {
			$taxonomies = \JNews\Util\Cache::get_enable_custom_taxonomies();
			foreach ( $taxonomies as $key => $value ) {
				if ( isset( $attr[ "header_filter_cpt_{$key}" ] ) && in_array( $attr['post_type'], array_values( array_filter( $value['post_types'], 'jnews_delete_default_post_type' ) ) ) ) {
					$taxs = trim( $attr[ "header_filter_cpt_{$key}" ] );
					if ( ! empty( $taxs ) ) {
						$taxs = explode( ',', $taxs );
						$taxs = is_array( $taxs ) ? $taxs : array( $taxs );

						foreach ( $taxs as $tax ) {
							$tag_object = get_term( $tax, trim( $key ) );
							if ( $tag_object ) {
								$sub_cat .= '<li><a class="subclass-filter" href="' . get_tag_link( $tag_object->term_id ) . "\" data-type=\"{$key}\" data-id='{$tag_object->term_id}'>{$tag_object->name}</a></li>";
							}
						}
					}
				}
			}
		}

		if ( ! empty( $sub_cat ) ) {
			$sub_cat = "<li><a class=\"subclass-filter current\" href=\"#\" data-type='all' data-id='0'>{$attr['header_filter_text']}</a></li>" . $sub_cat;
			$sub_cat =
				"<div class=\"jeg_subcat\">
                    <ul class=\"jeg_subcat_list\">
                        {$sub_cat}
                    </ul>
                </div>";
		}

		return empty( $heading_title ) && empty( $sub_cat ) ? '' :
				"<div class=\"jeg_block_heading {$header_class} jeg_subcat_right\">
                     {$heading_title}
                     {$sub_cat}
                 </div>";
	}

	/**
	 * Render script
	 *
	 * @param $attr
	 * @param $column_class
	 *
	 * @return string
	 */
	public function render_script( $attr, $column_class ) {
		// need to retrieve attribute from source
		$attr                 = $this->attribute;
		$attr['paged']        = 1;
		$attr['column_class'] = $column_class;
		$attr['class']        = $this->class_name;
		$json_attr            = wp_json_encode( $attr );

		$output = "<script>var {$this->unique_id} = {$json_attr};</script>";

		return ! ( isset( $attr['ads_type'] ) && $attr['ads_type'] === 'code' ) ? $output :
				$output .= "<div class='hidden'>
								<textarea readonly class='jeg_ad_code'>{$this->content}</textarea>
							</div>";
	}

	/**
	 * Handle Ajax Request for Module
	 */
	public function ajax_request() {
		$attr = (array) $_REQUEST['data'];

		if ( class_exists( 'Polylang' ) ) {
			if ( isset( $_REQUEST['lang'] ) ) {
				$attr['lang'] = sanitize_text_field( $_REQUEST['lang'] );
			}
		}
		$column_class = $attr['attribute']['column_class'];
		$query_param  = $this->build_ajax_query( $attr );
		$results      = $this->build_query( $query_param );
		$this->set_attribute( $attr['attribute'] );

		$content = $this->empty_content();
		if ( ! empty( $results['result'] ) ) {
			$content = $this->render_column( $results['result'], $column_class );
			if ( $attr['attribute']['pagination_mode'] === 'loadmore' || $attr['attribute']['pagination_mode'] === 'scrollload' ) {
				$content = $attr['current_page'] == 1 ? $this->render_column( $results['result'], $column_class ) : $this->render_column_alt( $results['result'], $column_class );
			}
		}

		wp_send_json(
			array(
				'content' => $content,
				'next'    => $results['next'],
				'prev'    => $results['prev'],
			)
		);
	}

	/**
	 * Build Ajax Query
	 *
	 * @param $attr
	 *
	 * @return array
	 */
	public function build_ajax_query( $attr ) {

		$args          = $attr['attribute'];
		$args['paged'] = $attr['current_page'];

		if ( ! empty( $attr['filter_type'] ) && $attr['filter_type'] !== 'all' ) {

			if ( 'post' === $attr['attribute']['post_type'] ) {
				switch ( $attr['filter_type'] ) {
					case 'category':
						$args['include_category'] = $attr['filter'];
						break;
					case 'author':
						$args['include_author'] = $attr['filter'];
						break;
					case 'tag':
						$args['include_tag'] = $attr['filter'];
						break;
				}
			} elseif ( 'author' === $attr['filter_type'] ) {
					$args['include_author'] = $attr['filter'];
			} else {
				$key              = $attr['filter_type'];
				$args[ "{$key}" ] = $attr['filter'];
			}

			$args['sort_by'] = 'latest';
			$args['paged']   = $attr['current_page'];
		}

		$args['number_post'] = $attr['attribute']['number_post'];

		$args['pagination_number_post'] = is_array( $attr['attribute']['pagination_number_post'] ) ? $attr['attribute']['pagination_number_post']['size'] : $attr['attribute']['pagination_number_post'];

		if ( class_exists( 'Polylang' ) ) {
			if ( isset( $attr['lang'] ) ) {
				$args['lang'] = $attr['lang'];
			}
		}
		return $args;
	}

	abstract public function render_column( $result, $column_class );

	abstract public function render_column_alt( $result, $column_class );

	abstract public function render_output( $attr, $column_class );
}
