<?php

use WPDRMS\ASL\Analytics\AnalyticsMigration;
use WPDRMS\ASL\Analytics\ORM\AnalyticsOptions;
use WPDRMS\ASL\Cache\ORM\CacheOptions;
use WPDRMS\ASL\Cache\ResultsCacheService;
use WPDRMS\ASL\Compatibility\ORM\CompatibilityOptions;
use WPDRMS\ASL\Statistics\StatisticsService;

if ( !defined('ABSPATH') ) {
	die("You can't access this file directly.");
}

/**
 * Class WD_ASL_init
 *
 * AJAX SEARCH Lite initializator Class
 */
class WD_ASL_Init {

	/**
	 * Core singleton class
	 *
	 * @var WD_ASL_Init self
	 */
	private static $_instance;

	private function __construct() {
		wd_asl()->db = WD_ASL_DBMan::getInstance();
	}

	/**
	 * Runs on activation
	 */
	public function activate() {

		WD_ASL_DBMan::getInstance()->create();
		ResultsCacheService::instance()->create();
		StatisticsService::instance()->createTables();

		$this->chmod();
		$this->backwards_compatibility_fixes();

		/**
		 * Store the version number after everything is done. This is going to help distinguishing
		 * stored asl_version from the ASL_CURR_VER variable. These two are different in cases:
		 *  - Uninstalling, installing new versions
		 *  - Uploading and overwriting old version with a new one
		 */
		update_option('asl_version', ASL_CURRENT_VERSION);
	}

	/**
	 *  Checks if the user correctly updated the plugin and fixes if not
	 */
	public function safety_check() {
		$curr_stored_ver = get_option('asl_version', 0);
		// Run the re-activation actions if this is actually a newer version
		if ( intval($curr_stored_ver) !== ASL_CURRENT_VERSION ) {
			$this->activate();
		}
	}

	/**
	 * Fix known backwards incompatibilities
	 */
	public function backwards_compatibility_fixes() {
		AnalyticsMigration::run();
		\WPDRMS\ASL\Compatibility\CompatibilityMigration::run();

		/*
		 * - Get instances
		 * - Check options
		 * - Transition to new options based on old ones
		 * - Save instances
		 */
		foreach ( wd_asl()->instances->get() as $si ) {
			$sd = $si['data'];

			// ------------------------- 4.13.2 -----------------------------
			if ( isset($sd['custom_css']) && $sd['custom_css'] !== '' ) {
				/**
				 * Old custom CSS field was stored as base64 encoded string.
				 * Here it's migrated to a non-encoded field.
				 */
				$decoded = base64_decode($sd['custom_css']); // phpcs:ignore
				if ( $decoded !== false ) {
					$sd['custom_css_code'] = $decoded;
				}
				unset($sd['custom_css']);
			}

			// ------------------------- 4.7.3 -----------------------------
			// Primary and secondary fields
			$values     = array( '-1', '0', '1', '2', 'c__f' );
			$adv_fields = array(
				'titlefield',
				'descriptionfield',
			);
			foreach ( $adv_fields as $field ) {
				// Force string conversion for proper comparision
				if ( isset($sd[ $field ]) && !in_array($sd[ $field ] . '', $values, true) ) {
					// Custom field value is selected
					$sd[ $field . '_cf' ] = $sd[ $field ];
					$sd[ $field ]         = 'c__f';
				}
			}

			// ------------------------- 4.12.8 -----------------------------

			foreach ( array(
				'advtitlefield',
				'advdescriptionfield',
			) as $fk
			) {
				$sd[ $fk ] = str_replace(
					array( '{titlefield}', '{descriptionfield}' ),
					array( "{result_field field_name='title' hash='x'}", "{result_field field_name='content' hash='y'}" ),
					$sd[ $fk ]
				);
			}

			// ------------------------- 4.7.13 -----------------------------
			if ( isset($sd['redirectonclick']) ) {
				if ( !$sd['redirectonclick'] ) {
					$sd['click_action'] = 'ajax_search';
				}
				unset($sd['redirectonclick']);
			}
			if ( isset($sd['redirect_on_enter']) ) {
				if ( !$sd['redirect_on_enter'] ) {
					$sd['return_action'] = 'ajax_search';
				}
				unset($sd['redirect_on_enter']);
			}
			// ------------------------- 4.7.14 -----------------------------
			if ( isset($sd['triggeronclick']) ) {
				unset($sd['triggeronclick']);
			}

			// ------------------------- 4.7.15 -----------------------------
			// Before, this was a string
			if ( isset($sd['customtypes']) && !is_array($sd['customtypes']) ) {
				$sd['customtypes'] = explode('|', $sd['customtypes']);
				foreach ( $sd['customtypes'] as $ck => $ct ) {
					if ( $ct === '' ) {
						unset($sd['customtypes'][ $ck ]);
					}
				}
			}
			// No longer exists
			if ( isset($sd['selected-customtypes']) ) {
				unset($sd['selected-customtypes']);
			}
			// No longer exists
			if ( isset($sd['searchinpages']) ) {
				if ( $sd['searchinpages'] && !in_array('page', $sd['customtypes'], true) ) {
					array_unshift($sd['customtypes'], 'page');
				}
				unset($sd['searchinpages']);
			}
			// No longer exists
			if ( isset($sd['searchinposts']) ) {
				if ( $sd['searchinposts'] && !in_array('post', $sd['customtypes'], true) ) {
					array_unshift($sd['customtypes'], 'post');
				}
				unset($sd['searchinposts']);
			}

			// ------------------------- 4.18.1 -----------------------------
			// For non-existence checks use the raw_data array
			if ( !isset($si['raw_data']['box_width_tablet']) ) {
				$sd['box_width_tablet'] = $sd['box_width'];
				$sd['box_width_phone']  = $sd['box_width'];
			}

			// ------------------------- 4.8.7 -----------------------------
			// No longer exists
			if ( isset($sd['showsearchinpages']) ) {
				if ( $sd['showsearchinpages'] ) {
					if ( $sd['showcustomtypes'] === '' ) {
						$sd['showcustomtypes'] = 'page;' . $sd['searchinpagestext'];
					} else {
						$sd['showcustomtypes'] = 'page;' . $sd['searchinpagestext'] . '|' . $sd['showcustomtypes'];
					}
				}
				unset($sd['showsearchinpages']);
				unset($sd['searchinpagestext']);
			}
			// No longer exists
			if ( isset($sd['showsearchinposts']) ) {
				if ( $sd['showsearchinposts'] ) {
					if ( $sd['showcustomtypes'] === '' ) {
						$sd['showcustomtypes'] = 'post;' . $sd['searchinpoststext'];
					} else {
						$sd['showcustomtypes'] = 'post;' . $sd['searchinpoststext'] . '|' . $sd['showcustomtypes'];
					}
				}
				unset($sd['showsearchinposts']);
				unset($sd['searchinpoststext']);
			}

			if ( isset($sd['titlefield']) ) {
				$sd['primary_titlefield']    = $sd['titlefield'];
				$sd['primary_titlefield_cf'] = $sd['titlefield_cf'];
				unset($sd['titlefield']);
				unset($sd['titlefield_cf']);
			}

			if ( isset($sd['descriptionfield']) ) {
				$sd['primary_descriptionfield']    = $sd['descriptionfield'];
				$sd['primary_descriptionfield_cf'] = $sd['descriptionfield_cf'];
				unset($sd['descriptionfield']);
				unset($sd['descriptionfield_cf']);
			}

			if ( isset($sd['redirect_enter_to']) ) {
				$sd['return_action'] = $sd['redirect_enter_to'];
				$sd['click_action']  = $sd['redirect_click_to'];
				unset($sd['redirect_enter_to']);
				unset($sd['redirect_click_to']);
			}

			// At the end, update
			wd_asl()->instances->update(0, $sd);
		}
	}


	/**
	 * Extra styles if needed..
	 */
	public function styles() {}

	/**
	 * Prints the scripts
	 *
	 * @noinspection PhpInconsistentReturnPointsInspection
	 */
	public function scripts() {
		wd_asl()->scripts = WD_ASL_Scripts::getInstance();

		$exit1 = apply_filters('asl_load_css_js', false);
		$exit2 = apply_filters('asl_load_js', false);
		if ( $exit1 || $exit2 ) {
			return false;
		}

		$opts           = CompatibilityOptions::instance();
		$load_in_footer = $opts->load_in_footer->value;
		$media_query         = ASL_DEBUG ? asl_gen_rnd_str() : ASL_CURRENT_VERSION;
		if ( wd_asl()->manager->getContext() === 'backend' ) {
			$js_minified   = false;
			$js_optimized  = true;
			$js_async_load = false;
		} else {
			$js_minified   = $opts->js_source->value === 'jqueryless-min';
			$js_optimized  = $opts->script_loading_method->value !== 'classic';
			$js_async_load = $opts->script_loading_method->value === 'optimized_async';
		}

		$single_highlight     = false;
		$single_highlight_arr = array();
		$search               = wd_asl()->instances->get();
		if ( is_array($search) && count($search) >0 ) {
			foreach ( $search as $s ) {
				// $style and $id needed in the include
				if ( $s['data']['single_highlight'] ) {
					$single_highlight       = true;
					$single_highlight_arr[] = array(
						'selector'      => $s['data']['single_highlight_selector'],
						'scroll'        => boolval($s['data']['single_highlight_scroll']),
						'scroll_offset' => intval($s['data']['single_highlight_offset']),
						'whole'         => boolval($s['data']['single_highlightwholewords']),
						'minWordLength' => intval($s['data']['min_word_length']),
					);
				}
			}
		}

		$ajax_url = admin_url('admin-ajax.php');
		if ( $opts->use_custom_ajax_handler->value ) {
			$ajax_url = ASL_URL . 'ajax_search.php';
		}

		$handle = 'wd-asl-ajaxsearchlite';
		if ( !$js_async_load ) {
			wd_asl()->scripts->enqueue(
				wd_asl()->scripts->get(
					array(),
					$js_minified,
					$js_optimized,
					array(
						'wd-asl-prereq-and-wrapper',
						'wd-asl-ajaxsearchlite-load-async',
					)
				),
				array(
					'media_query' => $media_query,
					'in_footer'   => $load_in_footer,
				)
			);
			$additional_scripts = array();
		} else {
			$handle = 'wd-asl-prereq-and-wrapper';
			wd_asl()->scripts->enqueue(
				wd_asl()->scripts->get($handle, $js_minified, $js_optimized),
				array(
					'media_query' => $media_query,
					'in_footer'   => $load_in_footer,
				)
			);
			$additional_scripts = wd_asl()->scripts->get(
				array(),
				$js_minified,
				$js_optimized,
				array(
					'wd-asl-async-loader',
					'wd-asl-prereq-and-wrapper',
					'wd-asl-ajaxsearchlite-wrapper',
					'wd-asl-ajaxsearchlite-prereq',
				)
			);
		}

		ASL_Helpers::addInlineScript(
			$handle,
			'ASL',
			array(
				'wp_rocket_exception'   => 'DOMContentLoaded',    // WP Rocket hack to prevent the wrapping of the inline script: https://docs.wp-rocket.me/article/1265-load-javascript-deferred
				'ajaxurl'               => $ajax_url,
				'backend_ajaxurl'       => admin_url('admin-ajax.php'),
				'asl_url'               => ASL_URL,
				'rest_url'              => apply_filters('asl/rest/base_url/', rest_url()),
				'detect_ajax'           => $opts->detect_ajax->value,
				'media_query'           => ASL_CURRENT_VERSION,
				'version'               => ASL_CURRENT_VERSION,
				'pageHTML'              => '',
				'additional_scripts'    => $additional_scripts,
				'script_async_load'     => $js_async_load,
				'init_only_in_viewport' => $opts->init_instances_inviewport_only->value,
				'font_url'              => str_replace('http:', '', plugins_url()) . '/ajax-search-lite/css/fonts/icons2.woff2',
				'highlight'             => array(
					'enabled' => $single_highlight,
					'data'    => $single_highlight_arr,
				),
				'analytics'             => ( function () {
					$ao = AnalyticsOptions::instance();
					return array(
						'method'      => $ao->method->value,
						'tracking_id' => $ao->tracking_id->value,
						'event'       => array(
							'focus'        => array( 'items' => $ao->focus->items ),
							'search_start' => array( 'items' => $ao->search_start->items ),
							'search_end'   => array( 'items' => $ao->search_end->items ),
							'magnifier'    => array( 'items' => $ao->magnifier->items ),
							'return'       => array( 'items' => $ao->return->items ),
							'facet_change' => array( 'items' => $ao->facet_change->items ),
							'result_click' => array( 'items' => $ao->result_click->items ),
						),
					);
				} )(),
				'statistics'            => array(
					'enabled' => StatisticsService::instance()->options->status->value,
					'uid'     => get_current_user_id(),
				),
				'cache'                 => array(
					'enabled' => CacheOptions::instance()->status->value,
					'type'    => CacheOptions::instance()->cache_type->value,
					'list'    => array(),
					'url'     => ResultsCacheService::instance()->resultsCacheUrl(),
				),
			),
			'before',
			true
		);

		add_action(
			'wp_print_footer_scripts',
			function () use ( $handle ) {
				$script_data = wd_asl()->instances->get_script_data();
				if ( count($script_data) > 0 ) {
					$script = 'window.ASL_INSTANCES = [];';
					foreach ( $script_data as $id => $data ) {
						$script .= "window.ASL_INSTANCES[$id] = $data;";
					}
					wp_add_inline_script($handle, $script, 'before');
				}
			},
			0
		);
	}

	public function pluginReset( $trigger_activate = true ) {
		$options = array(
			'asl_version',
			'asl_glob_d',
			'asl_performance_def',
			'asl_performance',
			'asl_analytics_def',
			'asl_analytics',
			'asl_caching_def',
			'asl_caching',
			'asl_compatibility_def',
			'asl_compatibility',
			'asl_compatibility_options',
			'asl_defaults',
			'asl_st_override',
			'asl_woo_override',
			'asl_stat',
			'asl_updates',
			'asl_updates_lc',
			'asl_performance_stats',
			'asl_recently_updated',
			'asl_debug_data',
		);
		foreach ( $options as $o ) {
			delete_option($o);
		}

		if ( $trigger_activate ) {
			$this->activate();
		}
	}

	public function pluginWipe() {
		// Options
		$this->pluginReset( false );

		// Additional options
		$options = array(
			'asl_options',
			'asl_version',
			'asl_debug_data',
		);
		foreach ( $options as $o ) {
			delete_option($o);
		}

		// Database
		wd_asl()->db->delete();
		StatisticsService::instance()->dropTables();

		// Deactivate
		deactivate_plugins(ASL_FILE);
	}


	/**
	 *  Tries to chmod the CSS and CACHE directories
	 */
	public function chmod() {
		// Nothing to do here yet :)
	}


	/**
	 *  If anything we need in the footer
	 */
	public function footer() {
	}

	/**
	 * Get the instane
	 *
	 * @return self
	 */
	public static function getInstance() {
		if ( !( self::$_instance instanceof self ) ) {
			self::$_instance = new self();
		}

		return self::$_instance;
	}
}
