/*
/*
 * This file is part of the TYPO3 CMS project.
 *
 * It is free software; you can redistribute it and/or modify it under
 * the terms of the GNU General Public License, either version 2
 * of the License, or any later version.
 *
 * For the full copyright and license information, please read the
 * LICENSE.txt file that was distributed with this source code.
 *
 * The TYPO3 project - inspiring people to share!
 */

/**
 * RequireJS module for workspace preview
 */
define([
	'jquery',
	'TYPO3/CMS/Workspaces/Workspaces',
	'TYPO3/CMS/Backend/Severity',
	'TYPO3/CMS/Backend/Modal',
	'twbs/bootstrap-slider'
], function($, Workspaces, Severity, Modal) {
	'use strict';

	var Preview = {
		identifiers: {
			topbar: '#typo3-topbar',
			workspacePanel: '.workspace-panel',
			liveView: '#live-view',
			workspaceTabs: '.t3js-workspace-tabs [data-toggle="tab"]',
			workspaceActions: '.t3js-workspace-actions',
			stageSlider: '#workspace-stage-slider',
			workspaceView: '#workspace-view',
			workspaceList: '#workspace-list',
			sendToStageAction: '[data-action="send-to-stage"]',
			discardAction: '[data-action="discard"]',
			stageButtonsContainer: '.t3js-stage-buttons',
			previewModeContainer: '.t3js-preview-mode',
			activePreviewMode: '.t3js-active-preview-mode',
			workspacePreview: '.t3js-workspace-preview'
		},
		currentSlidePosition: 100,
		elements: {} // filled in Preview.getElements()
	};

	/**
	 * Initializes the preview module
	 */
	Preview.initialize = function() {
		Preview.getElements();
		Preview.resizeViews();

		Preview.adjustPreviewModeSelectorWidth();
		Preview.elements.$stageSlider.slider();

		Preview.registerEvents();
	};

	/**
	 * Fetches and stores often required elements
	 */
	Preview.getElements = function() {
		Preview.elements.$liveView = $(Preview.identifiers.liveView);
		Preview.elements.$workspacePanel = $(Preview.identifiers.workspacePanel);
		Preview.elements.$workspaceTabs = $(Preview.identifiers.workspaceTabs);
		Preview.elements.$workspaceActions = $(Preview.identifiers.workspaceActions);
		Preview.elements.$stageSlider = $(Preview.identifiers.stageSlider);
		Preview.elements.$workspaceView = $(Preview.identifiers.workspaceView);
		Preview.elements.$workspaceList = $(Preview.identifiers.workspaceList);
		Preview.elements.$stageButtonsContainer = $(Preview.identifiers.stageButtonsContainer);
		Preview.elements.$previewModeContainer = $(Preview.identifiers.previewModeContainer);
		Preview.elements.$activePreviewMode = $(Preview.identifiers.activePreviewMode);
		Preview.elements.$workspacePreview = $(Preview.identifiers.workspacePreview);
	};

	/**
	 * Registers the events
	 */
	Preview.registerEvents = function() {
		$(window).on('resize', function() {
			Preview.resizeViews();
		});
		$(document)
			.on('click', Preview.identifiers.discardAction, Preview.renderDiscardWindow)
			.on('click', Preview.identifiers.sendToStageAction, Preview.renderSendPageToStageWindow)
		;

		Preview.elements.$workspaceTabs.on('show.bs.tab', function() {
			Preview.elements.$workspaceActions.toggle($(this).data('actions'));
		});
		Preview.elements.$stageSlider.on('change', Preview.updateSlidePosition);
		Preview.elements.$previewModeContainer.find('[data-preview-mode]').on('click', Preview.changePreviewMode);
	};

	/**
	 * Renders the staging buttons
	 *
	 * @param {String} buttons
	 */
	Preview.renderStageButtons = function(buttons) {
		Preview.elements.$stageButtonsContainer.html(buttons);
	};

	/**
	 * Calculate the available space based on the viewport height
	 *
	 * @returns {Number}
	 */
	Preview.getAvailableSpace = function() {
		var $viewportHeight = $(window).height(),
			$topbarHeight = $(Preview.identifiers.topbar).outerHeight();

		return $viewportHeight - $topbarHeight;
	};

	/**
	 * Updates the position of the comparison slider
	 *
	 * @param {Event} e
	 */
	Preview.updateSlidePosition = function(e) {
		Preview.currentSlidePosition = e.value.newValue;
		Preview.resizeViews();
	};

	/**
	 * Resize the views based on the current viewport height and slider position
	 */
	Preview.resizeViews = function() {
		var availableSpace = Preview.getAvailableSpace(),
			relativeHeightOfLiveView = (Preview.currentSlidePosition - 100) * -1,
			absoluteHeightOfLiveView = Math.round(Math.abs(availableSpace * relativeHeightOfLiveView / 100)),
			outerHeightDifference = Preview.elements.$liveView.outerHeight() - Preview.elements.$liveView.height();

		Preview.elements.$workspacePreview.height(availableSpace);

		if (Preview.elements.$activePreviewMode.data('activePreviewMode') === 'slider') {
			Preview.elements.$liveView.height(absoluteHeightOfLiveView - outerHeightDifference);
		}
		Preview.elements.$workspaceList.height(availableSpace);
	};

	/**
	 * Renders the discard window
	 *
	 * @private
	 */
	Preview.renderDiscardWindow = function() {
		var $modal = Modal.confirm(
			TYPO3.lang['window.discardAll.title'],
			TYPO3.lang['window.discardAll.message'],
			Severity.warning,
			[
				{
					text: TYPO3.lang['cancel'],
					active: true,
					btnClass: 'btn-default',
					name: 'cancel',
					trigger: function() {
						$modal.modal('hide');
					}
				}, {
				text: TYPO3.lang['ok'],
				btnClass: 'btn-warning',
				name: 'ok'
			}
			]
		);
		$modal.on('button.clicked', function(e) {
			if (e.target.name === 'ok') {
				Workspaces.sendRemoteRequest([
					Workspaces.generateRemoteActionsPayload('discardStagesFromPage', [TYPO3.settings.Workspaces.id]),
					Workspaces.generateRemoteActionsPayload('updateStageChangeButtons', [TYPO3.settings.Workspaces.id])
				]).done(function(response) {
					$modal.modal('hide');
					Preview.renderStageButtons(response[1].result);
					// Reloading live view and and workspace list view IFRAME
					Preview.elements.$workspaceView.attr('src', Preview.elements.$workspaceView.attr('src'));
					Preview.elements.$workspaceList.attr('src', Preview.elements.$workspaceList.attr('src'));
				});
			}
		});
	};

	/**
	 * Adjusts the width of the preview mode selector to avoid jumping around due to different widths of the labels
	 */
	Preview.adjustPreviewModeSelectorWidth = function() {
		var $btnGroup = Preview.elements.$previewModeContainer.find('.btn-group'),
			maximumWidth = 0;

		$btnGroup.addClass('open');
		Preview.elements.$previewModeContainer.find('li > a > span').each(function(_, el) {
			var width = $(el).width();
			if (maximumWidth < width) {
				maximumWidth = width;
			}
		});
		$btnGroup.removeClass('open');
		Preview.elements.$activePreviewMode.width(maximumWidth);
	};

	/**
	 * Renders the "send page to stage" window
	 *
	 * @private
	 */
	Preview.renderSendPageToStageWindow = function() {
		var $me = $(this),
			direction = $me.data('direction'),
			actionName;

		if (direction === 'prev') {
			actionName = 'sendPageToPreviousStage';
		} else if (direction === 'next') {
			actionName = 'sendPageToNextStage';
		} else {
			throw 'Invalid direction ' + direction + ' requested.';
		}

		Workspaces.sendRemoteRequest(
			Workspaces.generateRemoteActionsPayload(actionName, [TYPO3.settings.Workspaces.id])
		).done(function(response) {
			var $modal = Workspaces.renderSendToStageWindow(response);
			$modal.on('button.clicked', function (e) {
				if (e.target.name === 'ok') {
					var $form = $(e.currentTarget).find('form'),
						serializedForm = $form.serializeObject();

					serializedForm.affects = response[0].result.affects;
					serializedForm.stageId = $me.data('stageId');

					Workspaces.sendRemoteRequest([
						Workspaces.generateRemoteActionsPayload('sentCollectionToStage', [serializedForm]),
						Workspaces.generateRemoteActionsPayload('updateStageChangeButtons', [TYPO3.settings.Workspaces.id])
					]).done(function(response) {
						$modal.modal('hide');

						Preview.renderStageButtons(response[1].result);
					});
				}
			});
		});
	};

	/**
	 * Changes the preview mode
	 *
	 * @param {Event} e
	 */
	Preview.changePreviewMode = function(e) {
		e.preventDefault();

		var $trigger = $(this),
			currentPreviewMode = Preview.elements.$activePreviewMode.data('activePreviewMode'),
			newPreviewMode = $trigger.data('previewMode');

		Preview.elements.$activePreviewMode.text($trigger.text()).data('activePreviewMode', newPreviewMode);
		Preview.elements.$workspacePreview.parent()
			.removeClass('preview-mode-' + currentPreviewMode)
			.addClass('preview-mode-' + newPreviewMode);

		if (newPreviewMode === 'slider') {
			Preview.elements.$stageSlider.parent().toggle(true);
			Preview.resizeViews();
		} else {
			Preview.elements.$stageSlider.parent().toggle(false);

			if (newPreviewMode === 'vbox') {
				Preview.elements.$liveView.height('100%');
			} else {
				Preview.elements.$liveView.height('50%');
			}
		}

	};

	/**
	 * Serialize a form to a JavaScript object
	 *
	 * @see http://stackoverflow.com/a/1186309/4828813
	 * @return {Object}
	 */
	$.fn.serializeObject = function() {
		var o = {};
		var a = this.serializeArray();
		$.each(a, function() {
			if (typeof o[this.name] !== 'undefined') {
				if (!o[this.name].push) {
					o[this.name] = [o[this.name]];
				}
				o[this.name].push(this.value || '');
			} else {
				o[this.name] = this.value || '';
			}
		});
		return o;
	};

	$(document).ready(function() {
		Preview.initialize();
	});
});
