<?php

/**
 * Code Option Class
 *
 * @author Benjamin Intal
 * @package GAS Framework Core
 **/

if ( ! defined( 'ABSPATH' ) ) { exit; // Exit if accessed directly
}
/**
 * Code Option Class
 *
 * @since	1.3
 **/
class GASFrameworkOptionCode extends GASFrameworkOption {


	/**
	 * Default settings specific for this container
	 * @var array
	 */
	public $defaultSecondarySettings = array(

		/**
		 * (Optional) The language used for syntax highlighting for this option. The list of all supported languages are available in the Ace GitHub repo.
		 * @since 1.0
		 * @var string
		 */
		'lang' => 'css',

		/**
		 * (Optional) The color theme used in the option. The list of all supported themes are available in the Ace GitHub repo.
		 * @since 1.0
		 * @var string
		 */
		'theme' => 'chrome',

		/**
		 * (Optional) The height of the editor in pixels.
		 * @since 1.0
		 * @var string
		 */
		'height' => 200,

		/**
		 * (Optional) The inputted code is automatically included in the frontend if the <code>lang</code> parameter is <code>css</code> or <code>javascript</code>. Setting this to false forces the option to stop including the code in the front end. This is useful if you want to use the option value in the back end or somewhere else.
		 * @since 1.9.3
		 * @var bool
		 */
		'enqueue' => true,
	);


	/**
	 * Constructor
	 *
	 * @since	1.3
	 */
	function __construct( $settings, $owner ) {
		parent::__construct( $settings, $owner );

		add_action( 'admin_enqueue_scripts', array( $this, 'loadAdminScripts' ) );
		add_action( 'customize_controls_enqueue_scripts', array( $this, 'loadAdminScripts' ) );

		// CSS generation for CSS code langs
		add_filter( 'tf_generate_css_code_' . $this->getOptionNamespace(), array( $this, 'generateCSSCode' ), 10, 2 );
		add_filter( 'wp_head', array( $this, 'printCSSForPagesAndPosts' ), 100 );

		// JS inclusion for Javascript code langs
		add_filter( 'wp_footer', array( $this, 'printJS' ), 100 );
		add_filter( 'wp_footer', array( $this, 'printJSForPagesAndPosts' ), 101 );
	}


	/**
	 * Prints javascript code in the header using wp_print_scripts
	 *
	 * @return	void
	 * @since	1.3
	 */
	public function printJS() {

		// Allow the enqueue setting to stop this.
		if ( ! $this->settings['enqueue'] ) {
			return;
		}

		// For JavaScripts only
		if ( $this->settings['lang'] != 'javascript' ) {
			return;
		}

		// For non-meta box options only
		if ( GASFrameworkOption::TYPE_META == $this->type ) {
			return;
		}

		$js = $this->getValue();

		if ( ! empty( $js ) ) {
			printf( wp_kses("<script type=\"text/javascript\">\n" . $js . "\n</script>\n", get_allowed_html_wp_notifications()) );
		}
	}


	/**
	 * Prints javascript code in the header for meta options using wp_print_scripts
	 *
	 * @return	void
	 * @since	1.3
	 */
	public function printJSForPagesAndPosts() {

		// Allow the enqueue setting to stop this.
		if ( ! $this->settings['enqueue'] ) {
			return;
		}

		// This is for meta box options only, other types get generated normally
		if ( GASFrameworkOption::TYPE_META != $this->type ) {
			return;
		}

		// For CSS langs only
		if ( $this->settings['lang'] != 'javascript' ) {
			return;
		}

		// Don't generate CSS for non-pages and non-posts
		$id = get_the_ID();
		if ( empty( $id ) || 1 == $id || ! is_singular() ) {
			return;
		}

		echo wp_kses('<script> ' . $this->getValue( $id ) . ' </script>', get_allowed_html_wp_notifications());
	}


	/**
	 * Prints CSS styles in the header for meta options using wp_print_scripts
	 *
	 * @return	void
	 * @since	1.3
	 */
	public function printCSSForPagesAndPosts() {

		// Allow the enqueue setting to stop this.
		if ( ! $this->settings['enqueue'] ) {
			return;
		}

		// This is for meta box options only, other types get generated normally
		if ( GASFrameworkOption::TYPE_META != $this->type ) {
			return;
		}

		// For CSS langs only
		if ( $this->settings['lang'] != 'css' || $this->settings['lang'] != 'scss' ) {
			return;
		}

		// Don't generate CSS for non-pages and non-posts
		$id = get_the_ID();
		if ( empty( $id ) || 1 == $id || ! is_singular() ) {
			return;
		}

		// Check if a CSS was entered
		$css = $this->getValue( $id );
		if ( empty( $css ) ) {
			return;
		}

		// Print out valid CSS only
		require_once( trailingslashit( dirname( dirname( __FILE__ ) ) ) . 'inc/scssphp/scss.inc.php' );
		$scss = new gasscssc();
		try {
			$css = $scss->compile( $css );
			echo wp_kses("<style type='text/css' media='screen'>{$css}</style>", [ 'style' => [ 'type' => true, 'media' => true ]]);
		} catch (Exception $e) {
		}
	}


	/**
	 * Generates CSS to be included in our dynamically generated CSS file in
	 * GASFrameworkCSS, using tf_generate_css_code
	 *
	 * @param	string               $css The CSS to output
	 * @param	GASFrameworkOption $option The option object being generated
	 * @return	void
	 * @since	1.3
	 */
	public function generateCSSCode( $css, $option ) {
		// For CSS langs only
		if ( $this->settings['lang'] != 'css' || $this->settings['lang'] != 'scss' ) {
			return;
		}

		if ( $this->settings['id'] != $option->settings['id'] ) {
			return $css;
		}

		// Allow the enqueue setting to stop this.
		if ( ! $this->settings['enqueue'] ) {
			return $css;
		}

		if ( GASFrameworkOption::TYPE_META != $option->type ) {
			$css = $this->getValue();
		}
		return $css;
	}


	/**
	 * Loads the ACE library for displaying our syntax highlighted code editor
	 *
	 * @return	void
	 * @since	1.3
	 */
	public function loadAdminScripts() {
		wp_enqueue_script( 'tf-ace', GASFramework::getURL( '../js/ace-min-noconflict/ace.js', __FILE__ ) );
		wp_enqueue_script(
			'tf-ace-theme-' . $this->settings['theme'],
			GASFramework::getURL( '../js/ace-min-noconflict/theme-' . $this->settings['theme'] . '.js',
			__FILE__ )
		);
		wp_enqueue_script(
			'tf-ace-mode-' . $this->settings['lang'],
			GASFramework::getURL( '../js/ace-min-noconflict/mode-' . $this->settings['lang'] . '.js',
			__FILE__ )
		);
	}


	/**
	 * Displays the option for admin pages and meta boxes
	 *
	 * @return	void
	 * @since	1.3
	 */
	public function display() {
		$this->echoOptionHeader();

		?>
		<script>
		jQuery(document).ready(function ($) {
			var container = jQuery('#<?php echo wp_kses_post($this->getID() )?>_ace_editor');
			container.width( container.parent().width() ).height( <?php echo wp_kses_post($this->settings['height']) ?> );

			var editor = ace.edit( "<?php echo wp_kses_post($this->getID() )?>_ace_editor" );
			container.css('width', 'auto');
			editor.setValue(container.siblings('textarea').val());
			editor.setTheme("ace/theme/<?php echo wp_kses_post($this->settings['theme']) ?>");
			editor.getSession().setMode('ace/mode/<?php echo wp_kses_post($this->settings['lang']) ?>');
			editor.setShowPrintMargin(false);
			editor.setHighlightActiveLine(false);
			editor.gotoLine(1);
			editor.session.setUseWorker(false);

			editor.getSession().on('change', function(e) {
				$(editor.container).siblings('textarea').val(editor.getValue());
			});
		});
		</script>
		<?php

		printf( "<div id='%s_ace_editor'></div>", esc_attr($this->getID()) );

		// The hidden textarea that will hold our contents
		printf( "<textarea name='%s' id='%s' style='display: none'>%s</textarea>",
			esc_attr( $this->getID() ),
			esc_attr( $this->getID() ),
			esc_textarea( $this->getValue() )
		);

		$this->echoOptionFooter();
	}


	/**
	 * Cleans the value for getOption
	 *
	 * @param	string $value The raw value of the option
	 * @return	mixes The cleaned value
	 * @since	1.3
	 */
	public function cleanValueForGetting( $value ) {
		return stripslashes( $value );
	}


	/**
	 * Registers the theme customizer control, for displaying the option
	 *
	 * @param	WP_Customize                    $wp_enqueue_script The customize object
	 * @param	GASFrameworkCustomizerSection $section The section where this option will be placed
	 * @param	int                             $priority The order of this control in the section
	 * @return	void
	 * @since	1.3
	 */
	public function registerCustomizerControl( $wp_customize, $section, $priority = 1 ) {
		$wp_customize->add_control( new GASFrameworkOptionCodeControl( $wp_customize, $this->getID(), array(
			'label' => $this->settings['name'],
			'section' => $section->settings['id'],
			'settings' => $this->getID(),
			'description' => $this->settings['desc'],
			'priority' => $priority,
			'lang' => $this->settings['lang'],
			'theme' => $this->settings['theme'],
			'height' => $this->settings['height'],
		) ) );
	}
}



/*
 * We create a new control for the theme customizer
 */
add_action( 'customize_register', 'registerGASFrameworkOptionCodeControl', 1 );


/**
 * Creates the option for the theme customizer
 *
 * @return	void
 * @since	1.3
 */
function registerGASFrameworkOptionCodeControl() {
	class GASFrameworkOptionCodeControl extends WP_Customize_Control {
		public $description;
		public $lang;
		public $theme;
		public $height;

		public function render_content() {
			?>
			<script>
			jQuery(document).ready(function ($) {
				var container = jQuery('#<?php echo esc_attr($this->id) ?>_ace_editor');
				container.width( container.parent().width() ).height( <?php echo wp_kses_post($this->height )?> );

				var editor = ace.edit( "<?php echo esc_attr($this->id) ?>_ace_editor" );
				container.css('width', 'auto');
				editor.setValue(container.siblings('textarea').val());
				editor.setTheme("ace/theme/<?php echo wp_kses_post($this->theme) ?>");
				editor.getSession().setMode('ace/mode/<?php echo wp_kses_post($this->lang) ?>');
				editor.setShowPrintMargin(false);
				editor.setHighlightActiveLine(false);
				editor.gotoLine(1);
				editor.session.setUseWorker(false);

				editor.getSession().on('change', function(e) {
					$(editor.container).siblings('textarea').val(editor.getValue()).trigger('change');
				});
			});
			</script>

			<label>
			<span class="customize-control-title"><?php echo esc_html( $this->label ); ?></span>
			<?php

			printf( "<div id='%s_ace_editor' class='tf-code'></div>", wp_kses_post($this->id) );

			// The hidden textarea that will hold our contents
			?><textarea <?php $this->link(); ?> style='display: none'><?php echo wp_kses_post($this->value()) ?></textarea><?php

			if ( ! empty( $this->description ) ) {
				echo "<p class='description'>" . wp_kses_post($this->description) . "</p>";
			}

			?>
			</label>
			<?php
		}
	}
}
