<?php
/**
 * Installation related functions and actions.
 *
 * @author 		ThemeFuzz
 * @category 	Admin
 * @package 	ZnFramework/Classes
 * @version     1.0.0
 */

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

/**
 * Zn_Install Class
 */
class Zn_Install {

	private $theme_version;
	private $theme_old_version;
	private $theme_db_version;
	private $db_updates = array();

	function __construct(){

		// Only init this if we have a configuration file
		$this->init();
		$this->add_actions();
	}

	private function init(){
		$theme_name = 'zn_'.ZN()->theme_data['theme_id'];
		$this->theme_version = ZN()->theme_data['version'];
		$this->theme_old_version = $theme_name.'_version';
		$this->theme_db_version = $theme_name.'_db_version';

		// Load Updater scripts
		$update_config = THEME_BASE .'/template_helpers/update/update_config.php';
		if( file_exists($update_config) ){
			require( $update_config );
			$this->db_updates = apply_filters( 'zn_theme_update_scripts', array() );
		}

	}

	/**
	 * Checks if this a theme update or a new installation
	 * @return type
	 */
	private function add_actions(){
		// Set this action to 5 so we can load the about page at a higher priority
		add_action( 'admin_init', array( $this, 'check_version' ), 5 );
	}

	/**
	 * Checks if this a theme update or a new installation
	 * @return type
	 */
	public function check_version() {
		if ( get_option( $this->theme_old_version ) != ZN()->theme_data['version'] || get_option( $this->theme_db_version ) != ZN()->theme_data['version'] ) {
			$this->install();
		}
	}

	/**
	 * Install Current Theme or perform update
	 */
	private function install(){

		// Check if we need to load an updater script
		$current_db_version = get_option( $this->theme_db_version, apply_filters( 'zn_theme_db_version', null ) );
		// Run trough filter for Kallyas. We have the theme options saved in a different field than the one set in theme_Data
		$has_saved_options = get_option( apply_filters( 'zn_updater_options_prefix', ZN()->theme_data['options_prefix'] )  );

		// This is a new install
		if( !$has_saved_options ){
			// Proceed with default install
		}
		// We need to update the theme
		elseif ( !empty( $this->db_updates ) && version_compare( $current_db_version, $this->theme_version, '<' ) && null !== $current_db_version ) {

			$needs_update = false;
			foreach ( $this->db_updates as $version => $updater ) {

				if ( version_compare( $current_db_version, $version, '<' ) ) {
					$needs_update = true;
				}

			}

			// Set a flag that we need to check for update script
			if( $needs_update ){
				set_transient( 'zn_theme_needs_update', true, HOUR_IN_SECONDS );
				return false;
			}

		}

		// Update the DB version with the new one
		delete_option( $this->theme_db_version );
		add_option( $this->theme_db_version, $this->theme_version );
		
	}

	/**
	 * Handle updates
	 * TODO : Move all ajax code inside this file
	 */
	public function update( $step = 0,  $data = false ) {

		if( $step == '0' ){
			$this->set_data();

			if( !empty( $this->update_data['current_update'] ) ){
				$response = array(
					'status' => 'ok',
					'step'	=> 'process_update',
					'data'	=> array(
						'update_version' => $this->update_data['current_update'],
					), 
					'response_text' => 'Starting update for version '. $this->update_data['current_update'],
				);
				$this->zn_send_json( $response );
			}
			else{
				$this->do_update_end();
			}

			
		}
		elseif( $step == 'process_update' ){

			// Load the version update file
			if( empty( $this->db_updates[$data['update_version']] ) ){
				// TODO : Investigate if we should close here.. it may be a javascript issue ?
				$this->do_update_end();
			}

			// We need to call the updater script for the current version
			include( $this->db_updates[$data['update_version']]['file'] );
			$current_version_function = $this->db_updates[$data['update_version']]['function'];

			call_user_func_array( $current_version_function, array( $step, $data ) );

		}
		elseif( $step == 'version_done' ){
			// Here we need to set the current_db_version to the current script version
			if( empty( $this->db_updates[$data['update_version']] ) ){
				// TODO : Investigate if we should close here.. it may be a javascript issue ?
				$this->do_update_end();
			}

			delete_option( $this->theme_db_version );
			add_option( $this->theme_db_version, $data['update_version'] );

			$this->set_data();

			if( !empty( $this->update_data['current_update'] ) ){
				$response = array(
					'status' => 'ok',
					'step'	=> 'process_update',
					'data'	=> array(
						'update_version' => $this->update_data['current_update'],
					), 
					'response_text' => 'Starting update for version '. $this->update_data['current_update'],
				);
				$this->zn_send_json( $response );
			}
			else{
				$this->do_update_end();
			}
			

		}
		elseif( $step == 'done' ){
			$this->do_update_end();
		}
		return;
	}

	function do_update_end(){
		// Set the DB version to the current theme installed
		delete_option( $this->theme_db_version );
		add_option( $this->theme_db_version, $this->theme_version );
		delete_transient( 'zn_theme_needs_update' );

		$response = array(
				'status' => 'done',
				'response_text' => 'Theme update finished'
			);
		$this->zn_send_json( $response );
	}

	function zn_send_json( $response ) {

		while (ob_get_level()) {
		    ob_end_clean();
		}

		header( 'Content-Type: application/json; charset=' . get_option( 'blog_charset' ) );
		$response = json_encode( $response );
		echo '<div class="zn_json_response">';
			echo $response;
		echo '</div>';
		die();
	}

	function set_data(){

		$current_db_version = get_option( $this->theme_db_version, apply_filters( 'zn_theme_db_version', null ) );
		$updates_remaining  = array();

		foreach ( $this->db_updates as $version => $updater ) {

			if ( version_compare( $current_db_version, $version, '<' ) ) {
				$updates_remaining[] = $version;
			}

		}

		$current_update = false;
		if( !empty( $updates_remaining ) && is_array( $updates_remaining ) ){
			$current_update = reset( $updates_remaining );
		}

		$this->update_data = array(
			'updates_remaining' => $updates_remaining,
			'current_update' => $current_update,
		);

		set_transient( 'zn_update_process', $this->update_data, 12 * HOUR_IN_SECONDS );
	}

	function get_data(){
		 $this->update_data = get_transient( 'zn_update_process' );
	}

}