<?php

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

if ( ! class_exists( 'DLM_DB_Upgrader' ) ) {

	/**
	 * DLM_DB_Upgrader
	 */
	class DLM_DB_Upgrader {

		/**
		 * Holds the class object.
		 *
		 * @since 4.6.0
		 *
		 * @var object
		 */
		public static $instance;

		/**
		 * Class constructor
		 *
		 * @return void
		 * @since 4.6.0
		 */
		public function __construct() {

			// We need to add this because there are scenarios where the user deleted the download_log table.
			add_action( 'admin_init', array( $this, 'check_upgrade_necessity' ), 15, 1 );
		}

		/**
		 * Returns the singleton instance of the class.
		 *
		 * @return object The DLM_Admin_Helper object.
		 * @since 4.6.0
		 */
		public static function get_instance() {

			if ( ! isset( self::$instance ) && ! ( self::$instance instanceof DLM_DB_Upgrader ) ) {
				self::$instance = new DLM_DB_Upgrader();
			}

			return self::$instance;

		}

		/**
		 * Automatically recreate the upgrade environment if the download_log is not present
		 *
		 * @return false|void
		 */
		public function check_upgrade_necessity() {
			// Filter to allow disabling the upgrade process.
			if ( ! apply_filters( 'dlm_do_upgrade', false ) ) {
				return;
			}
			global $wpdb;
			if ( ! DLM_Utils::table_checker( $wpdb->download_log ) ) {
				DLM_Admin_Helper::redo_upgrade();
			}

			$this->check_upgrade_type();

			$this->init();
		}

		/**
		 * Init the upgrade process. Only actions after admin_init should be added here.
		 *
		 * @return void
		 */
		public function init(){
			global $wpdb;
			$cat_col_type = DLM_Admin_Helper::check_column_type( $wpdb->prefix . 'download_log', 'download_category', 'longtext' );

			// If null, then the column doesn't exist. If false, then the column is not the correct type.
			if ( null !== $cat_col_type && ! $cat_col_type ) {
				wp_enqueue_style( 'dlm-db-upgrade-style', download_monitor()->get_plugin_url() . '/assets/css/db-upgrader.min.css', array(), DLM_VERSION );
				wp_enqueue_script( 'dlm-log-db-upgrade', download_monitor()->get_plugin_url() . '/assets/js/database-upgrader' . ( ( ! SCRIPT_DEBUG ) ? '.min' : '' ) . '.js', array( 'jquery' ), DLM_VERSION, true );
				wp_add_inline_script(
					'dlm-log-db-upgrade',
					'dlm_upgraderColumn =' . wp_json_encode(
						array(
							'nonce'                     => wp_create_nonce( 'dlm-ajax-nonce' ),
							'upgrade_download_category' => esc_html__( 'Update started, please wait. Don\'t close or exit this page. it will reload automatically when it\'s finished.', 'download-monitor' )
						)
					),
					'before' );
				// Add notice for users to update the DB for download_log table to alter download_category column.
				add_action( 'admin_notices', array( $this, 'add_db_download_category_notice' ), 8 );
			}

			// Don't do anything if we don't need to or if upgrader already done from below 4.6.x.
			if ( ! self::do_upgrade() ) {
				return;
			}

			// Add notice for user to update the DB.
			add_action( 'admin_notices', array( $this, 'add_db_update_notice' ), 8 );
			// Enqueue our upgrader scripts.
			add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_db_upgrader_scripts' ) );
			// Add our AJAX actions.
			add_action( 'wp_ajax_dlm_db_log_entries', array( $this, 'count_log_entries' ) );
			add_action( 'wp_ajax_dlm_upgrade_db', array( $this, 'update_log_table_db' ) );
			add_action( 'wp_ajax_dlm_alter_download_log', array( $this, 'alter_download_log_table' ) );
			add_action( 'wp_ajax_dlm_upgrade_db_clear_offset', array( $this, 'clear_offset' ) );

			$dlm_logging = get_option( 'dlm_enable_logging' );
			// Also add the new option to the DB and set it to default.
			add_option(
				'dlm_db_upgraded',
				array(
					'db_upgraded'   => '0',
					'using_logs'    => ( isset( $dlm_logging ) && '1' === $dlm_logging ) ? '1' : '0',
					'upgraded_date' => wp_date( 'Y-m-d' ) . ' 00:00:00',
				)
			);
		}

		/**
		 * Check to see if we need to upgrade
		 *
		 * @since 4.6.0
		 *
		 * @return bool
		 */
		public static function do_upgrade() {

			if ( ! is_admin() || ! current_user_can( 'manage_options' ) ) {
				return false;
			}

			if ( false !== get_transient( 'dlm_db_upgrade_offset' ) || false !== get_transient( 'dlm_upgrade_type' ) ) {
				return true;
			}

			if ( self::check_if_migrated() ) {
				return false;
			}

			if ( ! self::version_checker() ) {
				return false;
			}

			return true;
		}

		/**
		 * Check for version
		 *
		 * @return bool
		 */
		public static function version_checker() {

			if ( get_transient( 'dlm_needs_upgrade' ) && '1' === get_transient( 'dlm_needs_upgrade' ) ) {
				return true;
			}

			$installed_version = get_option( 'dlm_current_version' );

			if ( $installed_version && version_compare( $installed_version, DLM_UPGRADER_VERSION, '<' ) ) {

				set_transient( 'dlm_needs_upgrade', '1', 30 * DAY_IN_SECONDS );
				return true;
			}

			return false;

		}

		/**
		 * Check the old table entries
		 *
		 * @since 4.6.0
		 */
		public function count_log_entries() {

			wp_verify_nonce( $_POST['nonce'], 'dlm_db_log_nonce' );
			// Check if user has the capability to do this.
			if ( ! current_user_can( 'manage_options' ) ) {
				wp_send_json_error( __( 'You do not have permission to do this.', 'download-monitor' ) );
			}

			global $wpdb;
			$posts_table = "{$wpdb->prefix}posts";
			require_once ABSPATH . 'wp-admin/includes/upgrade.php';
			// Made it here, now let's create the table and start migrating.
			// Let check if table does not exist.

			$charset_collate = $wpdb->get_charset_collate();

			$sql = "CREATE TABLE `{$wpdb->dlm_reports}` (
					  date DATE NOT NULL,
					  download_ids longtext NULL,
					  revenue longtext NULL,
					  refunds longtext NULL,
					  PRIMARY KEY  (date),
					  KEY attribute_name (date)
					  ) $charset_collate;";

			dbDelta( $sql );

			// Made it here, now let's create the table and start migrating.
			// Let check if table does not exist.
			$sql = "CREATE TABLE `{$wpdb->dlm_downloads}` (
					    ID bigint(20) NOT NULL auto_increment,
						download_id bigint(20) NOT NULL,
						download_count bigint(20) NOT NULL,
						download_versions varchar(200) NOT NULL,
		 				PRIMARY KEY  (ID),
		 				KEY attribute_name (download_id)
		 				) $charset_collate;";

			dbDelta( $sql );

			// Check if the table exists. User might have deleted it in the past.
			if ( ! DLM_Utils::table_checker( $wpdb->download_log ) ) {
				wp_send_json( '0' );
				exit;
			}

			$results = $wpdb->get_results( $wpdb->prepare( "SELECT  COUNT(dlm_log.ID) as `entries` FROM {$wpdb->download_log} dlm_log INNER JOIN $posts_table dlm_posts ON dlm_log.download_id = dlm_posts.ID" ), ARRAY_A );

			// If there is a transient it means that the import has taken place but did not complete.
			// Let's start from that offset.
			$upgrader_offset = get_transient( 'dlm_db_upgrade_offset' );
			if ( false !== $upgrader_offset ) {

				wp_send_json(
					array(
						'entries' => $results[0]['entries'],
						'offset'  => absint( $upgrader_offset ),
					)
				);
				exit;
			}

			wp_send_json(
				array(
					'entries' => $results[0]['entries'],
					'offset'  => 0,
				)
			);
			exit;
		}


		/**
		 * Alter the download_log table after the migration has taken place
		 *
		 * @return void
		 */
		public function alter_download_log_table() {

			wp_verify_nonce( $_POST['nonce'], 'dlm_db_log_nonce' );
			// Check if user has the capability to do this.
			if ( ! current_user_can( 'manage_options' ) ) {
				wp_send_json_error( __( 'You do not have permission to do this.', 'download-monitor' ) );
			}

			// Managed this far, means migration of data is finalized so we can delete our set transient with the offset.
			delete_transient( 'dlm_db_upgrade_offset' );
			delete_transient( 'dlm_needs_upgrade' );

			// Flush the permalinks.
			flush_rewrite_rules( false );

			// Final step has been made, upgrade is complete.
			$dlm_db_upgrade                  = get_option( 'dlm_db_upgraded' );
			$dlm_db_upgrade['db_upgraded']   = '1';
			$dlm_db_upgrade['upgraded_date'] = wp_date( 'Y-m-d' );

			update_option( 'dlm_db_upgraded', $dlm_db_upgrade );

			// Now lets clear all transients.
			download_monitor()->service( 'transient_manager' )->clear_all_version_transients();

			// Add extra columns to the table
			global $wpdb;

			require_once ABSPATH . 'wp-admin/includes/upgrade.php';
			$charset_collate = $wpdb->get_charset_collate();
			$dlm_tables      = '
					CREATE TABLE `' . $wpdb->prefix . "download_log` (
						ID bigint(20) NOT NULL auto_increment,
						user_id bigint(20) NOT NULL,
						user_ip varchar(200) NOT NULL,
						uuid varchar(200) NOT NULL,
						user_agent varchar(200) NOT NULL,
						download_id bigint(20) NOT NULL,
						version_id bigint(20) NOT NULL,
						version varchar(200) NOT NULL,
						download_date datetime DEFAULT NULL,
						download_status varchar(200) DEFAULT NULL,
						download_status_message varchar(200) DEFAULT NULL,
						download_location varchar(200) DEFAULT NULL,
						download_category longtext DEFAULT NULL,
						meta_data longtext DEFAULT NULL,
						PRIMARY KEY  (ID),
						KEY attribute_name (download_id)
					) $charset_collate;
					";

			dbDelta( $dlm_tables );
			$uuid_query = "UPDATE {$wpdb->download_log} SET uuid = md5(user_ip) WHERE ( uuid IS NULL OR '' = uuid ) AND user_ip IS NOT NULL;";
			$wpdb->query( $uuid_query );
			// Keep transient deletion here, we are using it to check if the upgrade is total or partial.
			delete_transient( 'dlm_upgrade_type' );
			wp_send_json( array( 'success' => true ) );
			exit;
		}

		/**
		 * Check if DB migrated or not
		 *
		 * @return bool
		 * @since 4.6.0
		 */
		public static function check_if_migrated() {

			global $wpdb;
			$upgrade_option = get_option( 'dlm_db_upgraded' );

			// Check if table exists and if option is valid.
			if ( null !== DLM_Utils::table_checker( $wpdb->dlm_reports ) && isset( $upgrade_option['db_upgraded'] ) && '1' === $upgrade_option['db_upgraded'] ) {

				return true;
			}

			return false;
		}

		/**
		 * The new table update functionality
		 *
		 * @since 4.6.0
		 */
		public function update_log_table_db() {

			wp_verify_nonce( $_POST['nonce'], 'dlm_db_log_nonce' );
			// Check if user has the capability to do this.
			if ( ! current_user_can( 'manage_options' ) ) {
				wp_send_json_error( __( 'You do not have permission to do this.', 'download-monitor' ) );
			}

			global $wpdb;
			$upgrade_type = get_transient( 'dlm_upgrade_type' );
			require_once ABSPATH . 'wp-admin/includes/upgrade.php';
			$charset_collate = $wpdb->get_charset_collate();
			$limit           = 10000;

			$offset = ( isset( $_POST['offset'] ) ) ? $limit * absint( $_POST['offset'] ) : 0;

			$sql_limit = "LIMIT {$offset},{$limit}";

			$items   = array();
			$table_1 = "{$wpdb->download_log}";
			$able_2  = "{$wpdb->posts}";
			// Table that contains downlaod counts about each Download and their versions. Used for performance issues introduced in version 4.6.0 of the plugin.
			$downloads_table = "{$wpdb->dlm_downloads}";
			// If at this point the table does not exist, we need to create it.
			$sql = "CREATE TABLE `{$wpdb->dlm_downloads}` (
					    ID bigint(20) NOT NULL auto_increment,
						download_id bigint(20) NOT NULL,
						download_count bigint(20) NOT NULL,
						download_versions varchar(200) NOT NULL,
		 				PRIMARY KEY  (ID),
		 				KEY attribute_name (download_id)
		 				) $charset_collate;";

			dbDelta( $sql );
			// Check if data has been introduced into table and update it, else we need to populate it.
			$data = $wpdb->get_results( $wpdb->prepare( "SELECT  dlm_log.download_id as `ID`, dlm_log.version_id as `version`, DATE_FORMAT(dlm_log.download_date, '%%Y-%%m-%%d') AS `date`, dlm_log.download_status as `status`, dlm_posts.post_title AS `title` FROM {$table_1} dlm_log LEFT JOIN {$able_2} dlm_posts ON dlm_log.download_id = dlm_posts.ID WHERE 1=1 {$sql_limit}" ), ARRAY_A );

			// Create empty array of downloads. Will be used to add to the table as a bulk insert and not each row at a time.
			// This will improve performance.
			$downloads          = array();
			// This should not be a problem as the number of entries would be the number of existing downloads.
			$saved_downloads = $wpdb->get_results( "SELECT * FROM {$downloads_table};", ARRAY_A );
			$download_id_column = array_column( $saved_downloads,'download_id' );
			$looped = array();

			foreach ( $data as $row ) {
				// Only add non-failed attempts to the table.
				if ( 'failed' !== $row['status'] ) {
					list( $loop_key, $download ) = $this->create_downloads( $row, $downloads, $download_id_column, $saved_downloads, $looped );
					$downloads[ $row['ID'] ] = $download;

					if ( false !== $loop_key ) {
						$looped[] = $loop_key;
					}
				}
				// Only do this if we need to recreate the dlm_reports_log table also.
				if ( 'total' === $upgrade_type ) {
					$item = $this->create_dates( $row, $items );
					if ( is_array( $item ) ) {
						$items[ $row['date'] ][ $row['ID'] ] = $item;
					} else {
						$items[ $row['date'] ][ $row['ID'] ]['downloads'] = $item;
					}
				}
			}
			// Import Downloads into new table.
			if ( ! empty( $downloads ) ) {
				$this->import_downloads( $downloads );
			}
			// Import Report Dates into new table.
			if ( 'total' === $upgrade_type ) {
				$this->import_dates( $items );
			}
			set_transient( 'dlm_db_upgrade_offset', absint( $_POST['offset'] ) );
			// We save the previous so that we make sure all the entries from that range will be saved.
			wp_send_json_success( $offset );
			exit;
		}

		/**
		 * Clear the previous set offset
		 *
		 * @return void
		 */
		public function clear_offset() {

			wp_verify_nonce( $_POST['nonce'], 'dlm_db_log_nonce' );
			// Check if user has the capability to do this.
			if ( ! current_user_can( 'manage_options' ) ) {
				wp_send_json_error( __( 'You do not have permission to do this.', 'download-monitor' ) );
			}

			if ( ! isset( $_POST['offset'] ) ) {
				// We need the previous set offset
				wp_send_json_error();
				exit;
			}

			global $wpdb;
			$downloads_table = "{$wpdb->dlm_downloads}";
			$limit           = 10000;
			$offset          = ( isset( $_POST['offset'] ) ) ? $limit * absint( $_POST['offset'] ) : 0;
			$sql_limit       = "LIMIT {$offset},{$limit}";
			$items           = array();
			$table_1         = "{$wpdb->download_log}";
			$able_2          = "{$wpdb->prefix}posts";

			$data = $wpdb->get_results( $wpdb->prepare( "SELECT  dlm_log.download_id as `ID`, dlm_log.version_id as `version`, DATE_FORMAT(dlm_log.download_date, '%%Y-%%m-%%d') AS `date`, dlm_log.download_status as `status`, dlm_posts.post_title AS `title` FROM {$table_1} dlm_log LEFT JOIN {$able_2} dlm_posts ON dlm_log.download_id = dlm_posts.ID WHERE 1=1 {$sql_limit}" ), ARRAY_A );

			// Create empty array of downloads. Will be used to add to the table as a bulk insert and not each row at a time.
			// This will improve performance.
			$downloads = array();
			// This should not be a problem as the number of entries would be the number of existing downloads.
			$saved_downloads    = $wpdb->get_results( "SELECT * FROM {$downloads_table};", ARRAY_A );
			$download_id_column = array_column( $saved_downloads, 'download_id' );
			$looped             = array();

			foreach ( $data as $row ) {

				if ( 'failed' !== $row['status'] ) {
					list( $loop_key, $download ) = $this->create_downloads( $row, $downloads, $download_id_column, $saved_downloads, $looped );
					$downloads[ $row['ID'] ] = $download;
					if ( false !== $loop_key ) {
						$looped[] = $loop_key;
					}
				}

				if ( 'total' === get_transient( 'dlm_upgrade_type' ) ) {
					$item = $this->create_dates( $row, $items );
					if ( is_array( $item ) ) {
						$items[ $row['date'] ][ $row['ID'] ] = $item;
					} else {
						$items[ $row['date'] ][ $row['ID'] ]['downloads'] = $item;
					}
				}
			}

			// Clear offset Downloads.
			if ( ! empty( $downloads ) ) {
				$this->clear_downloads( $downloads );
			}
			// Clear offset Report Dates
			if ( 'total' === get_transient( 'dlm_upgrade_type' ) ) {
				foreach ( $items as $key => $log ) {

					$table = "{$wpdb->dlm_reports}";

					$sql_check  = "SELECT * FROM $table  WHERE date = %s;";
					$sql_update = "UPDATE $table dlm SET dlm.download_ids = %s WHERE dlm.date = %s";
					$check      = $wpdb->get_results( $wpdb->prepare( $sql_check, $key ), ARRAY_A );

					if ( null !== $check && ! empty( $check ) ) {

						$downloads = json_decode( $check[0]['download_ids'], ARRAY_A );

						foreach ( $log as $item_key => $item ) {

							if ( isset( $downloads[ $item_key ] ) ) {
								$downloads[ $item_key ]['downloads'] = $downloads[ $item_key ]['downloads'] - $item['downloads'];
							}
						}

						$wpdb->query( $wpdb->prepare( $sql_update, wp_json_encode( $downloads ), $key ) );

					}
				}
			}

			wp_send_json_success();
			exit;
		}

		/**
		 * Add the DB Upgrader notice
		 *
		 * @since 4.6.0
		 */
		public function add_db_update_notice() {

			?>
			<div class="dlm-upgrade-db-notice notice">
				<div class="dlm-yellow-band-notice">
					<?php echo wp_kses_post( __( 'Please <a href="#" class="dlm-db-upgrade-link">upgrade the database</a>.', 'download-monitor' ) ); ?>
				</div>
				<div class="inside">
					<div class="main">
						<img class="dlm-notice-logo" src="data:image/png;base64, ">
						<h4><?php echo wp_kses_post( __('Hello there! We made some changes on how Download Monitor\'s data is structured. Please <a href="#" class="dlm-db-upgrade-link">click here</a> to upgrade your database', 'download-monitor' ) ); ?></h4>
						<button id="dlm-upgrade-db" class="button button-primary">
							<?php
							// If the transient is present it means that this is a Resume Upgrade request
							if ( get_transient( 'dlm_db_upgrade_offset' ) ) {
								esc_html_e( 'Resume Upgrade', 'download-monitor' );
							} else {
								esc_html_e( 'Upgrade', 'download-monitor' );
							}
							?>
						</button>
					</div>	
					<div class="dlm-progress-label">0%</div>		
				</div>
				<div id="dlm_progress-bar"></div>
			</div>
			<?php
		}

		/**
		 * Add the DB Upgrader notice to update download_category column.
		 *
		 * @since 4.8.0
		 */
		public function add_db_download_category_notice() {
			?>
			<div class="dlm-upgrade-db-notice notice">
				<div class="dlm-yellow-band-notice">
					<?php echo wp_kses_post( __( 'Please <a href="#" class="dlm-db-download_category-link">upgrade the database</a>.', 'download-monitor' ) ); ?>
				</div>
				<div class="inside">
					<div class="main">
						<img class="dlm-notice-logo" src="data:image/png;base64, ">
						<h4><?php echo wp_kses_post( __('Hello there! We made some changes on how Download Monitor\'s data is structured. Please make a backup of your database and click the upgrade button', 'download-monitor' ) ); ?></h4>
						<button id="dlm-upgrade-download_category" class="button button-primary">
							<?php
								esc_html_e( 'Upgrade', 'download-monitor' );
							?>
						</button>
					</div>
				</div>
			</div>
			<?php
		}

		/**
		 * Enqueue the DB Upgrader scripts
		 *
		 * @since 4.6.0
		 */
		public function enqueue_db_upgrader_scripts() {

			wp_enqueue_script( 'jquery-ui' );
			wp_enqueue_script( 'jquery-ui-progressbar' );
			wp_enqueue_script( 'dlm-log-db-upgrade', download_monitor()->get_plugin_url() . '/assets/js/database-upgrader' . ( ( ! SCRIPT_DEBUG ) ? '.min' : '' ) . '.js', array( 'jquery' ), DLM_VERSION, true );
			wp_add_inline_script( 'dlm-log-db-upgrade', 'dlm_upgrader =' . wp_json_encode( array( 'nonce' => wp_create_nonce( 'dlm_db_log_nonce' ) ) ), 'before' );

			wp_enqueue_style( 'dlm-db-upgrade-style', download_monitor()->get_plugin_url() . '/assets/css/db-upgrader.min.css', array(), DLM_VERSION );
			wp_enqueue_style( 'jquery-ui-style', download_monitor()->get_plugin_url() . '/assets/css/jquery-ui.min.css', array(), DLM_VERSION );
		}

		/**
		 * Import downloads in upgrader. Imports data to new {prefix}dlm_downloads table.
		 *
		 * @param $downloads
		 *
		 * @return void
		 * @since 4.7.0
		 */
		public function import_downloads( $downloads ) {
			global $wpdb;
			$downloads_table = "{$wpdb->dlm_downloads}";
			// The queries we need to make so that we insert each download as a row.
			$check_for_downloads = "SELECT * FROM {$downloads_table}  WHERE download_id = %s;";
			$downloads_insert    = "INSERT INTO {$downloads_table} (download_id,download_count,download_versions) VALUES ( %s , %s, %s );";
			$downloads_update    = "UPDATE {$downloads_table} dlm SET dlm.download_count = %s, dlm.download_versions = %s WHERE dlm.download_id = %s";

			if ( ! empty( $downloads ) ) {
				foreach ( $downloads as $key => $dlm ) {
					$check = $wpdb->get_results( $wpdb->prepare( $check_for_downloads, $key ), ARRAY_A );
					if ( ! empty( $check ) ) {
						$wpdb->query( $wpdb->prepare( $downloads_update, $dlm['download_count'], $dlm['download_versions'], $key ) );
					} else {
						$wpdb->query( $wpdb->prepare( $downloads_insert, $key, $dlm['download_count'], $dlm['download_versions'] ) );
					}
				}
			}
		}

		/**
		 * Clear created downloads
		 *
		 * @param $downloads
		 *
		 * @return void
		 * @since 4.7.0
		 */
		public function clear_downloads( $downloads ) {
			global $wpdb;
			$downloads_table = "{$wpdb->dlm_downloads}";
			// The queries we need to make so that we insert each download as a row.
			$check_for_downloads = "SELECT * FROM {$downloads_table}  WHERE download_id = %s;";
			$downloads_update    = "UPDATE {$downloads_table} dlm SET dlm.download_count = %s, dlm.download_versions = %s WHERE dlm.download_id = %s";

			if ( ! empty( $downloads ) ) {
				foreach ( $downloads as $key => $dlm ) {
					$check = $wpdb->get_results( $wpdb->prepare( $check_for_downloads, $key ), ARRAY_A );
					if ( ! empty( $check ) ) {
						$saved_download   = $check[0];
						$download_count   = absint( $saved_download['download_count'] ) - absint( $dlm['download_count'] );
						$saved_versions   = json_decode( $saved_download['download_versions'], true );
						$current_versions = json_decode( $dlm['download_versions'], true );
						foreach ( $saved_versions as $id => $count ) {
							if ( isset( $current_versions[ $id ] ) ) {
								$saved_versions[ $id ] = absint( $count ) - absint( $current_versions[ $id ] );
							}
						}
						$wpdb->query( $wpdb->prepare( $downloads_update, $download_count, json_encode( $saved_versions ), $key ) );
					}
				}
			}
		}

		/**
		 * Import data used for Reports chart. Adds data to new table {prefix}dlm_reports_log
		 *
		 * @param $items
		 *
		 * @return void
		 * @since 4.7.0
		 */
		public function import_dates( $items ){
			global $wpdb;

			foreach ( $items as $key => $log ) {

				$table = "{$wpdb->dlm_reports}";

				$sql_check  = "SELECT * FROM {$table}  WHERE date = %s;";
				$sql_insert = "INSERT INTO {$table} (date,download_ids) VALUES ( %s , %s );";
				$sql_update = "UPDATE {$table} dlm SET dlm.download_ids = %s WHERE dlm.date = %s";
				$check      = $wpdb->get_results( $wpdb->prepare( $sql_check, $key ), ARRAY_A );

				if ( null !== $check && ! empty( $check ) ) {

					$downloads = json_decode( $check[0]['download_ids'], ARRAY_A );

					foreach ( $log as $item_key => $item ) {
						if ( isset( $downloads[ $item_key ] ) ) {
							$downloads[ $item_key ]['downloads'] = $downloads[ $item_key ]['downloads'] + $item['downloads'];
							unset( $downloads[ $item_key ]['date'] );
						} else {
							$downloads[ $item_key ] = array(
								'downloads' => $item['downloads'],
								'title'     => $item['title'],
							);
						}
					}

					$wpdb->query( $wpdb->prepare( $sql_update, wp_json_encode( $downloads ), $key ) );

				} else {

					$wpdb->query( $wpdb->prepare( $sql_insert, $key, wp_json_encode( $log ) ) );
				}
			}
		}

		/**
		 * Check what type of upgrade we need
		 *
		 * @since 4.7.0
		 */
		public function check_upgrade_type() {
			global $wpdb;
			$transient = 'dlm_upgrade_type';
			if ( ! DLM_Utils::table_checker( $wpdb->dlm_downloads ) ) {
				set_transient( $transient, 'partial', 7 * DAY_IN_SECONDS );
				if ( ! DLM_Utils::table_checker( $wpdb->dlm_reports ) ) {
					set_transient( $transient, 'total', 7 * DAY_IN_SECONDS );
				}
			}
		}

		/**
		 * Create upgrader downloads
		 *
		 * @param $row
		 * @param $downloads
		 * @param array $download_id_column
		 * @param array $saved_downloads
		 * @param array $looped
		 *
		 * @return array
		 * @since 4.7.0
		 */
		public function create_downloads( $row, $downloads, $download_id_column = array(), $saved_downloads = array(), $looped = array() ) {

			$download_versions = array();
			$download_id       = $row['ID'];
			$version_id        = $row['version'];
			$download_count    = 1;
			$existing_versions = array(
				$version_id => 1,
			);
			$looped_key = false;

			// If download already exists in $downloads means we looped through, and we should take into consideration the existing data.
			if ( isset( $downloads[ $download_id ] ) ) {
				$existing_versions = json_decode( $downloads[ $download_id ]['download_versions'], true );
				$download_count    = absint( $downloads[ $download_id ]['download_count'] ) + 1;
				if ( isset( $existing_versions[ $version_id ] ) ) {
					$existing_versions[ $version_id ] = absint( $existing_versions[ $version_id ] ) + 1;
				} else {
					$existing_versions = array(
						$version_id => 1,
					);
				}
			}

			// IF the download does not exist in the table, we need to insert it, else we need to update it.
			if ( ! empty( $saved_downloads ) ) {
				// Search in a multidimensional array if download_id exists.
				$key = array_search( $download_id, $download_id_column );
				// We should only search the saved downloads once, otherwise it will falsely add data.
				if ( false !== $key && ! in_array( $key, $looped ) ) {
					$looped_key        = $key;
					$download          = $saved_downloads[ $key ];
					$download_versions = ! empty( $download['download_versions'] ) ? json_decode( $download['download_versions'], true ) : array();
					$download_count    = absint( $download['download_count'] ) + absint( $download_count );

					if ( isset( $download_versions[ $version_id ] ) ) {
						$download_versions[ $version_id ] = absint( $download_versions[ $version_id ] ) + absint( $existing_versions[ $version_id ] );
					} else {
						$download_versions[ $version_id ] = absint( $existing_versions[ $version_id ] );
					}
				}
			}

			if ( empty( $download_versions ) ) {
				$download_versions = $existing_versions;
			}

			$download = array(
				'download_id'       => $download_id,
				'download_count'    => $download_count,
				'download_versions' => wp_json_encode( $download_versions )
			);

			return array(
				$looped_key,
				$download
			);
		}

		/**
		 * Create upgrader dates.
		 *
		 * @param $row array Current row of the query.
		 * @param $items array Array of items parsed.
		 *
		 * @return array|int
		 * @since 4.7.0
		 */
		public function create_dates( $row, $items ) {
			if ( ! isset( $items[ $row['date'] ][ $row['ID'] ] ) ) {
				return array(
					'downloads' => 1,
					'title'     => $row['title'],
				);
			} else {
				return absint( $items[ $row['date'] ][ $row['ID'] ]['downloads'] ) + 1;
			}
		}
	}
}
