<?php
/**
 * Elite Notification Source Modules
 *
 * @package Elite_Notification_Lite\Modules
 */

namespace Elite_Notification_Lite\Modules;

use Appsbd_Lite\V4\libs\Ajax_Confirm_Response;
use Appsbd_Lite\V4\libs\Ajax_Data_Response;
use Appsbd_Lite\V4\libs\AppInput;
use Elite_Notification_Lite\Core\Elite_Notification_Lite;
use Elite_Notification_Lite\Core\Elite_Notification_Module_Lite;
use Elite_Notification_Lite\Libs\Elite_Notification_Source_Base;
use Elite_Notification_Lite\Libs\Elite_Notification_Source_Item;
use Elite_Notification_Lite\Models\Database\Mapbd_Dummy_Notification;
use Elite_Notification_Lite\Source\Ens_Comment_Source;
use Elite_Notification_Lite\Source\Ens_Easy_Digital_Downloads;
use Elite_Notification_Lite\Source\Ens_Elearning;
use Elite_Notification_Lite\Source\Ens_Elite_Licenser_Source;
use Elite_Notification_Lite\Source\Ens_Envato_Source;
use Elite_Notification_Lite\Source\Ens_Fast_Spring;
use Elite_Notification_Lite\Source\Ens_Give_Donation;
use Elite_Notification_Lite\Source\Ens_Review_X;
use Elite_Notification_Lite\Source\Ens_Woocommerce_Source;
use Elite_Notification_Lite\Source\Ens_Wordpress_Download_Stats;
use Elite_Notification_Lite\Source\Ens_Wp_Review;

if ( ! defined( 'ABSPATH' ) ) {
	exit;
}

/**
 * Class Elite_Notification_Source
 *
 * @package Elite_Notification_Lite\Modules
 */
class Elite_Notification_Source extends Elite_Notification_Module_Lite {
	/**
	 * Its property source
	 *
	 * @var array
	 */
	private static $sources = array();
	/**
	 * Its property sources_categories
	 *
	 * @var array
	 */
	private static $sources_categories = array();

	/**
	 * The initialize is generated by appsbd
	 */
	public function initialize() {
		add_action( 'wp_ajax_slnf-update-source', array( $this, 'cron_update_source' ) );
		add_action( 'wp_ajax_nopriv_slnf-update-source', array( $this, 'cron_update_source' ) );

		add_action( 'apbd-sales-notification/before-load-source', array( $this, 'before_load_source' ), 1 );
		add_action( 'apbd-sales-notification/add-source', array( $this, 'load_source' ), 1 );

		add_filter( 'appsbd-slnf-source-category', array( $this, 'load_categories' ) );
		/**
		 * Its for check is there any change before process
		 *
		 * @since 1.0
		 */
		do_action( 'apbd-sales-notification/before-load-source' );
		if ( ! isset( $this->options['global_view'] ) ) {
			$this->options['global_view'] = 0;
		}
		if ( ! isset( $this->options['global_click'] ) ) {
			$this->options['global_click'] = 0;
		}
	}

	/**
	 * The on init is generated by appsbd
	 */
	public function on_init() {
		parent::on_init();

		if ( version_compare(
			Elite_Notification_Lite::get_instance()->plugin_version,
			'2.0.0',
			'>='
		) && get_option( 'elite-notification_o_APBD_notification_source' ) ) {
			$options = get_option( 'elite-notification_o_APBD_notification_source' );
			if ( ! empty( $options['sources'] ) ) {
				$sources = $options['sources'];
				$sources = maybe_unserialize( $sources );
				$sources = json_decode( json_encode( $sources ) );
				if ( is_array( $sources ) ) {
					$updated_sources = array();
					foreach ( $sources as $source ) {
						if ( is_object( $source ) && property_exists(
							$source,
							'__PHP_Incomplete_Class_Name'
						) && 'Apbd_notification_source_item' == $source->__PHP_Incomplete_Class_Name ) {
							$new_object = new Elite_Notification_Source_Item();
							foreach ( get_object_vars( $source ) as $property => $value ) {
								if ( property_exists( $new_object, $property ) ) {
									if ( 'source_params' == $property ) {
										$value = (array) $value;
									}
									$new_object->$property = $value;
								}
							}
							$updated_sources[] = $new_object;
						} else {
							$updated_sources[] = $source;
						}
					}
					$this->options['sources'] = $updated_sources;
				}

				if ( ! empty( $options['global_view'] ) ) {
					$this->options['global_view'] = $options['global_view'];
				}
				if ( ! empty( $options['global_click'] ) ) {
					$this->options['global_click'] = $options['global_click'];
				}
			}
			if ( $this->update_option() ) {
				delete_option( 'elite-notification_o_APBD_notification_source' );
			}
		}

		$this->add_admin_ajax_action( 'add', array( $this, 'add' ) );
		$this->add_admin_ajax_action( 'edit', array( $this, 'edit' ) );
		$this->add_admin_ajax_action( 'details', array( $this, 'details' ) );
		$this->add_admin_ajax_action( 'delete-item', array( $this, 'delete_item' ) );
		$this->add_admin_ajax_action( 'status-change', array( $this, 'status_change' ) );
		/**
		 * Its for check is there any change before process
		 *
		 * @since 1.0
		 */
		do_action( 'apbd-sales-notification/add-source' );
		/**
		 * Its for check is there any change before process
		 *
		 * @since 1.0
		 */
		self::$sources_categories = apply_filters( 'appsbd-slnf-source-category', array() );

		add_filter( 'cron_schedules', array( $this, 'cron_time_intervals' ) );
		add_action( 'appsbd-slnf-load-source-item', array( $this, 'load_source_item' ) );
		add_action( 'appsbd-slnf-load-source-internally', array( $this, 'load_source_internally' ) );
		if ( Elite_Notification_Settings::get_module_instance( 'corn_type', 'W' ) == 'W' ) {
			$this->set_schedule();
		} else {
			$this->schedule_deactivate();
		}
		$is_queue = get_transient( '__slnf_load_requrie' );
		if ( ! empty( $is_queue ) && 'Y' == $is_queue ) {
			$this->load_source_internally();
			delete_transient( '__slnf_load_requrie' );
		}
	}

	/**
	 * The on plugin version updated is generated by appsbd
	 *
	 * @param mixed $current_version It is current_version param.
	 * @param mixed $previous_version It is previous_version param.
	 */
	public function on_plugin_version_updated( $current_version, $previous_version ) {
		if ( version_compare( $current_version, '2.0.0', '>=' ) ) {
			$updated_sources = get_option( 'elite-notification_o_APBD_notification_source' );
			if ( ! empty( $updated_sources ) ) {
				$this->options = $updated_sources;
				if ( $this->update_option() ) {
					delete_option( 'elite-notification_o_APBD_notification_source' );
				}
			}
		}
	}

	/**
	 * The load categories is generated by appsbd
	 *
	 * @param mixed $categories It is categories param.
	 *
	 * @return mixed
	 */
	public function load_categories( $categories ) {
		$categories['sales']          = $this->__( 'Sales' );
		$categories['comment']        = $this->__( 'Comment' );
		$categories['review']         = $this->__( 'Review' );
		$categories['download_stats'] = $this->__( 'Download Stats' );
		$categories['elearning']      = $this->__( 'eLearning' );
		$categories['donation']       = $this->__( 'Donation' );

		return $categories;
	}

	/**
	 * The set load queue is generated by appsbd
	 */
	public static function set_load_queue() {
		set_transient( '__slnf_load_requrie', 'Y' );
	}

	/**
	 * The set schedule is generated by appsbd
	 */
	public function set_schedule() {
		if ( ! wp_next_scheduled( 'appsbd-slnf-load-source-item', array( 'W' ) ) ) {
			wp_schedule_event( time(), 'apbd_slnf_cron', 'appsbd-slnf-load-source-item', array( 'W' ) );
		}
	}

	/**
	 * The schedule deactivate is generated by appsbd
	 */
	public function schedule_deactivate() {
		wp_clear_scheduled_hook( 'appsbd-slnf-load-source-item', array( 'W' ) );
	}

	/**
	 * The cron update source is generated by appsbd
	 */
	public function cron_update_source() {
		$this->load_source_item( 'C' );
		exit;
	}

	/**
	 * The on deactivate is generated by appsbd
	 */
	public function on_deactivate() {
		parent::on_deactivate();
		$this->schedule_deactivate();
	}

	/**
	 * The before load source is generated by appsbd
	 */
	public function before_load_source() {
		Ens_Easy_Digital_Downloads::set_edd_actions();
	}

	/**
	 * The load source is generated by appsbd
	 */
	public function load_source() {
		self::add_source( new Ens_Elite_Licenser_Source() );
		self::add_source( new Ens_Woocommerce_Source() );
		self::add_source( new Ens_Envato_Source() );
		self::add_source( new Ens_Easy_Digital_Downloads() );
		self::add_source( new Ens_Fast_Spring() );
		self::add_source( new Ens_Comment_Source() );
		self::add_source( new Ens_Wp_Review() );
		self::add_source( new Ens_Review_X() );
		self::add_source( new Ens_Elearning() );
		self::add_source( new Ens_Wordpress_Download_Stats() );
		self::add_source( new Ens_Give_Donation() );
	}

	/**
	 * The add source category is generated by appsbd
	 *
	 * @param mixed $id It is id param.
	 * @param mixed $title It is title param.
	 */
	public function add_source_category( $id, $title ) {
		self::$sources_categories[ $id ] = $this->__( $title );
	}

	/**
	 * The get all source categories is generated by appsbd
	 *
	 * @return array
	 */
	public function get_all_source_categories() {
		return self::$sources_categories;
	}

	/**
	 * The cron time intervals is generated by appsbd
	 *
	 * @param mixed $schedules It is schedules param.
	 *
	 * @return mixed
	 */
	public function cron_time_intervals( $schedules ) {
		$time_value          = (int) Elite_Notification_Settings::get_module_option( 'source_update_time_val' );
		$time_type           = strtoupper(
			Elite_Notification_Settings::get_module_option(
				'source_update_time_type',
				'M'
			)
		);
		$time_value_interval = 0;
		if ( 'D' == $time_type ) {
			$time_value_interval = DAY_IN_SECONDS;
		} elseif ( 'H' == $time_type ) {
			$time_value_interval = HOUR_IN_SECONDS;
		} elseif ( 'M' == $time_type ) {
			$time_value_interval = MINUTE_IN_SECONDS;
		}

		$schedules['apbd_slnf_cron'] = array(
			'interval' => $time_value * $time_value_interval,
			'display'  => 'As Per Appsbd Sales Notification Settings',
		);

		return $schedules;
	}

	/**
	 * The update or add source run log is generated by appsbd
	 *
	 * @param mixed $source_type It is source_type param.
	 */
	public function update_or_add_source_run_log( $source_type ) {
		$source_type_str = 'Unknown';
		if ( 'W' == $source_type ) {
			$source_type_str = 'WP Scheduler';
		} elseif ( 'C' == $source_type ) {
			$source_type_str = 'Cronjob';
		} elseif ( 'M' == $source_type ) {
			$user_info = wp_get_current_user();
			$name      = $this->__( 'Admin' );
			if ( ! empty( $user_info ) ) {
				$name = $user_info->display_name;
			}
			$source_type_str = $name;
		}
		$fild                 = new \stdClass();
		$fild->source_type    = $source_type_str;
		$fild->execution_time = gmdate( 'Y-m-d H:i:s' );
		update_option( '_appsbd_slnf_sulog', $fild ) || add_option( '_appsbd_slnf_sulog', $fild );
	}

	/**
	 * The get source update log msg is generated by appsbd
	 *
	 * @return mixed
	 */
	public static function get_source_update_log_msg() {
		$ops = get_option( '_appsbd_slnf_sulog', null );
		if ( empty( $ops ) || empty( $ops->source_type ) || empty( $ops->execution_time ) ) {
			return self::get_module_instance()->__( 'Not executed yet' );
		} else {
			return self::get_module_instance()->__(
				'Source update by %s %s at %s',
				$ops->source_type,
				'<br/>',
				appsbd_get_wp_datetime_with_format( $ops->execution_time )
			);
		}
	}

	/**
	 * The load source internally is generated by appsbd
	 */
	public function load_source_internally() {
		Elite_Notification_Settings::clear_notification_list();
		$sources = self::get_all_sources_data();
		foreach ( $sources as $key => $source_data ) {
			if ( 'A' != $source_data->status ) {
				continue;
			}
			$source = self::get_sources_id( $source_data->source_type );
			if ( $source instanceof Elite_Notification_Source_Base ) {
				$source_data->id = $key + 1;
				$source->set_params( $source_data );
				$items = $source->get_items( $source_data );
				if ( ! empty( $items ) && is_array( $items ) ) {
					Elite_Notification_Settings::get_module_instance()->add_notification_item_list( $items );
				}
			}
		}
	}

	/**
	 * The load source item is generated by appsbd
	 *
	 * @param string $source_type It is source_type param.
	 */
	public function load_source_item( $source_type = '' ) {
		$this->update_or_add_source_run_log( $source_type );
		$this->load_source_internally();
	}

	/**
	 * The save source item data is generated by appsbd
	 *
	 * @param mixed $data It is data param.
	 *
	 * @return mixed
	 */
	public function save_source_item_data( $data ) {
		if ( ! isset( $this->options['sources'] ) ) {
			$this->options['sources'] = array();
		}
		$this->options['sources'][] = $data;

		return $this->update_option();
	}

	/**
	 * The get all sources is generated by appsbd
	 *
	 * @return Elite_Notification_Source_Base []
	 */
	public static function get_all_sources() {
		/**
		 * Its for check is there any change before process
		 *
		 * @since 1.0
		 */
		return apply_filters( 'appsbd-slnf-source-list', self::$sources );
	}

	/**
	 * The get all sources is generated by appsbd
	 *
	 * @return array
	 */
	public static function get_all_sources_client_settings() {
		$sources         = self::get_all_sources();
		$client_settings = array();
		foreach ( $sources as $source ) {
			$client_settings[] = $source->get_client_settings();
		}

		return $client_settings;
	}

	/**
	 * The get all sources data is generated by appsbd
	 *
	 * @return mixed|string
	 */
	public static function get_all_sources_data() {
		return self::get_module_option( 'sources', array() );
	}

	/**
	 * The get sources id is generated by appsbd
	 *
	 * @param mixed $id It is id param.
	 *
	 * @return mixed|\stdClass
	 */
	public static function &get_sources_id( $id ) {
		if ( isset( self::$sources[ $id ] ) ) {
			return self::$sources[ $id ];
		}

		return new \stdClass();
	}

	/**
	 * The add source is generated by appsbd
	 *
	 * @param mixed $obj It is obj param.
	 */
	public static function add_source( $obj ) {
		if ( $obj instanceof Elite_Notification_Source_Base && ! empty( $obj->id ) ) {
			self::$sources[ $obj->id ] = $obj;
		}
	}

	/**
	 * The increase global view is generated by appsbd
	 *
	 * @param bool $is_db_update It is is_db_update param.
	 */
	public static function increase_global_view( $is_db_update = true ) {
		$obj = self::get_module_instance();
		++$obj->options['global_view'];
		if ( $is_db_update ) {
			$obj->update_option();
		}
	}

	/**
	 * The increase global click is generated by appsbd
	 *
	 * @param bool $is_db_update It is is_db_update param.
	 */
	public static function increase_global_click( $is_db_update = true ) {
		$obj = self::get_module_instance();
		++$obj->options['global_click'];
		if ( $is_db_update ) {
			$obj->update_option();
		}
	}

	/**
	 * The increase view is generated by appsbd
	 *
	 * @param mixed $id It is id param.
	 * @param bool  $is_db_update It is is_db_update param.
	 */
	public static function increase_view( $id, $is_db_update = true ) {
		$obj = self::get_module_instance();
		$pre = substr( $id, 0, 1 );
		if ( strtolower( $pre ) == 'd' ) {
			self::increase_global_view( false );
			Mapbd_Dummy_Notification::increase_view( $id );
		} else {
			self::increase_global_view( false );

			if ( ! empty( $obj->options['sources'][ $id - 1 ] ) ) {
				$source = &$obj->options['sources'][ $id - 1 ];
				if ( $source instanceof Elite_Notification_Source_Item ) {
					++$source->view_counter;
				}
			}
		}
		if ( $is_db_update ) {
			$obj->update_option();
		}
	}

	/**
	 * The increase click is generated by appsbd
	 *
	 * @param mixed $id It is id param.
	 * @param bool  $is_db_update It is is_db_update param.
	 */
	public static function increase_click( $id, $is_db_update = true ) {
		$obj = self::get_module_instance();
		$pre = substr( $id, 0, 1 );
		if ( strtolower( $pre ) == 'd' ) {
			self::increase_global_click( false );
			Mapbd_dummy_notification::increase_click( $id );
		} else {
			self::increase_global_click( false );
			if ( ! empty( $obj->options['sources'][ $id - 1 ] ) ) {
				$source = &$obj->options['sources'][ $id - 1 ];
				if ( $source instanceof Elite_Notification_Source_Item ) {
					++$source->click_counter;
				}
			}
		}
		if ( $is_db_update ) {
			$obj->update_option();
		}
	}

	/**
	 * The add is generated by appsbd
	 */
	public function add() {
		$response = new Ajax_Confirm_Response();
		if ( APPSBD_IS_POST_BACK ) {
			$nobject = new Elite_Notification_Source_Item();
			if ( $nobject->set_from_post_data() ) {
				if ( $this->save_source_item_data( $nobject ) ) {
					$this->add_info( 'Successfully added' );
					$this->load_source_internally();
					$response->display_with_response( true );

					return;
				} else {
					$this->add_error( 'Failed to save' );
					$response->display_with_response( false );

					return;
				}
			}
		}
		$response->display_with_response( false );
	}

	/**
	 * The edit is generated by appsbd
	 */
	public function edit() {
		$response = new Ajax_Confirm_Response();
		$param_id = AppInput::post_value( 'id' );
		if ( empty( $param_id ) || empty( $this->options['sources'][ $param_id - 1 ] ) ) {
			$this->add_error( 'Invalid request' );
			$response->display_with_response( false );

			return;
		}
		$mainobj =& $this->options['sources'][ $param_id - 1 ];
		if ( APPSBD_IS_POST_BACK ) {
			if ( $mainobj->set_from_post_data() ) {
				if ( $this->update_option() ) {
					$this->load_source_internally();
					$this->add_info( 'Successfully updated' );
					$response->display_with_response( true );

					return;
				} else {
					$this->add_error( 'Failed to update' );
					$response->display_with_response( false );

					return;
				}
			}
		}
		$response->display_with_response( false );
	}

	/**
	 * The details is generated by appsbd
	 */
	public function details() {
		$response = new Ajax_Confirm_Response();
		$param_id = AppInput::post_value( 'id' );
		if ( empty( $param_id ) || empty( $this->options['sources'][ $param_id - 1 ] ) ) {
			$this->add_error( 'Invalid request' );
			$response->display_with_response( false );

			return;
		}
		$mainobj =& $this->options['sources'][ $param_id - 1 ];
		if ( ! empty( $mainobj ) ) {
			$response->display_with_response( true, $mainobj );
		} else {
			$this->add_error( 'No source found with this id' );
			$response->display_with_response( false );
		}
	}

	/**
	 * The delete item is generated by appsbd
	 */
	public function delete_item() {
		$main_response = new Ajax_Confirm_Response();
		$param_id      = AppInput::post_value( 'id' );
		if ( empty( $param_id ) || empty( $this->options['sources'][ $param_id - 1 ] ) ) {
			$this->add_error( 'Delete failed try again' );
			$main_response->display_with_response( false );

			return;
		}
		unset( $this->options['sources'][ $param_id - 1 ] );
		$this->options['sources'] = array_values( $this->options['sources'] );
		if ( $this->update_option() ) {
			$this->add_info( 'Successfully deleted' );
			$main_response->display_with_response( true );
		} else {
			$this->add_error( 'Delete failed try again' );
			$main_response->display_with_response( false );
		}
	}

	/**
	 * The data is generated by appsbd
	 */
	public function data() {
		$main_response = new Ajax_Data_Response();
		$main_response->set_download_filename( 'apbd-dummy-notification-list' );
		$main_obje      = new Elite_Notification_Source_Item();
		$all_categories = $this->get_all_source_categories();
		if ( isset( $this->options['sources'] ) ) {
			$main_response->set_grid_records( count( $this->options['sources'] ) );
			$result = $this->options['sources'];
			if ( $result ) {

				foreach ( $result as $key => &$data ) {
					$source_obje           = self::get_sources_id( $data->source_type );
					$data->id              = $key + 1;
					$data->source_name     = ! empty( $source_obje ) ? $source_obje->source_name : '-';
					$data->source_category = appsbd_get_text_by_key( $data->source_category, $all_categories );

					/**
					 * Its for check is there any change before process
					 *
					 * @since 1.0
					 */
					$data = apply_filters( 'slnf_source_grid_item', $data );
					unset( $data->source_params );
				}
			}
			$main_response->set_grid_data( $result );
		}
		$main_response->display_grid_response();
	}

	/**
	 * The status change is generated by appsbd
	 */
	public function status_change() {
		$main_response = new Ajax_Confirm_Response();
		$param_id      = AppInput::post_value( 'id' );
		if ( empty( $param_id ) || empty( $this->options['sources'][ $param_id - 1 ] ) ) {
			$this->add_error( 'Update failed try again' );
			$main_response->display_with_response( false );

			return;
		}
		$mainobj =& $this->options['sources'][ $param_id - 1 ];

		$mainobj->status = 'I' == $mainobj->status ? 'A' : 'I';
		if ( $this->update_option() ) {
			$this->add_info( 'Successfully status changed' );
			$main_response->display_with_response( true );
		} else {
			$this->add_error( 'Change status process failed' );
			$main_response->display_with_response( false );
		}
	}
}
