<?php 
/* This file is not called from WordPress. We don't like that. */
! defined( 'ABSPATH' ) and exit;

/**
 * Yeahthemes Theme Options Interface
 *
 * @package     WordPress
 * @subpackage  framework/admin/includes
 * @since       1.0.0
 * @author      Yeahthemes
 */


/**********************************************************************************************************
 *        __   _______    _    _   _ _____ _   _ _____ __  __ _____ ____         ____ ___  __  __
 *        \ \ / / ____|  / \  | | | |_   _| | | | ____|  \/  | ____/ ___|       / ___/ _ \|  \/  |
 *         \ V /|  _|   / _ \ | |_| | | | | |_| |  _| | |\/| |  _| \___ \      | |  | | | | |\/| |
 *          | | | |___ / ___ \|  _  | | | |  _  | |___| |  | | |___ ___) |  _  | |__| |_| | |  | |
 *          |_| |_____/_/   \_\_| |_| |_| |_| |_|_____|_|  |_|_____|____/  (_)  \____\___/|_|  |_|
 *
 *				  		Premium WordPress Themes by YeahThemes.com - http://Yeahthemes.com
 *												Copyright (c) YeahThemes
 *											http://themeforest.net/user/Manh
 *
 * 									-------------------------------------------
 * 												DO NOT EDIT THIS FILE
 *
 **********************************************************************************************************/


if ( ! class_exists( 'YT_Options_Framework' ) ) {
	
class YT_Options_Framework {
	
	/**
	 * Prefix
	 *
	 * prepending before actions/filters
	 */
	public $_prefix = 'yt_';
	/**
	 * Option array
	 */
	public $_option_array = array();
	
	/**
	 * Option data
	 */
	public $_option_data;
	
	/**
	 * Function for adding setting page to Administration Menus:
	 * Checkout some type of position at:
	 * 
	 * http://codex.wordpress.org/Adding_Administration_Menus#Function_Reference
	 *
	 * Default: add_theme_page
	 */
	public $_menu_function = 'add_menu_page';
	
	/**
	 * Menu Parameters for $_menu_function
	 */
	public $_menu_args = array();
	
	/**
	 * Menu slug : The slug name to refer to this menu by
	 *
	 * Eg: your-option-page
	 * Your option page will be wp-admin/admin.php?page=your-option-page
	 */
	public $_menu_slug = '';
	
	/**
	 * Hide shortcut link from admin menu bar if false
	 */
	public $_admin_bar = true;
	
	public $_admin_bar_title = '';
	
	/**
	 * Option name
	 *
	 * The name of the constant should be UPPPERCASE. Only Alphanumeric and underscore (_) are allowed 
	 * @example: YEAHTHEMES_THEME_OPTIONS
	 * @usge:  	whole data: $my_data = get_option( YEAHTHEMES_THEME_OPTIONS );
	 * 				single id : $my_data['id']
	 */
	public $_option_name = '';
	
	public $_heading = '';
	
	/**
	 * Option backup name
	 */
	public $_option_name_backups = '';
	
	/**
	 * Option slug
	 *
	 * This will be taken from $_option_name in lowercase
	 */
	public $_option_name_slug = '';
	/**
	 * Options machine
	 */
	public $_options_machine;
	
	/**
	 * Options machine things
	 * 
	 * |-- Option Menus
	 * |-- Option fields
	 * |-- Option default values
	 */
	public $_option_menus;
	public $_option_fields;
	public $_option_defaults;
	
	/**
	 * WPML defaults variables
	 */
	 
	public $_current_lang;

	/**
	 * Allowed tags
	 */
	public $allowed_tags = array(
		'a' => array(
	        'href' => array(),
	        'title' => array(),
	        'class' => array(),
			'style' => array(),
			'target' => array()
	    ),
		'strong' => array(
			'class' => array(),
		),
		'div' => array(
			'class' => array(),
			'style' => array()
		),
		'p' => array(
			'class' => array(),
			'style' => array()
		),
		'b' => array(),
		'em' => array(),
		'br' => array(),
		'i' => array(
			'class' => array(),
			'style' => array()
		),
		'img'  => array(
			'class' => array(),
			'src' => array(),
			'style' => array()
		),
		'pre'  => array(
			'class' => array(),
			'style' => array()
		)

	);
	
	/**
     * PHP5 constructor method.
     *
     * @return    void
     *
     * @access    public
     * @since     1.0.0
     */
	public function __construct() {
		
	}
	
	/**
	 * Init function
	 *
	 * @param     array   	$args
	 * @return    void
	 *
	 * @access    public
	 * @since     1.0.0
	 */
	public function init( $args = array() ){

		if( !current_user_can( 'edit_theme_options' ) )
			return;
		
		/**
		 * This is for WPML, use option for current language individually
		 * If WMPL language is exists, assigns _default_lang to WML default language 
		 */
		
		global $sitepress;	

		/*Define theme option key constant*/
		if( defined( 'ICL_LANGUAGE_CODE' ) && is_a( $sitepress, 'SitePress') && ICL_LANGUAGE_CODE !== $sitepress->get_default_language() ) {
			
			$this->_current_lang = ICL_LANGUAGE_CODE;
			
		}
		
		/**
		 * If option name is nt empty
		 * Declare properties
		 */
		if( !empty( $args['option_name'] ) ){
			
			$this->_option_name = $args['option_name'];
			$this->_option_name_backups = '_backup';
			$this->_option_name_slug = self::clean_string( $this->_option_name );
			$this->_prefix = !empty( $args['prefix'] ) ? self::clean_string( $args['prefix'], '-', '_' ) : $this->_prefix; 
			
			/*Assigns $_menu_function to add option link to admin menu*/
			if( !empty( $args['menu_function'] ) ){
				
				$this->_menu_function = $args['menu_function'];
				
			}
			/**
			 * If 
			 */
			if( is_array( $args['menu_args'] ) && !empty( $args['menu_args'] ) ){
				
				$default_menu_args = array( 
					
					'page_title' 	=> '',
					'menu_title' 	=> '',
					'capability' 	=> '',
					'menu_slug' 	=> '',
					'function' 	=> array( $this, 'load_template' ),
					'icon_url'		=> '',
					'position'		=> ''
				
				);
				
				$default_submenu_args = array( 
					'parent_slug' 	=> '',
					'page_title' 	=> '',
					'menu_title' 	=> '',
					'capability' 	=> '',
					'menu_slug' 	=> '',
					'function' 	=> array( $this, 'load_template' ),
				
				);
				
				$temp_menu_args = array();
				
				if( in_array( $this->_menu_function, array( 
					'add_menu_page',
					'add_object_page',
					'add_utility_page',
					
					'add_dashboard_page', 
					'add_posts_page', 
					'add_media_page', 
					'add_links_page',
					'add_comments_page',
					'add_theme_page',
					'add_plugins_page',
					'add_users_page',
					'add_management_page',
					'add_options_page' 
				) ) ){
					
					$temp_menu_args = $default_menu_args;
						
				}elseif( $this->_menu_function == 'add_submenu_page' ){
					
					$temp_menu_args = $default_submenu_args;
					
				}
				
				
				foreach( $args['menu_args'] as $k => $v ){
					
					if( isset( $temp_menu_args[$k] ) && $v ){
						
						
						/*Assigns current lang to Admin menu title*/
						if( 'menu_title' == $k && $this->_current_lang ){
							
							$temp_menu_args[$k] = $v . ' (' . strtoupper( $this->_current_lang ) . ')';
							
						}else{
							
							$temp_menu_args[$k] = $v;
						
						}
					}
						
				}
				
				$this->_menu_args = $temp_menu_args ;
			
			}
			
			/* Assigns _admin_bar value */
			if( isset( $args['admin_bar'] ) && $this->_admin_bar !== $args['admin_bar'] ){
				
				$this->_admin_bar	= ( bool ) $args['admin_bar'];
				
			}
			
			if( !empty( $args['admin_bar_title'] ) ){
			
				$this->_admin_bar_title = $args['admin_bar_title'];
			
			}
			
			/* Assigns _menu_slug value */
			if( is_array( $this->_menu_args ) ){
				
				$temp_args = $this->_menu_args;
				$this->_menu_slug = $temp_args['menu_slug'] ? self::clean_string( $temp_args['menu_slug'] ) : self::clean_string( $this->_option_name_slug, '_', '-' ) ;
			}
		
		/*Else return*/
		}else{
		
			return;	
		
		}
		
		/*Option Heading title*/
		$this->_heading = !empty( $args['heading'] ) ? $args['heading'] : $this->_option_name;
		
		/*Assigning prefix*/
		if( !empty( $args['prefix'] ) ){
			
			$this->_prefix = $args['prefix'];
			
		}
		
		/**
		 * Assign $_option_array
		 */
		if( !empty( $args['option_fields'] ) ){
			
			$this->_option_array = $args['option_fields'];
			
		}
		
		/**
		 * Calls action hooks
		 */
		$this->action_hooks();
		
		
	}
	
	/**
	 * Aaction_hooks
	 *
	 * @since 1.0.0
	 */
	public function action_hooks(){
		
		if ( is_admin() ) {
		
			add_action( 'admin_init', array( $this, 'admin_init' ), 10, 2  );
			add_action( 'admin_head', array( $this, 'admin_message' ), 10, 2 );

			add_action( 'admin_menu', array( $this, 'render_admin_option_page' ) );
			
			
			/**
			 * AJAX Saving Options
			 *0
			 * @since 1.0.0
			 */
			add_action( 'wp_ajax_yt_ajax_save_options', array( $this, 'ajax_save' ) );
		}
		
		add_action( 'admin_bar_menu', array( $this, 'admin_bar_menu_shortcuts'),30);
		
		
	}
	/**
	 * Admin Init
	 *
	 *
	 * @since 1.0.0
	 */
	 
	public function admin_init(){
		
		$options_machine = $this->_options_machine;
		
		/**
		 * Store default values for the first time
		 */
		if ( is_admin() && ( false === get_option( $this->_option_name ) || '' === get_option( $this->_option_name ) || !$this->get_options( '_init_options_time' ) ) ) {
			
			$options_machine = $this->options_generator( $this->_option_array );
			$this->set_options( $options_machine['defaults'] );
			$this->set_options( date('r'), '_init_options_time' );
		
			$this->_options_machine = $options_machine;


			
		}

	}
	
	/**
	 * Change activation message
	 *
	 * @since 1.0.0
	 */
	public function admin_message() { 
		
		
	}
	
	/**
	 * Create Options page
	 *
	 * @uses add_theme_page()
	 * @uses add_action()
	 *
	 * @since 1.0.0 
	 */
	public function render_admin_option_page() {
		
		if( !empty( $this->_menu_function ) ){
			
			
			/* Filtering the associative array*/
			$args = array_values( $this->_menu_args ) ;
			
			/* Adding option link to WordPress menu using user-defined args*/
			$option_page =  call_user_func_array( $this->_menu_function,  $args );
			
			
			// Add framework functionaily to the head individually
			add_action("admin_print_scripts-$option_page", array( &$this, 'load_scripts' ) );
			add_action("admin_print_styles", array( &$this, 'load_styles' ) );
	
		}
	}
	
	/**
	 * Load style
	 * @since 1.0.0 
	 */
	public function load_styles(){
		
		do_action( $this->_prefix . 'before_load_styles');

		wp_enqueue_style('yt-admin-style', YEAHTHEMES_FRAMEWORK_URI . 'admin/assets/css/admin-style.css');		
		wp_enqueue_style('yt-jqueryui', 	YEAHTHEMES_FRAMEWORK_URI . "admin/assets/css/jqueryui.custom.css");
		wp_enqueue_style( 'wp-color-picker' );
		
		do_action( $this->_prefix . 'after_load_styles');
		
	}
	
	/**
	 * Load scripts
	 * @since 1.0.0
	 */
	public function load_scripts() {
		
		$suffix = defined('SCRIPT_DEBUG') && SCRIPT_DEBUG ? '' : '.min';

		do_action( $this->_prefix . 'before_load_scripts');
		
		wp_enqueue_script('yt-plugins', 	YEAHTHEMES_FRAMEWORK_URI . "admin/assets/js/yeahthemes.plugins{$suffix}.js", array( 'jquery' ), '1.0', true);
		wp_enqueue_script('yt-scripts', 	YEAHTHEMES_FRAMEWORK_URI . "admin/assets/js/yeahthemes{$suffix}.js", array( 'jquery', 'jquery-ui-core', 'jquery-ui-sortable', 'jquery-ui-draggable', 'jquery-ui-droppable', 'jquery-ui-autocomplete', 'jquery-ui-slider', 'jquery-ui-datepicker', 'wp-color-picker', 'yt-plugins' ), '1.0', true);
		wp_enqueue_media();

		/*Prevent duplicating translation string*/
		static $params = null;

		if( null == $params){
			$params = apply_filters( 'yt_options_framework_vars', array( ) );
			wp_localize_script('yt-scripts', 'yt_optionsVars', $params );
		}
		/* Do action after loaing scripts*/
		do_action( $this->_prefix . 'after_load_scripts');
	}
	
	/**
	 * Option page template
	 *
	 * @since 1.0.0
	 */
	public function load_template(){
		
		/**
		 * Assigns $_option_data
		 */
		$this->_option_data = $this->get_options();
		
		$options_machine = $this->options_generator( $this->_option_array );
	
		/**
		 * Assigns data for options machine
		 */
		$this->_options_machine = $options_machine;
		
		$this->_option_defaults = $options_machine['defaults'];
		$this->_option_fields = $options_machine['fields'];
		$this->_option_menus = $options_machine['menus'];
		
		
		include_once( YEAHTHEMES_FRAMEWORK_DIR . 'admin/includes/yt-options-frontend.php' );
	
	}
	
	/**
	 * Add's new global menu, if $href is false menu is added but registred as submenuable
	 *
	 * $name String
	 * $id String
	 * $href Bool/String
	 *
	 * @return void
	 * @since 1.0.0
	 */
	public function admin_bar_add_root_menu($name, $id, $href = false){
		global $wp_admin_bar;
		
		if ( !is_admin_bar_showing() )
			return;
		if( !$href ){
			$href = admin_url('admin.php?page=' . $this->_menu_slug );
		}
		
		$wp_admin_bar->add_menu( 
			array(
				'id' => $id,
				'title' => $name,
				'href' => $href 
			)
		);
	}
	/**
    * Add's new submenu where additinal $meta specifies class, id, target or onclick parameters
    *
    * $name String
    * $link String
    * $root_menu String
    * $meta Array
    *
    * @return void
	* @since 1.0.0
    **/
	public function admin_bar_add_sub_menu($name, $link, $id = null, $root_menu, $meta = FALSE){
		
		global $wp_admin_bar;
		
		if ( !is_admin_bar_showing() )
			return;

		$wp_admin_bar->add_menu( 
			array(
				'parent' => $root_menu,
				'id' => $id,
				'title' => $name,
				'href' => $link,
				'meta' => $meta
			)
		);
		
	}
	
	/**
	 * Add theme option links
	 * @since 1.0.0
	 */
	public function admin_bar_menu_shortcuts() {
		
		if( $this->_admin_bar && $this->_menu_slug && $this->_admin_bar_title){
			
			$this->admin_bar_add_root_menu( $this->_admin_bar_title , $this->_menu_slug );
		} 
		/*
		$this->admin_bar_add_sub_menu( __('Documentation', 'yeahthemes'), 'http://www.facebook.com/pages/manage', 'yt-documentation', 'yt-theme-options' );
		*/
	}
	
	/**
	 * Get options from the database and process them with the load filter hook.
	 *
	 * @since 1.0
	 * @return array
	 */
	
	/* Handy get_options*/
	public function get_options( $id = null ){
		
		return $this->fetch_options( $this->_option_name, $id );
	
	}
	
	public function fetch_options( $name = null, $id = null ) {
		
		
		if( empty( $name ) ){
		
			$name = $this->_option_name;
		}
		
		$options_data = get_option( $name );
		
		/*Get single option value by key*/
		if( $id != null ){
			
			$data = isset( $options_data[$id] ) ? $options_data[$id] : '';
			
		}else{
			/*return the whole data*/
			$data = $options_data;
				
		}
		
		$data = apply_filters( $this->_prefix . 'before_return_option_data', $data );
		
		do_action( $this->_prefix . '_before_option_data_return', $data );
		
		return $data;
	
	}
	
	/**
	 * Add's new global menu, if $href is false menu is added but registred as submenuable
	 *
	 * $name String
	 * $id String
	 * $href Bool/String
	 *
	 * @return void
	 * @since 1.0.0
	 */
	 
	/* Handy set_options*/
	public function set_options( $data, $id = null ){
		
		if ( empty( $data ) ){
			return;	
		}
		
		$this->save_options( $this->_option_name, $data, $id );
	
	}
	
	public function save_options( $name = '', $data, $id = null ){
		
		if ( empty( $data ) ){
			return;	
		}
		
		if( empty( $name ) ){
			
			$name = $this->_option_name ;
		}
		
		/* Apply filler data before saving*/
		$data = apply_filters( $this->_prefix . 'before_save_option_data', $data );
		
		do_action( $this->_prefix . 'before_option_data_save', $data );
		
		$options_data = get_option( $name );
		
		$unset_array = apply_filters( $this->_prefix . 'unset_before_save_option_data', array() );
		
		if( !empty( $unset_array ) ){
			
			foreach( $unset_array as $unset_k){
				
				unset( $data[ $unset_k ]);		
				
			}
	
		}
		
		/*Update single option by id*/
		if( $id != null ){
			
			$options_data[$id] = $data;
			
			update_option( $name, $options_data );
			
		}else{
			
			if( is_array( $data ) ){


				foreach ( $data as $k => $v ) {
					
					//if( empty( $k ) ) return;
					
					if ( !isset( $options_data[$k] ) || $options_data[$k] != $v ) {
						
						$options_data[$k] = $v;
					
					}elseif( is_array( $v ) ){
						
						foreach ( $v as $key => $val ) {
							
							if ( $key != $k && $v[$key] == $val) {
								
								$options_data[$k] = $v;
					
								break;
								
							}
							
						}
					}
						
				}
			}
			//unset($options_data[])
			update_option( $name, $options_data );
				
		}
		
		do_action( $this->_prefix . 'after_option_data_saved', $options_data );
		
	}
	/* Delete Options*/
	public function delete_options( $name,  $keys = array(), $exclude = true  ){
		
		if( empty( $name ) ){
			
			$name = $this->_option_name ;
		}
		
		$data = $this->fetch_options( $name );
		$temp_data = array();
		
		
		/* If type = exclude */
		if( $exclude ){
		
			delete_option( $name );
			
			if( !empty( $keys ) ){
				
				foreach( ( array ) $data as $k => $v ){
					
					if( in_array( $k, $keys) ){
						
						$temp_data[$k] = $v;
						
					}
				}
				
				$this->save_options( $name, $temp_data );
					
			}
		
		}else{
			
			$temp_data = $data;
			
			if( !empty( $keys ) ){
				
				delete_option( $name );
			
				foreach( ( array ) $temp_data as $k => $v ){
					
					if( in_array( $k, $keys) ){
						
						unset( $temp_data[$k] );
						
					}
				
				}
			
			}
			
			$this->save_options( $name, $temp_data );
			
			
		}
	}

	
	/**
	 * Ajax Save Options
	 *
	 * @since 1.0.0
	 */
	 
	public function ajax_save() { 
		
		if( empty( $_POST['security'] )) die('-1'); 

		$nonce = $_POST['security'];

		$action = 'yt-options-ajaxify-saving-data';

		$adminurl = strtolower( admin_url() );
		$referer = strtolower( wp_get_referer() );
		$result = !empty( $nonce ) ? wp_verify_nonce( $nonce , $action) : false;

		if ( !$result && !(-1 == $action && strpos( $referer, $adminurl) === 0) ) {
			die( '-1' );
		}
		
		//check_ajax_referer('yt-options-ajaxify-saving-data', 'security');
		//if (! wp_verify_nonce( $nonce, 'yt-options-ajaxify-saving-data') ) die('-1'); 
		
		/*Save type from ajax request*/
		$save_type = $_POST['type'];
		
		/*key name from ajax request*/
		$option_key = $_POST['key'];
		
		$prefix =  $_POST['prefix'];
				
		/*get options array from db*/
		$options_data = $this->fetch_options( $option_key );
		$backup_name = $option_key . $this->_option_name_backups;
		
		
		if( 'backup_options' == $save_type ){
			
			$backup = $options_data;
			$backup['_backup_log'] = date('r');
			//unset( $backup['_init_options_time'] );
			
			//$this->delete_options( $option_key, array( $this->_option_name_backups ), false );
			
			if ( get_option( $backup_name ) !== false ) {
				$this->save_options( $backup_name, $backup );
			}else{
				add_option( $backup_name, $backup );
			}
			
			//$this->save_options( $option_key, $backup, $this->_option_name_backups );
				
			die('1'); 
			
		}
		elseif( 'restore_options' == $save_type ){
				
			$data = $this->fetch_options( $backup_name );
			
			if( !empty( $data ) ){

				$this->save_options( $option_key, $data);
				
				do_action( $prefix . 'after_update_options',  $data );

				
			}
			
			die('1'); 
			
		}
		elseif( 'import_options' == $save_type ){
	
			$import_data = self::helper_decode( $_POST['data'] );
			
			$data = maybe_unserialize( $import_data );
			
			//die($data);
			
			$this->save_options( $option_key, $data );
			
			do_action( $prefix . 'after_update_options',  $data );

			
			
			die('1'); 
		}
		elseif ( 'save' == $save_type ){
			
			wp_parse_str( self::helper_stripslashes( $_POST['data'] ), $options_data );
			
			unset( $options_data['security'] );			
			
			$this->save_options( $option_key, $options_data );
			
			do_action( $prefix . 'after_update_options',  $options_data );

			
			
			die('1');
			
		}
		elseif ( 'reset' == $save_type ){
			
			$default_data = self::helper_decode( $_POST['data'] );
			
			$default_data = maybe_unserialize( $default_data );
			
			$this->delete_options( $option_key, array( $this->_option_name_backups ) );
			$this->save_options( $option_key, $default_data );
			
			do_action( $prefix . 'after_update_options',  $default_data );

			
			
			die('1'); //options reset
			
		}
	
		die();
	}
	
	/** 
	 * normalize option
	 *
	 * Normalize & returns default values if don't exist
	 * 
	 * Notes:
	 * 	- For further uses, you can check for the $field['type'] and performs
	 *	  more speficic sanitization on the option
	 *	- The ultimate objective of this function is to prevent the "undefined index"
	 *	  errors some authors are having due to malformed options array
	 */
	static function normalize( $field ) {
		$defaults = array(
			'name' 		=> '',
			'desc' 		=> '',
			'std' 		=> '',
			'type' 		=> '',
			'settings'	=> array()
		);

		$field = wp_parse_args( $field, $defaults );

		return $field;
	}
	
	/**
	 * Process options data and build option fields
	 *
	 * @uses get_option()
	 *
	 * @access public
	 * @since 1.0.0
	 *
	 * @return array
	 */
	private function options_generator( $options ) {
	
		$yt_output = '';
		$yt_details;
		$options_data = array();
		$options_data = $this->_option_data;
		//print_r($options_data);

		
		if ( empty( $options ) )
			return;
			
		/*if ( empty( $option_data ) )
			$yt_data = yt_get_options();*/

		$defaults = array();   
	    $_counter = 0;
		$menu = '';
		$output = '';
		$update_data = false;
		$headings = array();
		
		do_action( $this->_prefix . 'options_generator_before_loop',
			array(
				'options'	=> $options,
				'data'		=> $options_data,
				'defaults'	=> $defaults,
				'menu'		=> $menu,
				'output'	=> $output
			)
		);
		
		/*Nested Tab*/
		
		$nested_tab_array = array();
		$tab_parent_heading;
		$tab_sub_heading;
		$tab_combined_heading;
		$tab_break_counter = 0;
		
		foreach ( $options as $k => $v ) {
			
			if ( in_array( $v['type'], array( 'heading', 'subheading' ) ) ) {
				
				$tab_break_counter = 0;
				
				$headings[] = $v;

				//$heading
				if('heading' == $v['type']){
					$tab_sub_heading = '';
					$tab_parent_heading = self::clean_string( $v['name'], ' ', '');
					
					
				}else{

					//$tab_parent_heading = self::clean_string( $v['name'], ' ', '') . '-' . $tab_parent_heading;
					$tab_sub_heading = self::clean_string( $v['name'], ' ', '') . '-' . $tab_parent_heading;
					//print_r( $tab_sub_heading .'=====');
				}
				
			}elseif( 'tab' == $v['type'] ){
				
				$tab_combined_heading = $tab_sub_heading ? $tab_sub_heading : $tab_parent_heading;
				//print_r( $tab_parent_heading.'////////');
				
				$nested_tab_array[$tab_combined_heading . '_' . $tab_break_counter ][] = $v['name'];
				
			}elseif( 'tab_break' == $v['type'] ){
				
				$tab_break_counter++;
				
			}
			
		}
		
		
		$prev_heading_key = '';
		
		foreach ( $headings as $k => $v ) {
			
			$token = 'yt-option-' . self::clean_string( $v['name'], ' ' ,'');
			
			// Capture the token.
			$v['token'] = $token;
			
			if ( $v['type'] == 'heading' ) {
				
				$menu_items[$token] = $v;
				$prev_heading_key = $token;
				
			}
			
			if ( $v['type'] == 'subheading' ) {
				
				$menu_items[$prev_heading_key]['children'][] = $v;
			}
			
		}
		
		$parent_class = '';
		$sub_parent_class = '';
		$separator_class = '';
		$tab_break_loop_counter = 0;
		
		
		$tab_count = 0;
		foreach ( $options as $field ) {
		
			// sanitize option
			if ( !in_array( $field['type'], array( 'heading', 'subheading' ) ) ) {
			
				$field = self::normalize( $field );
			
			}
			
			$_counter++;
			$val = '';
			
			
			if( 'tab' == $field['type'] ){
				$tab_count++;
			}
			
			//create array of defaults		
			if ( $field['type'] == 'multicheck' ){
				
				if ( is_array($field['std'] ) ){
					
					$defaults[$field['id']] = $field['std'];
					
				} else {
					
					$defaults[$field['id']][$field['std']] = true;
				}
				
			} elseif( !in_array( $field['type'], apply_filters( $this->_prefix . 'exclude_default_option_type_data', array( 'heading', 'subheading', 'separator', 'info', 'tab', 'tab_break', 'transfer', 'backup' ) ) ) ) {
				
				if ( isset( $field['id'] ) ) {
					
					$defaults[$field['id']] = $field['std'];
					
				}
			
			}
			
			$defaults = apply_filters( $this->_prefix . 'option_default_data', $defaults, $field );
				
			/* condition start */
			if( !empty( $options_data ) ){
				
				if ( array_key_exists('id', $field ) && !isset( $options_data[$field['id']] ) ) {
					
					$options_data[$field['id']] = $field['std'];
					
					if ( $field['type'] == 'checkbox' && ( $field['std'] == 0 || $field['std'] == '' ) ) {
						
						$options_data[$field['id']] = '';
						
					} else {
						
						$update_data = true;
						
					}
					
				}
				
				if ( array_key_exists('id', $field) && !isset( $yt_details[$field['id']] ) ) {
				
					$yt_details[$field['id']] = $options_data[$field['id']];
				
				}
				
				if ( in_array( $field['type'], array( 'tab' ) ) ) { 
					
					
				
				}


				/* build the arguments array */
				$_args = apply_filters( $this->_prefix . 'option_field_args', array(
					'name'        			=> $field['name'],
					'type'        			=> $field['type'],
					'id'          			=> isset( $field['id'] ) ? $field['id'] : '',
					'value'       			=> !empty($field['value'] ) ? $field['value'] : ( isset( $field['id'] ) ? $options_data[$field['id']] : '' ),
					'desc'        			=> isset( $field['desc'] ) ? $field['desc'] : '',
					'std'         			=> isset( $field['std'] ) ? $field['std'] : '',
					'class'       			=> isset( $field['class'] ) ? $field['class'] : '',
					'options'    			=> isset( $field['options'] ) && !empty( $field['options'] ) ? $field['options'] : array(),
					'settings'				=> isset( $field['settings'] ) ? $field['settings'] : array(),
					
				) );
				
				//Start Heading
				
				if ( !in_array( $field['type'], array( 'heading', 'subheading', 'tab', 'tab_break' ) ) ) { 
					 
					$class = ''; 
					
					if( isset( $field['class'] ) ) { 
					
						$class = $field['class']; 
						
					}
					
					//hide items in checkbox group
					$fold='';
					
					if ( array_key_exists( 'fold', isset( $field['settings'] ) ? $field['settings'] : array() ) && !isset( $field['settings']['fold_value'] ) ) {
						
						if ( !empty( $options_data[$field['settings']['fold']] ) ) {
							
							$fold = 'f_' . $field['settings']['fold'] . ' ';
							
						} else {
							
							$fold = 'f_' . $field['settings']['fold'] . ' yt-temp-hide ';
							
						}
						
					}elseif ( array_key_exists( 'fold', 
						isset( $field['settings'] ) ? $field['settings'] : array() ) 
						&& isset( $field['settings']['fold_value'] ) ) {
							
							$fold = 'f_' . $field['settings']['fold'] . ' yt-temp-hide ';
							
					}
					
					$attr_datafold = !empty( $field['settings']['fold_value'] ) ? $field['settings']['fold_value'] : '';
					
					$attr_datafold = $attr_datafold ? ' data-fold="' . esc_attr( $attr_datafold ) . '"' : '';
					
					if( 'separator' === $field['type'] ){
						
						$separator_class = self::clean_string( ( isset( $field['name'] ) && $field['name'] ? $field['name'] : $field['std'] ), ' ', '') . ( $sub_parent_class ? '-' . $sub_parent_class : '' )  . $parent_class;
						
					}
		
					$output .= '<div' . 
						( $separator_class && 'separator' !== $field['type'] ? ' data-folds="' . esc_attr( $separator_class ) . '"' : '' ) 
						. ( !empty( $field['id'] ) ? sprintf( ' data-id="%s"', esc_attr( $field['id'] ) ) : '' )
						. ( 'separator' === $field['type'] 
							? ' id="yt-section-' . esc_attr( sanitize_title( $separator_class ) ) . '" data-show="yes"' 
							: ( isset( $field['id'] ) && $field['id'] ? ' id="yt-section-' . esc_attr( sanitize_title( self::clean_string( $field['id'], '_', '-') ) ) . '"' : '') ) 
						. ' class="' . esc_attr( $fold ) . 'yt-section yt-section-' . esc_attr( sanitize_title( self::clean_string( $field['type'], '_', '-') ) ) . ' ' . esc_attr( $class ) . '"' 
						. $attr_datafold . '>' . "\n";


					
					
					//only show header if 'name' value exists
					if( !empty( $field['name'] ) && !in_array( $field['type'], array( 'separator', 'info' ) ) ){
						
						$output .= '<h3 class="yt-heading">' . esc_html( $field['name'] ) . apply_filters( $this->_prefix . 'options_inside_option_title', '', $_args ) . '</h3>' . "\n";
							
					}
					
					$output .= '<div class="yt-option yt-clear">' . "\n" . '<div class="yt-controls">' . "\n";
		
				} 
			 	//End Heading

				// Private only
				$output .= !empty( $field['settings']['before_control'] ) ? sprintf( '<div class="yt-before-controls">%s</div>', wp_kses( $field['settings']['before_control'], $this->allowed_tags ) ) : '';
				
				

				$before_control = apply_filters( $this->_prefix . 'options_before_option_control', '', $_args );
				$output .= $before_control;
				
				/* get the option HTML */
				
			 
				switch ( $field['type'] ) {
					
					case 'backup':
					
						$instructions = $field['desc'];
						
						$backup = $this->fetch_options( $this->_option_name . $this->_option_name_backups );
						
						if(!isset($backup['_backup_log'])) {
							$log = __('No backups yet ', 'yeahthemes');
						} else {
							$log = $backup['_backup_log'];
						}
						
						$output .= '<div class="backup-box">';
						$output .= '<div class="instructions">' . esc_html( $instructions ) . "\n";
						$output .= '<p><strong>' . esc_html( __('Last Backup : ','yeahthemes') ) . '<span class="backup-log">' . esc_html( $log ) . '</span></strong></p></div>' . "\n";
						$output .= '<a href="#" id="yt-backup-button" class="button yt-button" title="' . esc_attr( __('Backup Options','yeahthemes') ) . '"><i class="fa fa-database"></i> ' . __('Backup Options','yeahthemes') . '</a>';
						if(isset($backup['_backup_log'])) {
							$output .= '<a href="#" id="yt-restore-button" class="button yt-button" title="' . esc_attr( __('Restore Options','yeahthemes') ) . '"><i class="fa fa-history"></i> ' . esc_html( __('Restore Options','yeahthemes') ) . '</a>';
						}
						$output .= '</div>';
					
					break;
					
					case 'heading':
						
						$tab_break_loop_counter = 0;
						
						if( $tab_count > 0 ){
							
							$output .= '</div><!--/tab_by_heading--></div><!--/yt-group-tab-wrapper-->' . "\n";	
							
							$tab_count = 0;
						}
					
						if( $_counter >= 2 ){
							
						   $output .= '</div><!--/heading-->' . "\n";
						   
						}
						
						$parent_class = '-' . self::clean_string( $field['name'], ' ', '') ;
						$separator_class = '';
						$sub_parent_class = '';
						
						$icon = '';
						//$icon = isset($field['icon']) && $field['icon'] ? 'style="background-image:url('.$field['icon'].')" ' : 'class="no-icon" '; 
						$desc = isset( $field['desc']) && $field['desc'] ? ' data-content="' . esc_attr( $field['desc'] ) . '" ' : ''; 
						$header_class = str_replace( ' ', '', strtolower( $field['name'] ) );
						$anchor_hook = self::clean_string( $field['name'], ' ', '');
						$anchor_hook = 'yt-option-' . $anchor_hook;
						$menu .= '<li class="' . esc_attr( $header_class ) . '"><a title="' .  esc_attr( $field['name'] ) . '" href="#'.  esc_attr( $anchor_hook )  . '">'.  esc_html( $field['name'] ) . '</a></li>';
						$output .= '<!--heading--><div class="yt-group heading" id="' . esc_attr( sanitize_title( $anchor_hook ) ) . '"><h2 ' . strip_tags( $desc ) . '>' . $field['name'] . '</h2>' . "\n";
						
					break;
					
					/*---------------------------------------------------------------------------------------------------------*/
					case 'separator':
					
					
						$info_text = isset( $field['name'] ) && $field['name'] ? $field['name'] : $field['std'];
						
						$output .= '<div class="yt-separator"><h3 style="margin:0">' . $info_text. '</h3></div>';
						
					break;
					
					case 'subheading':
						
						$tab_break_loop_counter = 0;
					
						$separator_class = '';
						
						if( $tab_count > 0 ){
							
							$output .= '</div><!--/tab_by_subheading--></div><!--/yt-group-tab-wrapper-->' . "\n";	
							
							$tab_count = 0;
						}
						
						if( $_counter >= 2 ) {
							$output .= '</div><!--/subheading-->' . "\n";
						}
						
						$sub_parent_class = $anchor_hook = self::clean_string( $field['name'], ' ', '' );
						// $anchor_hook = preg_replace( '/[^\p{L}\p{N}]/u', '', strtolower( $field['name'] ) ); // Regex for UTF-8 languages.
						$anchor_hook = str_replace( ' ', '', $anchor_hook );
						$desc = isset( $field['desc'] ) && $field['desc'] ? ' data-content="' . esc_attr( $field['desc'] ) . '" ' : '';
						$anchor_hook = "yt-option-" . $anchor_hook . $parent_class;
						$menu .= '<li><a title="' . esc_attr( $field['name'] ) . '" href="#' . esc_attr( $anchor_hook ) . '">' . esc_html( $field['name'] ) . '</a></li>';
						$output .= '<!--subheading--><div class="yt-group subheading" id="' . esc_attr( sanitize_title( $anchor_hook ) ) . '"><h2 class="subheading-title"' . strip_tags( $desc ) . '>' . esc_html( $field['name'] ) . '</h2>' . "\n";
					break;
					
					case 'tab':
					
						if( $tab_count == 1 ){
							
								
								//print_r( $nested_tab_array );
								$tab_key_tab = $sub_parent_class ? $sub_parent_class . $parent_class : self::clean_string( $parent_class, '-', ' ' );
								$tab_key_tab = $tab_key_tab . '_' . $tab_break_loop_counter;
								$output .= '<!--yt-group-tab-wrapper--><div class="yt-group-tab-wrapper" id="yt-group-tab-' . esc_attr( sanitize_title( self::clean_string( join( '-', $nested_tab_array[$tab_key_tab] ), '-', '' ) ) ) . '">';

								//print_r( $nested_tab_array ); print_r( $tab_key_tab ); 
								
								
								//print_r($nested_tab_array[$tab_key_tab]);
								
								if( !empty( $nested_tab_array[$tab_key_tab] ) ){
							
									$output .=  '<ul class="yt-group-tab-header" data-ul-tab="' . esc_attr( $tab_key_tab ) . '">';
										
									foreach( $nested_tab_array[$tab_key_tab] as $tab_k => $tab_v ){
										
										$output .=  '<li data-index="' . esc_attr( $tab_k + 1 ) . '"><span>' . esc_html( $tab_v ) . '</span></li>';
									
									}
									
									$output .=  '</ul>';
								}
							//$output .= '</div>';
							
						}
						if( $tab_count >= 2 ){
							
							$output .= '</div><!--/tab-->' . "\n";	
							
						}
					
						$output .= '<div class="yt-group-tab" data-tab="' . esc_attr( $tab_count ) . '">';
						
					break;
					
					case 'tab_break':
						
						if( $tab_count > 0 ){
						
							$output .= '</div><!--/tab_by_tab_break--></div><!--/yt-group-tab-wrapper-->' . "\n";
							
							$tab_count = 0;
						}
						
						$tab_break_loop_counter++;
						
					break;
					
					case 'transfer':
						
						$instructions = $field['desc'];
						$transfer_data = $options_data;
						//print_r($transfer_data);
						unset( $transfer_data[$this->_option_name_backups]);
						
						$transfer_value = !is_serialized( $transfer_data ) ? maybe_serialize( $transfer_data ) : $transfer_data;
						$output .= '<textarea id="yt-export-data" rows="8">' . esc_textarea( self::helper_encode( $transfer_value ) ) /* 100% safe - ignore theme check nag */ . '</textarea>' . "\n";
						$output .= '<a href="#" id="yt-import-button" class="button" title="' . esc_attr( __('Restore Options','yeahthemes') ) . '"><i class="fa fa-sign-in"></i> ' . esc_html( __('Import Options','yeahthemes') ) . '</a>';
					
					break;

					case 'wysiwyg':
						ob_start();
						wp_editor( isset( $options_data[$_args['id']] ) ? $options_data[$_args['id']] : $field['std'], $_args['id'], isset( $_args['options'] ) ? $_args['options'] : array() );
						$output .= ob_get_clean();
					break;
					
					default:
						
						if( function_exists('yt_display_by_type') ){
							
							if( !is_array( yt_display_by_type( $_args ) )){
								$output .= yt_display_by_type( $_args );
							}
							else{
								$output .= esc_html__('Undefined field type', 'yeahthemes' );	
							}
						}
					
				
				}
				
				do_action( $this->_prefix . 'options_generator_loop',
					array(
						'options'	=> $options,
						'data'		=> $options_data,
						'defaults'	=> $defaults,
						'menu'		=> $menu,
						'output'	=> $output,
						'field'		=> $field
					)
				);

				$after_control = apply_filters( $this->_prefix . 'options_after_option_control', '', $_args );
				$output .= $after_control;

				// Private only
				$output .= !empty( $field['settings']['after_control'] ) ? sprintf( '<div class="yt-after-controls">%s</div>', wp_kses( $field['settings']['after_control'], $this->allowed_tags ) ) : '';
			
				//description of each option
				if ( !in_array( $field['type'], array( 'heading', 'subheading', 'tab', 'tab_break' ) ) ) { 
					
					//Explain
					$explain_value = ( isset( $field['desc'] ) ) ? $field['desc'] : '';
					$output .= '</div><!--End control-->';
					
					if( !in_array($field['type'], array( "info" , "separator" ) ) && !empty( $field['desc'] ) ){	
					
						$output .= '<div class="yt-explain">' .  wp_kses( $explain_value, $this->allowed_tags ) ;
						
						//Gradient
						if($field['type'] === 'textarea' && isset($field['preview_gradient']) && $field['preview_gradient'] ==1 && $options_data[$field['id']]){
							
							$output .= '<div class="yt-preview-gradient" style="width:80px;height:80px;' .esc_attr(  $options_data[$field['id']]  ).'"></div>';
						
						}
						
						$output .= '</div><!--End Desc-->'."\n";
					}
					
					//End Explain
					$output .= '</div></div>'."\n";
				}
			
			} /* condition empty end */			
		   
		}
		
		//print_r($options_data);
		
	    if ($update_data == true) {
			
			$this->set_options( $options_data );
			
		}
		
	    $output .= '</div><!--That\'s it! End the heading/subheading/tab group-->';
		
		do_action( $this->_prefix . 'options_generator_after_loop',
			array(
				'options'	=> $options,
				'data'		=> $options_data,
				'defaults'	=> $defaults,
				'menu'		=> $menu,
				'output'	=> $output,
			)
		);
		
		//print_r($menu_items);
		/*
		 * Override the menu with a new multi-level menu.
		 */ 
		if ( count( $menu_items ) > 0 ) {
			
			$menu = '';
			
			$parent_class = '';
				
			foreach ( $menu_items as $k => $v ) {
				
				if( $v['type'] == 'heading'){
					
					$parent_class = '-' . self::clean_string( $v['name'], ' ', '');
					
				}
				
				$class =  self::clean_string( $v['name'], ' ', '');
				
				$icon = '';
				$menu_icon = '';
				//$icon = isset($v['icon']) && $v['icon'] ? 'style="background-image:url('.$v['icon'].')" ' : 'class="no-icon" '; 
				
				if ( isset( $v['children'] ) && ( count( $v['children'] ) > 0 ) ) {
					
					$class .= ' has-children';
					
				}
				
				if ( empty( $v['settings']['icon'] ) ) {
					
					$class .= ' hasnt-icon';
					$menu_icon = '';
				
				}else{
					
					$menu_icon = '<i class="yt-icon-optionnav-' . esc_attr( $v['settings']['icon'] ) . '"></i>';
					
				}
				
				$menu .= '<li class="top-level ' . esc_attr( $class ) . '">' . "\n" ; 

				$menu .= '<a title="' . esc_attr( $v['name'] ) . '" href="#' . esc_attr( sanitize_title( $v['token'] ) ) . '" ' . $icon . '>' . $menu_icon . esc_attr( $v['name'] ) . '</a>' . "\n";
				
				if ( isset( $v['children'] ) && ( count( $v['children'] ) > 0 ) ) {
					
					$menu .= '<ul class="sub-menu">' . "\n";
					
						foreach ( $v['children'] as $i => $j ) {
							
							$menu .= '<li>' . "\n" . '<a title="' . esc_attr( $j['name'] ) . '" href="#' . esc_attr( sanitize_title( $j['token'] ) . $parent_class ) .  '">' . esc_html( $j['name'] ) . '</a></li>' . "\n";
						
						}
					$menu .= '</ul>' . "\n";
				}
				$menu .= '</li>' . "\n";

			}
			
		}
		
		
	    return array( 'fields' => $output, 'menus' => $menu, 'defaults' => $defaults );
		
		
	    
	}
	
	/**********************************************************************************************************
	 *                                  Helper Functions for this Class
	 *
	 **********************************************************************************************************/
	
	/*
	 * Helper function to clean strings, replace character
	 */
	static function clean_string( $string, $replace = ' ', $seperator = '-' ){
		
		return preg_replace( '/[^a-zA-Z0-9-_]/', '', strtolower( trim( str_replace( $replace, $seperator, $string ) ) ) );
	}
	
	/**
	 * Helper function to return encoded strings
	 *
	 * @return    string
	 *
	 * @access    public
	 * @since     1.0
	 */
	static function helper_encode( $value ) {
	
		$func = 'base64' . '_encode';
		return $func( $value );
	  
	}
	
	/**
	 * Helper function to return decoded strings
	 *
	 * @return    string
	 *
	 * @access    public
	 * @since     1.0
	 */
	static function helper_decode( $value ) {
	
		$func = 'base64' . '_decode';
		return $func( $value );
	  
	}
	
	/**
	 * Custom stripslashes from single value or array.
	 *
	 * @param       mixed   $input
	 * @return      mixed
	 *
	 * @access      public
	 * @since       1.0
	 */
	static function helper_stripslashes( $input ) {
	
		if ( is_array( $input ) ) {
		
			foreach( $input as &$val ) {
			
				if ( is_array( $val ) ) {
				
					$val = helper_stripslashes( $val );
					
				} else {
					
					$val = stripslashes( trim( $val ) );
					
				}
				
			}
			
		} else {
			
			$input = stripslashes( trim( $input ) );
		
		}
		
		return $input;
	}
	
}

}

