<?php
/********************************************************************
 * Copyright (C) 2024 Darko Gjorgjijoski (https://darkog.com/)
 * Copyright (C) 2024 IDEOLOGIX MEDIA Dooel (https://ideologix.com/)
 *
 * This file is property of IDEOLOGIX MEDIA Dooel (https://ideologix.com)
 * This file is part of Vimeify Plugin - https://wordpress.org/plugins/vimeify/
 *
 * Vimeify - Formerly "WP Vimeo Videos" is free software: you can redistribute
 * it and/or modify it under the terms of the GNU General Public License as
 * published by the Free Software Foundation, either version 2 of the License,
 * or (at your option) any later version.
 *
 * Vimeify - Formerly "WP Vimeo Videos" is distributed in the hope that it
 * will be useful, but WITHOUT ANY WARRANTY; without even the implied
 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along
 * with this plugin. If not, see <https://www.gnu.org/licenses/>.
 *
 * Code developed by Darko Gjorgjijoski <dg@darkog.com>.
 **********************************************************************/

namespace Vimeify\Core\Abstracts;

use Vimeify\Core\Abstracts\Interfaces\SystemInterface;
use Vimeify\Core\System;

abstract class BaseTool {

	/**
	 * The instance id
	 * @var - integer
	 */
	protected $id;

	/**
	 * The identifier
	 * @var string
	 */
	protected $slug;

	/**
	 * The description
	 * @var string
	 */
	protected $description;

	/**
	 * Is the tool one-time tool only?
	 * @var bool
	 */
	protected $is_one_time;

	/**
	 * The plugin
	 * @var SystemInterface
	 */
	protected $system;

	/**
	 * Constructor
	 *
	 * @param string $id
	 * @param SystemInterface|System $plugin
	 */
	public function __construct( $id, $system ) {
		$this->id     = $id;
		$this->system = $system;
	}

	/**
	 * Set the tool id
	 * @param $id
	 *
	 * @return void
	 */
	public function set_id($id) {
		$this->id = $id;
	}

	/**
	 * Set temporary tool data
	 *
	 * @param $key
	 * @param $value
	 *
	 * @return array
	 */
	public function set_temporary_data( $key, $value ) {
		$data = $this->get_temporary_data();
		if ( ! is_array( $data ) ) {
			$data = array();
		}
		$data[ $key ] = $value;
		set_transient( $this->get_temporary_dataKey(), $data, apply_filters( 'vimeify_tool_data_expiration', 48 * HOUR_IN_SECONDS, $this ) );

		return $value;
	}

	/**
	 * Get temporary tool data
	 *
	 * @param $key
	 * @param $default
	 *
	 * @return mixed|null
	 */
	public function get_temporary_data( $key = null, $default = null ) {
		$data = get_transient( $this->get_temporary_dataKey() );

		if ( is_null( $key ) ) {
			return $data;
		}

		return is_array( $data ) && isset( $data[ $key ] ) ? $data[ $key ] : $default;
	}

	/**
	 * Delete temporary tool data
	 * @return void
	 */
	public function delete_temporary_data() {
		delete_transient( $this->get_temporary_dataKey() );
	}

	/**
	 * Get the temporary data key
	 * @return string
	 */
	public function get_temporary_dataKey() {
		return 'vimeify_tool_' . md5( $this->id );
	}

	/**
	 * Set persisted tool data
	 *
	 * @param $key
	 * @param $value
	 *
	 * @return void
	 */
	public function set_data( $key, $value ) {
		$tools = get_option( 'vimeify_tools', array() );
		if ( ! is_array( $tools ) ) {
			$tools = [];
		}
		if ( empty( $tools[ $this->set_data_key() ] ) ) {
			$tools[ $this->set_data_key() ] = [];
		}
		$tools[ $this->set_data_key() ][ $key ] = $value;
		update_option( 'vimeify_tools', $tools );
	}

	/**
	 * Get persisted tool data
	 *
	 * @param $key
	 * @param $default
	 *
	 * @return mixed|null
	 */
	public function get_data( $key = null, $default = null ) {
		$tools = get_option( 'vimeify_tools', array() );
		if ( ! is_array( $tools ) ) {
			$tools = [];
		}
		if ( empty( $tools[ $this->set_data_key() ] ) ) {
			$tools[ $this->set_data_key() ] = [];
		}

		if ( is_null( $key ) ) {
			return $tools[ $this->set_data_key() ];
		}

		return is_array( $tools[ $this->set_data_key() ] ) && isset( $tools[ $this->set_data_key() ][ $key ] ) ? $tools[ $this->set_data_key() ][ $key ] : $default;
	}

	/**
	 * Delete persisted tool data
	 * @return void
	 */
	public function delete_data( $key = null ) {

		$tools = get_option( 'vimeify_tools', array() );

		if ( is_null( $key ) ) {
			if ( ! empty( $tools[ $this->set_data_key() ] ) ) {
				unset( $tools[ $this->set_data_key() ] );
			}
		} else {
			if ( isset( $tools[ $this->set_data_key() ][ $key ] ) ) {
				unset( $tools[ $this->set_data_key() ][ $key ] );
			}
		}
		if ( empty( $tools ) ) {
			delete_option( 'vimeify_tools' );
		} else {
			update_option( 'vimeify_tools', $tools );
		}
	}

	/**
	 * Get persisted tool data key
	 * @return string
	 */
	public function set_data_key() {
		return $this->slug;
	}

	/**
	 * Returns the view
	 * @return string
	 */
	abstract public function get_view();

	/**
	 * Returns the tool steps
	 *
	 * eg:
	 *
	 *    [
	 *        1 => array( 'name' => 'Step 1', 'pages' => 3 ),
	 *        2 => array( 'name' => 'Step 2', 'pages' => 4 ),
	 *        3 => array( 'name' => 'Step 3', 'pages' => 5 ),
	 *        4 => array( 'name' => 'Step 4', 'pages' => 6 ),
	 *        5 => array( 'name' => 'Step 5', 'pages' => 7 )
	 *    ];
	 *
	 * @return array|\WP_Error
	 */
	abstract public function get_steps();

	/**
	 * Initializes the process
	 *
	 * @return bool|\WP_Error
	 */
	abstract public function init_process();

	/**
	 * Initializes the process
	 *
	 * @param $step
	 * @param $page
	 *
	 * @return bool|\WP_Error
	 */
	abstract public function do_step( $step, $page );


	/**
	 * Mark as complete (Not all tools needs this)
	 * @return void
	 */
	public function mark_as_complete() {
		$this->set_data( 'completed_at', time() );
	}

	/**
	 * Mark as not-complete (Not all tools needs this)
	 * @return void
	 */
	public function mark_as_incomplete() {
		$this->delete_data( 'completed_at' );
	}

	/**
	 * Has this tool completed previously?
	 * @return bool
	 */
	public function is_complete() {
		$completed_at = $this->get_data( 'completed_at', null );

		return ! empty( $completed_at );
	}

	/**
	 * Return the next step
	 *
	 * @param $step
	 * @param $page
	 *
	 * @return array|\WP_Error
	 */
	public function get_next_step( $step, $page ) {

		$step = is_null( $step ) ? 1 : (int) $step;
		$page = is_null( $page ) ? 1 : (int) $page;

		$steps = $this->get_steps();

		if ( ! is_array( $steps ) ) {
			return new \WP_Error( '500', 'Unable to determine next step', 'vimeify' );
		}

		$total = 0;
		foreach ( $steps as $id => $next_step ) {
			$total += (int) $next_step['pages'];
		}

		$data = [
			'next_step' => 0,
			'next_page' => 0,
			'message'   => '',
			'total'     => $total,
			'current'   => 0,
			'percent'   => 0,
		];

		if ( ! isset( $steps[ $step ] ) ) {
			$data['next_step'] = - 1;
			$data['next_page'] = - 1;
			$data['message']   = __( 'Operation not initialized properly.', 'vimeify' );

			return $data;
		} else {

			if ( ! isset( $steps[ $step ]['pages'] ) ) {
				return new \WP_Error( '500', __( 'Unable to determine next step', 'vimeify' ) );
			}

			$next_page   = $page + 1;
			$total_pages = (int) $steps[ $step ]['pages'];

			if ( $page === $total_pages ) {
				$next_step         = isset( $steps[ $step + 1 ] ) ? $step + 1 : - 1;
				$data['next_step'] = $next_step;
				$data['next_page'] = isset( $steps[ $step + 1 ] ) ? 1 : - 1;
				$data['message']   = sprintf( __( 'Processing "%s" - Page: %d/%d', 'vimeify' ), $steps[ $step ]['name'], $page, $total_pages );
			} else if ( $page < $total_pages ) {
				$next_step         = $step;
				$data['next_step'] = $next_step;
				$data['next_page'] = $next_page;
				$data['message']   = sprintf( __( 'Processing "%s" - Page: %d/%d', 'vimeify' ), $steps[ $step ]['name'], $page, $total_pages );
			} else if ( isset( $steps[ $step + 1 ] ) ) {
				$next_page         = 1;
				$next_step         = $step + 1;
				$data['next_step'] = $next_step;
				$data['next_page'] = $next_page;
				$data['message']   = sprintf( __( 'Processing "%s" - Page: %d/%d', 'vimeify' ), $steps[ $step ]['name'], $page, $total_pages );

			} else {
				$next_step         = - 1;
				$data['next_step'] = - 1;
				$data['next_page'] = - 1;
				$data['message']   = __( 'Operation complete.', 'vimeify' );
			}


			$current = 0;
			foreach ( $steps as $i => $info ) {
				if ( $i < $step ) {
					$current += $info['pages'];
				} else if ( $i === $step ) {
					$current += $page;
				}
			}

			$data['percent'] = $current > 0 && $total > 0 ? round( $current / $total * 100, 2 ) : 0;

		}

		return $data;

	}

	/**
	 * Return the id identifier
	 * @return string
	 */
	public function get_id() {
		return $this->id;
	}

	/**
	 * Return the id identifier
	 * @return string
	 */
	public function get_slug() {
		return $this->slug;
	}

	/**
	 * Return the description
	 * @return string
	 */
	public function get_description() {
		return $this->description;
	}

	/**
	 * Check if the tool is one-time only
	 * @return bool
	 */
	public function is_one_time() {
		return apply_filters( 'vimeify_tools_is_one_time', $this->is_one_time, $this );
	}
}