ShortcodesUltimateMakerEditor.Code = ( function( $ ) {

	/**
	 * Define main object.
	 */
	var self = {};

	/**
	 * Define component elements.
	 */
	self.el = {
		field: $( '#sum-code' ),
		value: $( '#sum-code-value' ),
		mode: $( '#sum-type' ),
		container: $( '#sum-code-editor' ),
		editor: null,
		variablesContainer: $( '#sum-code-variables' ),
		variables: $( '#sum-code-variables-list' ),
		fullscreen: null,
		attributes: $( '#sum-attributes' )
	};

	/**
	 * Define component templates.
	 */
	self.tpl = {
		fullscreen: $( '#sum-code-fullscreen-tpl' ).html(),
		variable: {
			tag: $( '#sum-code-variable-tpl' ).html(),
			html: '{{%s}}',
			php_echo: '$%s',
			php_return: '$%s'
		}
	};

	/**
	 * Retrieve l10n strings.
	 */
	self.l10n = ShortcodesUltimateMakerEditorData.l10n.Code;

	/**
	 * Initialize the component.
	 */
	self.init = function() {

		/**
		 * Initialize the code editor.
		 */
		self.el.container.removeClass( 'hidden' );
		self.el.editor = ace.edit( 'sum-code-editor' );
		self.el.editor.$blockScrolling = Infinity;
		self.el.editor.getSession().setValue( self.el.value.val() );
		self.el.editor.getSession().setUseWrapMode( true );
		self.el.editor.getSession().setWrapLimitRange( null, null );
		self.el.editor.getSession().setUseSoftTabs( null );
		self.el.editor.getSession().setUseWorker( false );
		self.el.editor.setTheme( 'ace/theme/sqlserver' );
		self.el.editor.renderer.setShowPrintMargin( null );

		self.el.value.addClass( 'hidden' );

		/**
		 * Create and insert fullscreen button.
		 */
		self.el.fullscreen = $( self.tpl.fullscreen ).attr( 'title', self.l10n.fullscreen );
		self.el.container.append( self.el.fullscreen );

		self.changeEditorMode();
		self.updateHeight();
		self.updateVariables();
		self.bindEvents();

	};

	/**
	 * Setup event listeners.
	 */
	self.bindEvents = function() {

		self.el.editor.getSession().on( 'change', self.updateValue );
		self.el.editor.getSession().on( 'change', self.updateHeight );

		self.el.mode.on( 'change', self.changeEditorMode );

		self.el.fullscreen.on( 'click', self.toggleFullscreen );

		self.el.mode.on( 'change', self.updateVariables );
		$( document ).on( 'sum/attributes/updated', self.updateVariables );

		self.el.variables.on( 'click', 'a', self.insertVariable );

	};

	/**
	 * Update hidden textrea value.
	 */
	self.updateValue = function() {
		self.el.value.val( self.el.editor.getSession().getValue() );
	};

	/**
	 * Update editor height.
	 */
	self.updateHeight = function() {

		var newHeight = self.el.editor.getSession().getScreenLength() * self.el.editor.renderer.lineHeight + self.el.editor.renderer.scrollBar.getWidth() + self.el.editor.renderer.lineHeight * 3,
			maxHeight = $( window ).height() - 100;

		if ( newHeight > maxHeight ) {
			newHeight = maxHeight;
		}

		self.el.container.height( newHeight.toString() + 'px' );

		self.el.editor.resize();

	};

	/**
	 * Change code editor mode.
	 */
	self.changeEditorMode = function() {

		var mode = self.el.mode.val();

		// Change mode to HTML
		if ( mode === 'html' ) {
			self.el.editor.getSession().setMode( 'ace/mode/html' );
		}

		// Change mode to PHP
		else if ( mode === 'php_echo' || mode === 'php_return' ) {

			self.el.editor.getSession().setMode( {
				path: 'ace/mode/php',
				inline: true
			} );

		}

	};

	/**
	 * Toggle editor fullscreen mode.
	 */
	self.toggleFullscreen = function() {

		self.el.container.toggleClass( 'sum-code-editor-fullscreen' );

		self.el.editor.resize();

		self.el.editor.focus();

	};

	/**
	 * Update the list of variables.
	 */
	self.updateVariables = function() {

		var attributes = self.el.attributes.find( '.sum-attributes-item' );

		self.el.variables.children( 'li' ).remove();

		self.addVariable( 'content' );

		attributes.each( function() {

			var attribute = $( this );

			if ( attribute.hasClass( 'deleted' ) ) {
				return;
			}

			var slug = attribute.find( 'input:text[data-name="slug"]' ).val();

			if ( slug !== '' ) {
				self.addVariable( slug );
			}

		} );

	};

	/**
	 * Insert single variable.
	 */
	self.addVariable = function( name ) {

		var mode = self.el.mode.val(),
			newVariable = $( self.tpl.variable.tag );

		newVariable.children( 'a' )
			.text( self.tpl.variable[ mode ].replace( '%s', name ) );

		self.el.variables.append( newVariable );

	};

	/**
	 * Insert a variable into editor.
	 */
	self.insertVariable = function( event ) {

		event.preventDefault();

		var variable = $( this ).text();

		self.el.editor.insert( variable );

		self.el.editor.focus();

	};

	/**
	 * Provide public API.
	 */
	return {
		init: self.init
	};

} )( jQuery );