// com.tts.initial.html5.navigation.back.history
// HTML4 / HTML5: No differences
define([
    "jquery",
    "./locals",
    "./button.state",
    "./image.button.builder",
	"./svg.button.builder",
	"./accessibility.builder"
],
function(
    jq,
    uiText,
    ButtonState,
    ImageButtonBuilder,
	SvgButtonBuilder,
	AccessibilityBuilder
){

	"use strict";

	/**
	 * @constructor
	 */
	return function (context, metadata) {

		var shellElement,
			button,
			instance,
			pageId = metadata.page.getId(),
            buttonInitialized = false,
			isStandardPlayer = context.getPlayerName() === "standard",
			hasStageTriggerSupport = true,
			isInAuthoringMode = false,
            pointerUpEventName,
			pointerDownEventName,
			pointerMoveEventNames,
			pointerLeaveEventNames,
			accessibilityTooltip,
			accessibilityTabOrder = metadata.parameters.asNumber("tab-order", -1),
			exludeFromTabControl = metadata.parameters.asBool("exclude-from-tab-control", false),
			accessibilityKey = metadata.parameters.get("accessibility-key", "KeyNone"),
			accessibilityLocation = metadata.parameters.asNumber( "accessibility-location", 0 ),
			accessibilityPositionX = metadata.parameters.asNumber( "accessibility-position-x", -6 ),
			accessibilityPositionY = metadata.parameters.asNumber( "accessibility-position-y", -6 );

		function loadBackgroundImage() {

			var deferred = jq.Deferred(),
				defaultImage = new Image(),
				metadataParameters = metadata.parameters,
				backgroundImage = metadataParameters.get("bg_image", null),
				backgroundFileName,
				result = {};

			defaultImage.onload = function () {
				result.width = this.width;
				result.height = this.height / 4;
				deferred.resolve(result);
			};

			if (backgroundImage) {
				backgroundFileName = context.stage.getSharedPath() + backgroundImage.fileName;
			}
			else {
				backgroundFileName = context.getPath() + "back.png";
			}

			result.fileName = backgroundFileName;
			defaultImage.src = backgroundFileName;

			return deferred.promise();
		}

		function cancelEvent(e) {
			if(e && e.preventDefault) {
				e.preventDefault();
			}
			if(e && e.stopPropagation()) {
				e.stopPropagation();
			}
			return false;
		}

		function back() {
			var pageHistory = updateLocalHistoryArray(),
				previousPageId;

			if (pageHistory && pageHistory.length > 0) {
				pageHistory.pop();
				pageHistory = updateLocalHistoryArray(pageHistory);

				if (isHistoryEmpty()) {
					return;
				}

				context.stage.accessibility.turnAccessibilityModeOff();

				previousPageId = pageHistory[pageHistory.length - 1];

				if(typeof context.stage.navigation.gotoPageById === "function") {
					context.stage.navigation.gotoPageById(previousPageId);
				} else if(typeof context.stage.navigation.gotoPage === "function") {
					context.stage.navigation.gotoPage({
						getId: function() {
							return previousPageId;
						}
					});
				}
			}
		}

		// create an object shield so we are able to select and drag element
		function createAuthoringShield(shellElement) {
			shellElement.append(jq(document.createElement("div"))
				.css({
					"position": "absolute",
					"left": 0,
					"top": 0,
					"background-color": "#ffffff",
					"opacity": "0.4",
					"width": "100%",
					"height": "100%",
					"z-index": "9999"
				}));
		}

		function lockNavigation() {
			if (isInAuthoringMode || !hasStageTriggerSupport) {
				return;
			}
			context.stage.trigger.lock(metadata.getId());
		}

		function unlockNavigation() {
			if (isInAuthoringMode || !hasStageTriggerSupport) {
				return;
			}
			context.stage.trigger.unlock(metadata.getId());
		}

		function onMouseOver() {
            if( !button.hasState( ButtonState.Pressed ) ) {
                button.changeState(ButtonState.Hover);
            }
		}

		function onMouseDown( e ) {
			cancelEvent( e );
			lockNavigation();
            button.changeState( ButtonState.Pressed );
		}

		function deactivateButton() {
            removeEvents();
            button.changeState( ButtonState.Inactive );
		}

		function isOnTarget(e) {
			var elem = e.target,
				origEvent = e.originalEvent,
				changedTouch = origEvent.changedTouches && origEvent.changedTouches.length > 0 ? origEvent.changedTouches[0] : undefined;

			if(changedTouch) {
				elem = document.elementFromPoint(changedTouch.clientX, changedTouch.clientY);
			}
			return e.target === elem;
		}

		function onMouseUp(e) {
			cancelEvent( e );
			unlockNavigation();

            button.changeState( ButtonState.Default );

			if ( isOnTarget( e ) ) {
				back();
			}
			if(!hasStageTriggerSupport) {
				if (e.originalEvent.preventDefault) {
					e.originalEvent.preventDefault();
				}
				if (e.originalEvent.stopPropagation) {
					e.originalEvent.stopPropagation();
				}
			}
		}

		function onMouseLeave() {
			unlockNavigation();
            button.changeState( ButtonState.Default );
		}

        function initPointerEventNames() {
            if( !pointerUpEventName ) {
                var nodeName = getHotspotElementNodeName();
                pointerDownEventName = context.device.getDownEvents( nodeName );
                pointerUpEventName = context.device.getUpEvents( nodeName );
				pointerMoveEventNames = context.device.getMoveEvents( nodeName );
				pointerLeaveEventNames = context.device.getReleaseEvents( nodeName );
            }
        }

        function getHotspotElementNodeName() {
            return button.getHotspotElement().nodeName
                ? button.getHotspotElement().nodeName
                : "document";
        }

        function bindEvents() {

            if (context.stage.isInAuthoringMode()) {
				return;
			}

			if (!button) {
				return;
			}

			removeEvents();
            context.device.attachFirstSupportedEvent( button.getHotspotElement(), pointerDownEventName, onMouseDown );
			context.device.attachFirstSupportedEvent( button.getHotspotElement(), pointerMoveEventNames, onMouseOver );
			context.device.attachFirstSupportedEvent( button.getHotspotElement(), pointerLeaveEventNames, onMouseLeave );
            context.device.attachFirstSupportedEvent( button.getHotspotElement(), pointerUpEventName, onMouseUp );
        }

		function removeEvents() {
			unlockNavigation();
			if (!button) {
				return;
			}

            initPointerEventNames();
            context.device.removeFirstSupportedEvent( button.getHotspotElement(), pointerDownEventName, onMouseDown );
			context.device.removeFirstSupportedEvent( button.getHotspotElement(), pointerMoveEventNames, onMouseOver );
			context.device.removeFirstSupportedEvent( button.getHotspotElement(), pointerLeaveEventNames, onMouseLeave );
            context.device.removeFirstSupportedEvent( button.getHotspotElement(), pointerUpEventName, onMouseUp );
        }

		function addHistoryPoint() {
			var pageHistory = updateLocalHistoryArray();

			if (pageHistory && pageHistory[pageHistory.length - 1] !== pageId) {
				pageHistory.push(pageId);
			}
			updateLocalHistoryArray(pageHistory);

			if(isHistoryEmpty()) {
				deactivateButton();
			} else {
				activateButton();
			}
		}

		function updateLocalHistoryArray(pH) {
			var pageHistory;

			if(pH) {
				context.stage.variable.set("tts_pageNavigationHistory", pH, "tts.pageHistory");
			}
			pH = context.stage.variable.get("tts_pageNavigationHistory", "tts.pageHistory");

			if (!pH) {
				pageHistory = [];
				context.stage.variable.set("tts_pageNavigationHistory", [], "tts.pageHistory");
			} else {
				pageHistory = [].slice.call(pH, 0);
			}
			return pageHistory;
		}

		function isHistoryEmpty() {
			var pageHistory = updateLocalHistoryArray();
			if(!pageHistory) {
				return true;
			}
			if(pageHistory.length < 1) {
				return true;
			}
			return pageHistory.length === 1 && pageHistory[0] === pageId;
		}

		function activateButton() {
			bindEvents();
			if(button) {
                button.changeState( ButtonState.Default );
			}
		}

		function initializeButton() {

			buttonInitialized = true;

            button = metadata.parameters.asBool("use_svg") ? createSvgButton() : createImageButton();

            context.page.interaction.provokesFeedback( button.getHotspotElement(), false );
            context.page.interaction.provokesAutosolve( button.getHotspotElement(), false );

            shellElement.append( button.getHotspotElement() );

			if (isHistoryEmpty()) {
				deactivateButton();
			} else {
				activateButton();
			}

			accessibilityTooltip = new AccessibilityBuilder(accessibilityKey, accessibilityLocation, accessibilityPositionX, accessibilityPositionY, context).build();
			if (accessibilityTooltip.getElement()) {
				shellElement.append( accessibilityTooltip.getElement() );
			}

            if (isInAuthoringMode) {
                createAuthoringShield( shellElement );
            }
		}

        function createImageButton(){

            var scParams = metadata.parameters,
                imageButton = new ImageButtonBuilder({
                    width: metadata.getWidth(),
                    height: metadata.getHeight(),
					caption: uiText.get("player.navigation.button.back", metadata.stage.getContentLanguage()),
					ariaLabel: ((metadata.parameters.get("aria-label", false) || "").trim() === "") ? false : metadata.parameters.get("aria-label", false),
                    color : scParams.get("color", "#919191"),
                    text : {
                        content : scParams.get("text", ""),
                        fontFamily : getFontStyle( scParams.asNumber("font-family", "1") ),
                        fontSize : scParams.asNumber("font-size", "14"),
                        orientation : scParams.get("text_orientation", "center"),
                        verticalAlignment: scParams.get("text_vertical_align", "middle"),
                        paddingLeft : Math.abs(scParams.asNumber("padding-left", "10")),
                        paddingRight : Math.abs(scParams.asNumber("padding-right", "10")),
                        paddingTop : Math.abs(scParams.asNumber("padding-top", "10")),
                        paddingBottom : Math.abs(scParams.asNumber("padding-bottom", "10"))
                    }
                }).build();

            loadBackgroundImage().then( function( buttonImage ) {
                applyButtonImage( buttonImage );
            });

            return imageButton;
        }

		function createSvgButton() {

            var scParams = metadata.parameters;
            return new SvgButtonBuilder({
                id: "svg_" + pageId + "_" + metadata.getId(),
                width: metadata.getWidth(),
                height: metadata.getHeight(),
				caption: uiText.get("player.navigation.button.back", metadata.stage.getContentLanguage()),
				ariaLabel: ((metadata.parameters.get("aria-label", false) || "").trim() === "") ? false : metadata.parameters.get("aria-label", false),
                colors: {
                    default: {
                        icon: scParams.get("color_svg_icon_default", "#ffffff"),
                        bg: scParams.get("color_svg_background_default", "#707070")
                    },
                    hover: {
                        icon: scParams.get("color_svg_icon_hover", "#ffffff"),
                        bg: scParams.get("color_svg_background_hover", "#fd7e2f")
                    },
                    pressed: {
                        icon: scParams.get("color_svg_icon_pressed", "#ffffff"),
                        bg: scParams.get("color_svg_background_pressed", "#df7a3b")
                    },
                    inactive: {
                        icon: scParams.get("color_svg_icon_inactive", "#a9a9a9"),
                        bg: scParams.get("color_svg_background_inactive", "#707070")
                    }
                }
            }).build();
        }

        function getFontStyle( paramValue ) {
            switch( paramValue ) {
                case 2:
                    return "\"Times New Roman\", Times, serif";
                case 3:
                    return "Verdana, Geneva, sans-serif";
                case 4:
                    return "\"Courier New\", Courier, monospace";
                default:
                    return "Arial, Helvetica, sans-serif";
            }
        }

        function applyButtonImage( buttonImage ){

            var buttonWidth = buttonImage.width,
                buttonHeight = buttonImage.height;

            shellElement.css({
                "width": buttonWidth + "px",
                "height": buttonHeight + "px"
            });

            button.changeImage( buttonWidth, buttonHeight, buttonImage.fileName );
        }

		// revealing public API
		return {
			onLoading: function () {
				instance = this;

				context.page.event.bindOnEnter(instance);
				context.page.event.bindOnExit(instance);
				context.stage.accessibility.bindOnAccessibilityModeChanged(instance);
				if (!isStandardPlayer) {
					context.page.event.bind(instance, "onTabNavigationOff");
					context.page.event.bind(instance, "onTabNavigationSelection");
					context.page.event.bind(instance, "onTabNavigationFire");
				}

				hasStageTriggerSupport = !!context.stage.trigger;
				isInAuthoringMode = !!context.stage.isInAuthoringMode();

				shellElement = jq(context.getElement());

				// because of some problems with loading SVG while it is hidden on page,
				// we initialize SVG button onEnterPage
				if (!isStandardPlayer || isInAuthoringMode) {
					initializeButton();
				}
			},

			onEnterPage: function () {
				// because of some problems with loading SVG while it is hidden on page,
				// we initialize SVG button onEnterPage
				if (!buttonInitialized) {
					initializeButton();
				}

				unlockNavigation();
				addHistoryPoint();

				if (!isStandardPlayer && !exludeFromTabControl) {
					accessibilityTooltip.registerTabNavigation(metadata.getId(), accessibilityTabOrder);
				}
			},

            onExitPage: function () {
				removeEvents();
				context.stage.accessibility.turnAccessibilityModeOff();
			},

			onAccessibilityModeChanged: function (dataHTML5, dataHTML4) {
				if (isHistoryEmpty()) {
					button.changeState(ButtonState.Inactive);
					return;
				}

				var params = dataHTML4 || dataHTML5;

				if ( params.isActive  && !(isHistoryEmpty()) ) {
					accessibilityTooltip.show();
				} else {
					accessibilityTooltip.hide();
				}
			},

			onAccessibilityKeyPressed: function (dataHTML5, dataHTML4) {
				if (isHistoryEmpty()) {
					button.changeState(ButtonState.Inactive);
					return;
				}

				var params = dataHTML4 || dataHTML5;

				if ( params.keyCode == accessibilityTooltip.getKeyCode() ) {
					back();
				}
			},

			onTabNavigationSelection: function (dataHTML5, dataHTML4, data) {
				if (data && data.id && data.id == metadata.getId()) {
					if (isHistoryEmpty()) {
						setTimeout(function () {
							context.page.event.fire(instance, "onInactiveTabNavigationSelection");
						}, 10);
						return;
					}
					button.focusButton();
				} else {
					if (isHistoryEmpty()) {
						button.changeState(ButtonState.Inactive);
						return;
					}
					button.blurButton();
				}
			},

			onTabNavigationOff: function (dataHTML5, dataHTML4) {
				if (isHistoryEmpty()) {
					button.changeState(ButtonState.Inactive);
					return;
				}

				button.blurButton();
			},

			onTabNavigationFire: function (dataHTML5, dataHTML4, data) {
				if (isHistoryEmpty()) {
					button.changeState(ButtonState.Inactive);
					return;
				}

				if (data && data.id && data.id == metadata.getId()) {
					back();
				}
			}
        };
	};
});
