<?php

/**
 * Class CFF_Feed_Pro
 */

namespace CustomFacebookFeed;

if (! defined('ABSPATH')) {
	exit; // Exit if accessed directly
}


class CFF_Feed_Pro
{
	/**
	 * @var string
	 */
	private $regular_feed_transient_name;

	/**
	 * @var array
	 */
	private $post_data;

	/**
	 * @var array
	 */
	private $next_pages;

	/**
	 * @var bool
	 */
	private $should_paginate;

	/**
	 * @var int
	 */
	private $num_api_calls;

	/**
	 * @var bool
	 */
	private $should_use_backup;

	/**
	 * @var array
	 */
	private $report;

	private $resized_images;

	private $is_customizer;

	protected $one_post_found;

	protected $max_api_calls;

	public function __construct($transient_name, $is_customizer = false)
	{
		$this->regular_feed_transient_name = $transient_name;

		$this->post_data = array();
		$this->next_pages = array();
		$this->should_paginate = true;

		// this is a count of how many api calls have been made for each feed
		// type and term.
		// By default the limit is 10
		$this->num_api_calls = 0;
		$this->max_api_calls = 10;
		$this->should_use_backup = false;

		// used for errors and the sbi_debug report
		$this->report = array();

		$this->resized_images = array();

		$this->one_post_found = false;
		$this->is_customizer = $is_customizer;
	}

	public function get_post_data()
	{
		return $this->post_data;
	}

	public function set_post_data($post_data)
	{
		$this->post_data = $post_data;
	}

	public function get_next_pages()
	{
		return $this->next_pages;
	}

	public function need_posts($num, $offset = 0)
	{
		$num_existing_posts = is_array($this->post_data) ? count($this->post_data) : 0;
		$num_needed_for_page = (int)$num + (int)$offset;

		($num_existing_posts < $num_needed_for_page) ? $this->add_report('need more posts') : $this->add_report('have enough posts');

		return ($num_existing_posts < $num_needed_for_page);
	}

	public function can_get_more_posts()
	{
		$one_type_and_term_has_more_ages = $this->next_pages !== false;
		$max_concurrent_api_calls_not_met = $this->num_api_calls < $this->max_api_calls;
		$max_concurrent_api_calls_not_met ? $this->add_report('max conccurrent requests not met') : $this->add_report('max concurrent met');
		$one_type_and_term_has_more_ages ? $this->add_report('more pages available') : $this->add_report('no next page');

		return ($one_type_and_term_has_more_ages && $max_concurrent_api_calls_not_met);
	}

	public function add_remote_posts($settings, $feed_id = false)
	{
		$new_post_sets = array();
		$next_pages = $this->next_pages;

		$settings['include_extras'] = true;

		$one_post_found = false;
		$next_page_found = false;
		$settings['the_feed_id'] = $feed_id;

		if (! empty($next_pages) && $next_pages !== '{}') {
			$next_pages = json_decode(str_replace(array( '\"', '&quot;' ), '"', $next_pages), true);
			$new_post_sets = CFF_Shortcode::cff_get_json_data($settings, $next_pages, '', $this->is_customizer);
		} else {
			$new_post_sets = CFF_Shortcode::cff_get_json_data($settings, null, '', $this->is_customizer);
		}

		$reporter = CFF_Utils::cff_is_pro_version() ? \cff_main_pro()->cff_error_reporter : \cff_main()->cff_error_reporter;
		if (
			! $reporter->are_critical_errors()
			 && isset($settings['sources'])
			 && is_array($settings['sources'])
		) {
			foreach ($settings['sources'] as $source) {
				if (! empty($source['error'])) {
					\CustomFacebookFeed\Builder\CFF_Source::clear_error($source['account_id']);
				}
			}
		}

		if (! empty($new_post_sets)) {
			$next_pages = CFF_Shortcode::cff_get_next_url_parts($new_post_sets);
			if (! empty($next_pages) && $next_pages !== '{}') {
				$next_page_found = true;
			}
		}

		$posts = $this->merge_posts($new_post_sets, $settings);

		$posts = $this->filter_posts($posts, $settings);


		if (isset($posts[0])) {
			$one_post_found = true;
		} else {
			$next_page_found = false;
		}

		if (! empty($this->post_data) && is_array($this->post_data)) {
			$posts = array_merge($this->post_data, $posts);
		} elseif ($one_post_found) {
			$this->one_post_found = true;
		}

		$this->post_data = $posts;



		if (isset($next_page_found) && $next_page_found) {
			$this->next_pages = $next_pages;
		} else {
			$this->next_pages = false;
		}
	}

	public function set_next_pages($next_pages)
	{
		$this->next_pages = $next_pages;
	}

	private function merge_posts($post_sets, $settings)
	{
		$merged_posts = array();
		$settings['sortby'] = isset($settings['sortby']) ? $settings['sortby'] : 'date';

		$i = 0;
		foreach ($post_sets as $post_set) {
			$post_data = [];
			if (isset($post_set->data)) {
				$post_data = $post_set->data;
			} elseif (isset($post_set)) {
				$post_data = [$post_set];
			}
			if (
				isset($post_data[ $i ])
				 && (isset($post_data[ $i ]->id) || isset($post_data[ $i ]->created_time) )
			) {
				$merged_posts = array_merge($merged_posts, $post_data);
			}
			$i++;
		}


		return $merged_posts;
	}

	public function should_use_pagination($settings, $offset = 0)
	{
		if ($settings['minnum'] < 1) {
			return false;
		}
		$posts_available = count($this->post_data) - ($offset + $settings['num']);
		$show_loadmore_button_by_settings = ($settings['showbutton'] == 'on' || $settings['showbutton'] == 'true' || $settings['showbutton'] == true ) && $settings['showbutton'] !== 'false';

		if ($show_loadmore_button_by_settings) {
			if ($posts_available > 0) {
				$this->add_report('do pagination, posts available');
				return true;
			}
			$pages = $this->next_pages;

			if ($pages && ! $this->should_use_backup()) {
				foreach ($pages as $page) {
					if (! empty($page)) {
						return true;
					}
				}
			}
		}

		$this->add_report('no pagination, no posts available');

		return false;
	}

	public function add_report($to_add)
	{
		$this->report[] = $to_add;
	}

	public function get_report()
	{
		return $this->report;
	}

	protected function filter_posts($post_set, $settings = array())
	{

		if (isset($settings['filter'])) {
			$settings['includewords'] = $settings['filter'];
		}

		if (isset($settings['exfilter'])) {
			$settings['excludewords'] = $settings['exfilter'];
		}

		if (
			empty($settings['includewords'])
			 && empty($settings['excludewords'])
			 && empty($settings['whitelist'])
			 && empty($settings['hidephotos'])
		) {
			return $post_set;
		}

		$includewords = ! empty($settings['includewords']) ? explode(',', $settings['includewords']) : array();
		$excludewords = ! empty($settings['excludewords']) ? explode(',', $settings['excludewords']) : array();
		$hide_photos = ! empty($settings['hidephotos']) && empty($settings['doingModerationMode']) ? explode(',', str_replace(' ', '', $settings['hidephotos'])) : array();
		$white_list = false;
		$media_filter = false;

		$filtered_posts = array();
		foreach ($post_set as $post) {
			$keep_post = false;
			$caption = CFF_Parse::get_message($post);

			$padded_caption = ' ' . str_replace(array( '+', '%0A' ), ' ', urlencode(str_replace(array( '#', '@' ), array( ' HASHTAG', ' MENTION' ), strtolower($caption)))) . ' ';
			$id = CFF_Parse::get_post_id($post);

			$is_hidden = false;
			$passes_media_filter = true;
			if (
				! empty($hide_photos)
				 && (in_array($id, $hide_photos, true) || in_array('cff_' . $id, $hide_photos, true))
			) {
				$is_hidden = true;
				if ($white_list) {
					if (in_array($id, $white_list, true) || in_array('cff_' . $id, $white_list, true)) {
						$is_hidden = false;
					}
				}
			}

			if ($media_filter) {
				$media_type = '';
				if ($media_filter === 'videos') {
					if ($media_type !== 'video') {
						$passes_media_filter = false;
					}
				} else {
					if ($media_type === 'video') {
						$passes_media_filter = false;
					}
				}
			}

			// any blocked photos will not pass any additional filters so don't bother processing
			if (! $is_hidden && $passes_media_filter) {
				$is_on_white_list = false;
				$has_includeword = false;
				$has_excludeword = false;
				$passes_word_filter = false;

				if ($white_list) {
					if (in_array($id, $white_list, true) || in_array('cff_' . $id, $white_list, true)) {
						$is_on_white_list = true;
					}
				} elseif (! empty($includewords) || ! empty($excludewords)) {
					if (! empty($includewords)) {
						foreach ($includewords as $includeword) {
							if (! empty($includeword)) {
								$converted_includeword = trim(str_replace('+', ' ', urlencode(str_replace(array( '#', '@' ), array( ' HASHTAG', ' MENTION' ), strtolower($includeword)))));

								if (preg_match('/\b' . $converted_includeword . '\b/i', $padded_caption, $matches)) {
									$has_includeword = true;
								}
							}
						}
					}

					if (! empty($excludewords)) {
						foreach ($excludewords as $excludeword) {
							if (! empty($excludeword)) {
								$converted_excludeword = trim(str_replace('+', ' ', urlencode(str_replace(array( '#', '@' ), array( ' HASHTAG', ' MENTION' ), strtolower($excludeword)))));
								if (preg_match('/\b' . $converted_excludeword . '\b/i', $padded_caption, $matches)) {
									$has_excludeword = true;
								}
							}
						}
					}
					if (! empty($excludewords) && ! empty($includewords)) {
						$passes_word_filter = $has_includeword && ! $has_excludeword;
					} elseif (! empty($includewords)) {
						$passes_word_filter = $has_includeword;
					} else {
						$passes_word_filter = !$has_excludeword;
					}
				} else {
					// no other filters so it belongs in the feed
					$keep_post = true;
				}

				if ($is_on_white_list || $passes_word_filter) {
					$keep_post = true;
				}
			}

			$keep_post = apply_filters('cff_passes_filter', $keep_post, $post, $settings);
			if ($keep_post) {
				$filtered_posts[] = $post;
			}
		}

		return $filtered_posts;
	}

	protected function handle_no_posts_found($settings = array(), $feed_types_and_terms = array())
	{
	}

	protected function remove_duplicate_posts()
	{
		$posts = $this->post_data;
		$ids_in_feed = array();
		$non_duplicate_posts = array();
		$removed = array();

		foreach ($posts as $post) {
			$post_id = CFF_Parse::get_post_id($post);
			if (! in_array($post_id, $ids_in_feed, true)) {
				$ids_in_feed[] = $post_id;
				$non_duplicate_posts[] = $post;
			} else {
				$removed[] = $post_id;
			}
		}

		$this->add_report('removed duplicates: ' . implode(', ', $removed));
		$this->set_post_data($non_duplicate_posts);
	}
}
