<?php
/**
 * N-Media Settings Panel Framework
 * 
 * @version 1.0
*/


/* 
**========== Block direct access =========== 
*/
if( ! defined('ABSPATH' ) ){ exit; }


class PPOM_SettingsFramework {
    
    private static $ins = null;
	
	/**
	 * Return setting key.
	 * 
	 * @var string
	 *
	*/
	private static $save_key =  '';
	
	/**
	 * Return saved settings.
	 * 
	 * @var string
	 *
	*/
	private static $saved_settings =  '';
	
	/**
	 * Return setting tabs.
	 * 
	 * @var array
	 *
	*/
	public $tabs = [];
	
	/**
	 * Return setting panels.
	 * 
	 * @var array
	 *
	*/
	public $panels = [];
	
	/**
	 * Return panels setting.
	 * 
	 * @var array
	 *
	*/
	public $settings_array = [];
	
	/**
	 * Return settings config array.
	 * 
	 * @var array
	 *
	*/
	public $config = [];
	
	/**
	 * Return current settings panel assets URL.
	 * 
	 * @var url
	 *
	*/
	private static $assets_url =  '';
	
	/**
	 * Return main scripts framework class.
	 *
	*/
	var $scripts_class;
    
    function __construct(){
    	
    	
    	$this->register_config();
    	
    	self::$assets_url = $this->get_config('plugin_url').'/backend/assets';
    	
    	// Save settings key
    	self::$save_key = "{$this->get_config('id')}-settings_panel";
	    
	    // Save Settings action
	    add_action( 'wp_ajax_'.$this->get_config('id').'_settings_panel_action', array($this,'save_settings') );
	    
	    // PPOM settings migration action, it only used for ppom plugin
    	add_action( 'admin_post_ppom_migrate_settings_panel', array($this, 'ppom_migrate_settings_panel' ) );
		
		add_action( 'admin_menu', array( $this, 'add_admin_menu' ) );
		
		add_action( 'admin_enqueue_scripts', array( $this, 'load_scripts' ), 999 );
		
		add_action('in_admin_header', array( $this, 'remove_admin_notices'), 99);
    	// delete_option('ppom_settings_migration_done');
	}
	
	
	/**
	 * Get class instace
	 */
	public static function get_instance() {
	    
        // create a new object if it doesn't exist.
        is_null(self::$ins) && self::$ins = new self;
        
        return self::$ins;
    }
    
    
    /**
	 * Register config options
	 */
    public function register_config(){
    	
    	$this->config = array(
			'name'               => __( 'PPOM Admin Settings', 'ppom' ),
			'id'                 => 'ppom',
			'version'            => '1.0',
			'form_tag'           => false,
			'menu_type'          => 'wc',
			'menu_title'         =>  __( 'PPOM Settings', 'ppom' ),
			'menu_page_title'    =>  __( 'PPOM Settings', 'ppom' ),
			'menu_slug'          => 'ppom_settings',
			'wc_slug'            => 'wc-settings',
			'menu_capability'    => 'manage_options',
			'menu_parent'        => 'woocommerce',
			'menu_position'      => 50,
			'plugin_name'        => __( 'PPOM', 'ppom' ),
			'plugin_version'     => PPOM_VERSION,
			'plugin_domain'      => 'ppom',
			'plugin_url'         => PPOM_URL,
		);
    }
    
    
    /**
	 * Get conifg option
	 */
    public function get_config($key){
    	
    	$value = '';
    	if (isset($this->config[$key])) {
    		$value = $this->config[$key];
    	}
    	return $value;
    }
	
	
	/**
	 * Register WC settings tab slug
	 */
	public function add_settings_tab( $settings_tabs ) {
    	
        $settings_tabs[$this->get_config('menu_slug')] = $this->get_config('menu_title');

        return $settings_tabs;
    }
	
	
	/**
	 * Render settings panel template
	 */
	function render_settings_panel(){
		
		wp_dequeue_script('woocommerce_settings');
	    
	    self::load_template( "/templates/admin-settings.php", array('tabs' => $this->tabs, 'class_ins' => $this) );
	}
	
	
	/**
	 * Register tabs
	 */
	public function register_tabs($tabs){
		
		if (array_intersect_key($tabs, $this->tabs)) return $this;
		
		$this->tabs = array_merge($this->tabs, $tabs);
		
	    return $this;
	}
	
	
	/**
	 * Register Panels
	 */
	public function register_panel($tab_id, $panels) {
		
		
		// only used for store all Panels on single array
		$this->panels = array_merge($this->panels, $panels);
	
		$existing_panels = !isset($this->tabs[$tab_id]['panels']) ? [] : $this->tabs[$tab_id]['panels'];
		$this->tabs[$tab_id]['panels'] = array_merge($existing_panels, $panels);

		return $this;
	}
	
	
	/**
	 * Register Panel Settings
	 */
	public function register_setting($panel_id, $settings) {
		
		// only used for store all settings on single array
		$this->settings_array = array_merge($this->settings_array, $settings);

		$this->tabs = array_map(function($tab) use ($panel_id, $settings){
					if(isset($tab['panels']) && isset($tab['panels'][$panel_id]) ) {
						$existing_settings = !isset($tab['panels'][$panel_id]['settings']) ? [] : $tab['panels'][$panel_id]['settings'];
						$tab['panels'][$panel_id]['settings'] = array_merge($existing_settings, $settings);
					}
					return $tab;
		}, $this->tabs);
		
		return $this;
	}

	
	/**
	 * Load inputs types
	 */
	public function load_inputs($input_meta){
		
		$type = isset($input_meta['type']) ? $input_meta['type'] : '';
		
		self::load_template("/templates/inputs/{$type}.php", array('input_meta' => $input_meta, 'class_ins' => $this));
	}
	
	
	/**
	 * Control the settings position from given array
	 */
	public static function settings_position_controller($settings){
		
		$new_settings = array();
		foreach ($settings as $index => $value) {
			
			$move_to = isset($value['move_to']) ? $value['move_to'] : '';

			if ($move_to != '') {
				
        		$settings = self::reposition_array_element($settings, $move_to, $index);
			}
		}
		
		return $settings;
	}
	
	
	/**
	 * Move the settings array from one to another position
	 */
	public static function reposition_array_element($arr, $find, $move) {
	    
	    if (!isset($arr[$find], $arr[$move])) { return $arr; }
	
	    $elem = [$move=>$arr[$move]];
	    $start = array_splice($arr, 0, array_search($find, array_keys($arr)));
	    unset($start[$move]);
	    
	    return $start + $elem + $arr;
	}
	
    
    /**
	 * Save all settings action callback
	 */
    function save_settings(){
    	
    	$response = array();
        if (isset($_REQUEST[self::$save_key])) {
        	
            // $settings_meta = $_REQUEST[self::$save_key];
            $settings_meta = array_map(function($setting){
            	
            	$setting = is_array($setting) ? array_map('sanitize_text_field', $setting) : sanitize_text_field($setting);
            	return $setting;
            }, $_REQUEST[self::$save_key]);
            
            
            // Generate and saved css
        	$this->generate_css($settings_meta);
        	
            update_option(self::$save_key, $settings_meta);
            
            $response = array(
            	'status'  => 'success', 
            	'message' => __('Settings saved successfully.', $this->get_config('plugin_domain'))
        	);
           
        }else{
            $response = array(
            	'status'  => 'error' , 
            	'message' => __('Settings saved error.', $this->get_config('plugin_domain'))
        	);
        }
        
        wp_send_json($response);
    }
    
    
    /**
	 * Generate output css
	 */
    function generate_css($settings_meta){
    	
    	$setting_fields = array_intersect_key($this->settings_array, $settings_meta);
    	
    	$ppom_css_output = '';
    	foreach ($settings_meta as $key => $val) {
        	
        	if ($val != '') {
        		$settings = $this->settings_array[$key];
        		$output  = isset($settings['output']) ? $settings['output'] : array();
        		$type    = isset($settings['type']) ? $settings['type'] : '';
        		$mode    = isset($settings['mode']) ? $settings['mode'] : '';
        		$enqueue = isset($settings['enqueue']) ? $settings['enqueue'] : true;
    			
    			if (!$enqueue)  continue;
    			
    			if ($type == 'css_editor') {
    				$css_val = isset($val[$mode]) ? $val[$mode] : '';
					$ppom_css_output .= $this->generate_css_editor_output_css($settings, $css_val);
    			}else if($type == 'typography'){
					$ppom_css_output .= $this->generate_typograpy_output_css($settings, $val);
    			}else if (is_array($output) && !empty($output)) {
			    	foreach ($output as $css_key => $css_selector) {
			    		$ppom_css_output .= $css_selector.'{'.$css_key.':'.$val.' !important;}';
			    	}
    			}
        	}
        }
        
        // update ppom css output
        update_option('ppom_css_output', $ppom_css_output);
    }
    
    
    /**
	 * Get settings meta by Type and ID
	 */
    public function _get($type, $key) {
    	
    	$return = null;
    	switch($type){
    		
    		case 'tabs':
    			$return = isset($this->tabs[$key]) ? $this->tabs[$key] : null;
			break;
    			
    		case 'panels':
    			$return = isset($this->panels[$key]) ? $this->panels[$key] : null;
    		break;
    		
    		case 'settings':
    			$return = isset($this->settings_array[$key]) ? $this->settings_array[$key] : null;
    		break;
    	}
    	
    	return $return;
    }
	
	
	/**
	 * Set name attribute for inputs
	 */
	public static function get_form_name($id){
		
		if (empty($id)) return '';
		
		return self::$save_key."[".esc_attr($id)."]";
	}
	
	
	/**
	 * Get saved settings by ID
	 */
	public static function get_saved_settings($key, $default=null){
		
		$saved_settings = get_option(self::$save_key);
		
		$value = $default != null ? $default : null;
		
		if (isset($saved_settings[$key]) && $saved_settings[$key] != '') {
			$value = $saved_settings[$key];
		}
		
		return $value;
	}
	

    /**
	 * Migration process
	 * It only used for PPOM plugin
	 */
    function ppom_migrate_settings_panel(){
    	
    	$ppom_settings_url = admin_url( 'admin.php');
    	$ppom_settings_url = add_query_arg(
    		array(
    			'page' => 'wc-settings',
    			'tab'  => 'ppom_settings'
    		), 
    		$ppom_settings_url
    	);
    	
    	// if( ppom_settings_migrated() && $old_settings == 'yes' ) return '';
		
		// Migrate to back old settings
		$old_settings = isset($_GET['old_settings']) ? sanitize_text_field($_GET['old_settings']) : '';
		if ($old_settings == 'yes') {
			delete_option('ppom_settings_migration_done');
			
			wp_redirect( $ppom_settings_url ); exit;
		}else{
	        
	        $legacy_values = [];
	        $panel_fields = $this->settings_array;
	        
	        // Getting the keys
	        foreach($panel_fields as $key => $meta){
	            $legacy_values[$key] = get_option($key);
	        }
	        
	        update_option(self::$save_key, $legacy_values);
	        
	        update_option('ppom_settings_migration_done', 1);
	        
	        wp_redirect( $ppom_settings_url ); exit;
		}
    }
	
	
	/**
	 * Get border styles
	 */
	public function border_style(){

		$style = array(
			'none'   => __( 'None', $this->get_config('plugin_domain') ),
			'solid'  => __( 'Solid', $this->get_config('plugin_domain') ),
			'dotted' => __( 'Dotted', $this->get_config('plugin_domain') ),
			'dashed' => __( 'Dashed', $this->get_config('plugin_domain') ),
			'double' => __( 'Double', $this->get_config('plugin_domain') ),
			'groove' => __( 'Groove', $this->get_config('plugin_domain') ),
			'rige'   => __( 'Ridge', $this->get_config('plugin_domain') ),
			'inset'  => __( 'Inset', $this->get_config('plugin_domain') ),
			'outset' => __( 'Outset', $this->get_config('plugin_domain') ),
		);
	
		return $style;
	}
	
	
	/**
	 * Get css editor field options
	 * Border | Padding | Margin
	 */
	public function css_editor_options(){

		$option = array(
			'top'   => array(
				'title' => __( 'Top', $this->get_config('plugin_domain') ),
				'icon'  => 'dashicons dashicons-arrow-up-alt'
			),
			'right'  => array(
				'title' => __( 'Right', $this->get_config('plugin_domain') ),
				'icon'  => 'dashicons dashicons-arrow-right-alt'
			),
			'bottom' => array(
				'title' => __( 'Bottom', $this->get_config('plugin_domain') ),
				'icon'  => 'dashicons dashicons-arrow-down-alt'
			),
			'left' => array(
				'title' => __( 'Left', $this->get_config('plugin_domain') ),
				'icon'  => 'dashicons dashicons-arrow-left-alt'
			),
		);
	
		return $option;
	}
	
	
	/**
	 * Get typography fields options
	 */
	public function typography_options(){

		$option = array(
			'font-size'   => array(
				'title' => __( 'Font Size', $this->get_config('plugin_domain') ),
			),
			'line-height'  => array(
				'title' => __( 'Line Height', $this->get_config('plugin_domain') ),
			),
			'color' => array(
				'title' => __( 'Font Color', $this->get_config('plugin_domain') ),
			),
		);
		
		return $option;
	}
	
	
	/**
	 * Generate CSS Editor CSS output
	 * Border | Padding | Margin
	 */
	public function generate_css_editor_output_css($settings, $css_val){
		
		$css = '';
		$css_prop = '';
		$output = isset($settings['output']) ? $settings['output'] : array();
		$type   = isset($settings['type']) ? $settings['type'] : '';
		$mode   = isset($settings['mode']) ? $settings['mode'] : '';
		
		$border_types = $this->css_editor_options();
		
		foreach ($border_types as $key => $meta) {
			
			if ($mode == 'border') {
				if (isset($css_val[$key], $css_val['style'], $css_val['color']) && $css_val[$key] != '' && $css_val['color'] != '' && $css_val['style'] != 'none') {
					$css_prop .= $mode.'-'.$key.'-width:'.$css_val[$key].'!important;';
				}
				if (isset($css_val[$key], $css_val['style'], $css_val['color']) && $css_val[$key] != '' && $css_val['color'] != '' && $css_val['style'] != 'none') {
					$css_prop .= $mode.'-'.$key.'-color:'.$css_val['color'].'!important;';
				}
				if (isset($css_val[$key], $css_val['style'], $css_val['color']) && $css_val[$key] != '' && $css_val['color'] != '' && $css_val['style'] != 'none') {
					$css_prop .= $mode.'-'.$key.'-style:'.$css_val['style'].'!important;';
				}
			}else{
				if (isset($css_val[$key]) && $css_val[$key] != '') {
					$css_prop .= $mode.'-'.$key.':'.$css_val[$key].'!important;';
				}
			}
		}
		
		if ($css_prop != '') {
			$css .= $output.'{'.$css_prop.'}';
		}
		
		return $css;
	}
	
	
	public function generate_typograpy_output_css($settings, $css_val){
		
		$css = '';
		$css_prop = '';
		$output = isset($settings['output']) ? $settings['output'] : array();
		$type   = isset($settings['type']) ? $settings['type'] : '';
		$mode   = isset($settings['mode']) ? $settings['mode'] : '';
		
		$options = $this->typography_options();
		
		foreach ($options as $key => $meta) {
			if (isset($css_val[$key]) && $css_val[$key] != '') {
				$css_prop .= $key.':'.$css_val[$key].'!important;';
			}
		}
		
		if ($css_prop != '') {
			$css .= $output.'{'.$css_prop.'}';
		}
		
		return $css;
	}
	
	
	/**
	 * Load settings panel templates
	 */
	public static function load_template($file_name, $variables=array('')){

		if( is_array($variables))
	    extract( $variables );
	    
	   $file_path =  PPOM_PATH . '/backend/'.$file_name;

	   if( file_exists($file_path))
	   	include ($file_path);
	   else
	   	die('File not found'.$file_path);
	}
	
	
	/**
	 * Register plugin Settings page
	*/
	public function add_admin_menu() {

		if ( $this->get_config('menu_type') === 'menu' ) {

			$menu = add_menu_page(
				$this->get_config('menu_page_title'),
				$this->get_config('menu_title'),
				$this->get_config('menu_capability'),
				$this->get_config('menu_slug'),
				array( $this, 'render_settings_panel' ),
				$this->get_config('menu_icon'),
				$this->get_config('menu_position')
			);

		} else if($this->get_config('menu_type') === 'submenu' ) {

			$menu = add_submenu_page(
				$this->get_config('menu_parent'),
				$this->get_config('menu_page_title'),
				$this->get_config('menu_title'),
				$this->get_config('menu_capability'),
				$this->get_config('menu_slug'),
                array( $this, 'render_settings_panel' ),
                $this->get_config('menu_position')
			);
		}else{
			
			// It only used for ppom settings ppom_settings_migrated()
			if( ppom_settings_migrated() ) {
	    		add_filter( 'woocommerce_settings_tabs_array', array($this, 'add_settings_tab'), 50 );
	    		add_action( 'woocommerce_settings_tabs_ppom_settings', array($this, 'render_settings_panel') );
			}
		}
	}
	
	
	/**
	 * Register settings panel scripts
	*/
	function get_scripts(){
		
		$register_scripts = array(
			'nmsf-notifications-lib' => array(
				'src'     => self::$assets_url.'/notifications/notifications.js',
				'deps'    => array( 'jquery' ),
				'version' => '1.0',
			),
			'nmsf-tooltip-lib' => array(
				'src'     => self::$assets_url.'/tooltip/tooltip.js',
				'deps'    => array( 'jquery' ),
				'version' => '1.0',
			),
			'nmsf-videopopup-lib' => array(
				'src'     => self::$assets_url."/videopopup/videopopup.js",
				'deps'    => array( 'jquery' ),
				'version' => $this->get_config('plugin_version'),
			),
			'nmsf-deps-lib' => array(
				'src'     => self::$assets_url.'/deps.js',
				'deps'    => array( 'jquery' ),
				'version' => '1.0',
			),
			'nmsf-settings-panel' => array(
				'src'     => self::$assets_url.'/settings.js',
				'deps'    => array( 'jquery' ),
				'version' => '1.0',
			),
			'nmsf-wpcolorpicker-alpha' => array(
				'src'     => self::$assets_url.'/wp-color-picker-alpha.min.js',
				'deps'    => array( 'jquery' ),
				'version' => '1.0',
			),
		);
		
		return apply_filters('ppom_admin_global_settings_scripts_before_register', $register_scripts);
	}
	
	
	/**
	 * Register settings panel styles
	*/
	function get_styles(){
		
		$register_styles = array(
			'nmsf-notifications-lib' => array(
				'src'     => self::$assets_url.'/notifications/notifications.css',
				'deps'    => array(),
				'version' => $this->get_config('plugin_version'),
			),
			'nmsf-tooltip-lib' => array(
				'src'     => self::$assets_url.'/tooltip/tooltip.css',
				'deps'    => array(),
				'version' => $this->get_config('plugin_version'),
			),
			'nmsf-videopopup-lib' => array(
				'src'     => self::$assets_url."/videopopup/videopopup.css",
				'deps'    => array(),
				'version' => '4.0.0',
			),
			'nmsf-grid-lib' => array(
				'src'     => self::$assets_url.'/grid-layout.css',
				'deps'    => array(),
				'version' => '4.0.0',
			),
			'nmsf-settings-panel' => array(
				'src'     => self::$assets_url.'/settings.css',
				'deps'    => array(),
				'version' => '4.0.0',
			),
		);
		
		return apply_filters('ppom_admin_global_settings_styles_before_register', $register_styles);
	}
	
	
	/**
	 * Load styles/scripts on settings page
	*/
	public function load_scripts(){
		
		$is_settings_page = $this->is_settings_page();
		
		if (!$is_settings_page) return '';
		
		$all_scripts = $this-> get_scripts();
		$all_styles  = $this-> get_styles();
		
		// Register all styles & scripts
		PPOM_SCRIPTS::register_scripts($all_scripts);
		PPOM_SCRIPTS::register_styles($all_styles);
	    
	    // WP color picker
	    PPOM_SCRIPTS::enqueue_style( 'wp-color-picker' );
		PPOM_SCRIPTS::enqueue_script( 'wp-color-picker' );
		PPOM_SCRIPTS::enqueue_script( 'nmsf-wpcolorpicker-alpha' );
	    
	   // Alert notification library
	    PPOM_SCRIPTS::enqueue_style( 'nmsf-notifications-lib' );
		PPOM_SCRIPTS::enqueue_script( 'nmsf-notifications-lib' );
	    
	    // Powertip tooltip library	
		PPOM_SCRIPTS::enqueue_style( 'nmsf-tooltip-lib' );
		PPOM_SCRIPTS::enqueue_script( 'nmsf-tooltip-lib' );
		
		// Videopopup library	
		PPOM_SCRIPTS::enqueue_style( 'nmsf-videopopup-lib' );
		PPOM_SCRIPTS::enqueue_script( 'nmsf-videopopup-lib' );
		
		// nmsf grid library	
		PPOM_SCRIPTS::enqueue_style( 'nmsf-grid-lib' );
		
		// Condition base settings library	
		PPOM_SCRIPTS::enqueue_script( 'nmsf-deps-lib' );
		
        // Settings panel scripts
		PPOM_SCRIPTS::enqueue_style( 'nmsf-settings-panel' );
		PPOM_SCRIPTS::enqueue_script( 'nmsf-settings-panel' );
    	
    	$this->set_localize_data('nmsf-settings-panel', 'nmsf_vars');
	}
	
	
	/**
	 * Localize scripts data
	*/
	public function set_localize_data($handle, $var_name, $js_vars=array(), $global_js_vars=array()){
		
		switch ($handle) {
			
			case 'nmsf-settings-panel':
			    
				$localize_data = [
        		   'migrate_back_msg' => __('Are you sure?', $this->get_config('plugin_domain'))
    		    ];
				
				break;
		}
		
		$localize_data = array_merge($js_vars, $localize_data, $global_js_vars);
	
		$localize_data = apply_filters( 'ppom_get_admin_global_settings_localize_script_data', $localize_data, $handle );

		PPOM_SCRIPTS::localize_script( $handle, $var_name, $localize_data );
	}
	
	
	/**
	 * Remove all admin notices
	*/
	function remove_admin_notices(){
		
		$is_settings_page = $this->is_settings_page();
		
		if ($is_settings_page) {
			remove_all_actions( 'user_admin_notices' );
			remove_all_actions( 'admin_notices' );
    	}
	}
	
	
	/**
	 * Is admin settings page
	*/
	function is_settings_page(){
		
		$current_screen = get_current_screen();
		
		$id = substr( $current_screen->id, - strlen( $this->get_config('menu_slug') ) );
		$is_settings_page = false;
		
		switch ($this->get_config('menu_type')) {
			case 'wc':
				if (isset($_GET['page'], $_GET['tab']) && $_GET['page'] == 'wc-settings' && $_GET['tab'] == $this->get_config('menu_slug') && ppom_settings_migrated()) {
					$is_settings_page=true;
				}
				break;
			
			default:
				if ($id == $this->get_config('menu_slug')) {
					$is_settings_page=true;
				}
				break;
		}
		
		return $is_settings_page;
	}
	
	
    function insert_at($array = [], $item = [], $position = 0) {
	    $previous_items = array_slice($array, 0, $position, true);
	    $next_items     = array_slice($array, $position, NULL, true);
	    return $previous_items + $item + $next_items;
	}
}

PPOMSETTINGS();
function PPOMSETTINGS() {
	return PPOM_SettingsFramework::get_instance();
}