// com.tts.initial.html5.navigation.close
define([
    "jquery",
    "./locals",
    "./button.state",
    "./image.button.builder",
    "./svg.button.builder",
    "./dialog.builder",
    "./accessibility.builder"
],
function(
    jq,
    uiText,
    ButtonState,
    ImageButtonBuilder,
    SvgButtonBuilder,
    DialogBuilder,
    AccessibilityBuilder
){

	"use strict";

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

        var instance,
            shellElement,
            enabled = true,
            button,
            closeDialog,
            showDialog = metadata.parameters.asBool( "show_dialog" ),
            buttonInitialized = false,
            isStandardPlayer = context.getPlayerName() === "standard",
            hasStageTriggerSupport = true,
            isInAuthoringMode = false,
            pointerUpEventName,
            pointerDownEventName,
            pointerMoveEventNames,
            pointerLeaveEventNames,
            accessibilityTooltipClose,
            accessibilityTabOrder = metadata.parameters.asNumber("tab-order", -1),
            exludeFromTabControl = metadata.parameters.asBool("exclude-from-tab-control", false),
            accessibilityKeyClose = metadata.parameters.get("accessibility-key-close", "KeyB"),
            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() + "close.png";
			}

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

			return deferred.promise();
        }

        function loadImage( key, image ) {
            var result = {};

            if ( image ) {
                result.fileNameURL = context.stage.getSharedPath() + image.fileName;
                result.width = parseInt( image.width );
                result.height = parseInt( image.height );
            }
            else {
                switch ( key ) {
                    case "noButton":
                        result.fileNameURL = context.getPath() + "no.png";
                        result.width = 120;
                        result.height = 150;
                        break;
                    case "yesButton":
                        result.fileNameURL = context.getPath() + "yes.png";
                        result.width = 120;
                        result.height = 150;
                        break;
                    default:
                        return null;
                }
            }

            return result;
        }

        function asRgbaValue( colorValue, transparencyValue ) {

            var color = hexToRgb( colorValue ),
                alpha = asAlpha( transparencyValue );

            return "rgba(" + color.r + ", " + color.g + ", " + color.b + ", " + alpha + ")";
        }

        function asAlpha( percentValue ) {
            return ( 100 - percentValue ) / 100;
        }

        function hexToRgb( hex ) {
            var result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec( hex );
            return result ? {
                r: parseInt( result[1], 16 ),
                g: parseInt( result[2], 16 ),
                b: parseInt( result[3], 16 )
            } : {
                    r: 0,
                    g: 0,
                    b: 0
                };
        }

        function getText( parameterName, defaultTextName ) {
            var paramValue = ( metadata.parameters.get( parameterName, "" ) || "").trim();
            return ( paramValue.length > 0 ) ? paramValue : uiText.get( defaultTextName, metadata.stage.getContentLanguage() );
        }

		// 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( enabled && !button.hasState( ButtonState.Pressed ) ) {
                button.changeState( ButtonState.Hover );
            }
		}

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

		function onMouseDown( e ) {

			lockNavigation();

		    if( !enabled ) {
                return;
            }

                button.changeState( ButtonState.Pressed );

            e.preventDefault();
            e.stopPropagation();
		}

		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) {

			unlockNavigation();

            if( !enabled ) {
                return;
            }

			e.preventDefault();
			e.stopPropagation();

            button.changeState( ButtonState.Default );

            if ( isOnTarget( e ) ) {
                close();
			}
        }

        function close() {
            if ( showDialog ) {
                closeDialog.showDialog();
            } else {
                context.stage.navigation.terminate();
            }
        }

        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 || !buttonInitialized) {
                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 || !buttonInitialized) {
                return;
            }

            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 initializeButton(){

        	if( buttonInitialized ){
        		return;
			}
            buttonInitialized = true;

            var scParams = metadata.parameters;

            shellElement.css({
                "width": metadata.getWidth() + "px",
                "height": metadata.getHeight() + "px"
            });

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

            initPointerEventNames();

            if ( showDialog ) {
                closeDialog = new DialogBuilder( context, metadata, {
                    Id: metadata.getId(),
                    isInAuthoringMode: isInAuthoringMode,
                    hasStageTriggerSupport: hasStageTriggerSupport,
                    showDialog: showDialog,
                    stageSize: {
                        height: jq( context.getPositioningElement() ).closest( '.ttclasssimulation' ).height(),
                        width: jq( context.getPositioningElement() ).closest( '.ttclasssimulation' ).width()
                    },
                    pointerDownEventName: pointerDownEventName,
                    pointerMoveEventNames: pointerMoveEventNames,
                    pointerLeaveEventNames: pointerLeaveEventNames,
                    pointerUpEventName: pointerUpEventName,
                    noButton: {
                        image: loadImage( "noButton", scParams.get( "bg_image_no_button", null ) ),
                        showLabel: scParams.asBool( "show_label_no_button" ),
                        label: {
                            text: getText( "label_no_button", "player.navigation.button.labelNoButton" ),
                            fontFamily: getFontStyle( scParams.asNumber( "font_family_no_button", 1 ) ),
                            fontSize: scParams.get( "font_size_no_button", "21" ),
                            fontColor: scParams.get( "color_no_button", "#ffffff" ),
                            fontColorHover: scParams.get( "color_hover_no_button", "#ffffff" ),
                            fontColorPressed: scParams.get( "color_pressed_no_button", "#ffffff" ),
                            horizontalAlign: scParams.get( "text_orientation_no_button", "left" ),
                            verticalAlign: scParams.get( "text_vertical_align_no_button", "middle" ),
                            paddingLeft: scParams.asNumber( "padding_left_no_button", "10" ),
                            paddingRight: scParams.asNumber( "padding_right_no_button", "95" ),
                            paddingTop: scParams.asNumber( "padding_top_no_button", "10" ),
                            paddingBottom: scParams.asNumber( "padding_bottom_no_button", "10" )
                        },
                        ariaLabel: ((metadata.parameters.get("aria-label-no", false) || "").trim() === "") ? false : metadata.parameters.get("aria-label-no", false)
                    },
                    yesButton: {
                        image: loadImage( "yesButton", scParams.get( "bg_image_yes_button", null ) ),
                        showLabel: scParams.asBool( "show_label_yes_button" ),
                        label: {
                            text: getText( "label_yes_button", "player.navigation.button.labelYesButton" ),
                            fontFamily: getFontStyle( scParams.asNumber( "font_family_yes_button", 1 ) ),
                            fontSize: scParams.get( "font_size_yes_button", "21" ),
                            fontColor: scParams.get( "color_yes_button", "#ffffff" ),
                            fontColorHover: scParams.get( "color_hover_yes_button", "#ffffff" ),
                            fontColorPressed: scParams.get( "color_pressed_yes_button", "#ffffff" ),
                            horizontalAlign: scParams.get( "text_orientation_yes_button", "left" ),
                            verticalAlign: scParams.get( "text_vertical_align_yes_button", "middle" ),
                            paddingLeft: scParams.asNumber( "padding_left_yes_button", "10" ),
                            paddingRight: scParams.asNumber( "padding_right_yes_button", "95" ),
                            paddingTop: scParams.asNumber( "padding_top_yes_button", "10" ),
                            paddingBottom: scParams.asNumber( "padding_bottom_yes_button", "10" )
                        },
                        ariaLabel: ((metadata.parameters.get("aria-label-yes", false) || "").trim() === "") ? false : metadata.parameters.get("aria-label-yes", false)
                    },
                    text: {
                        text: getText( "text_dialog", "player.navigation.button.text" ),
                        fontFamily: getFontStyle( scParams.asNumber( "font_family_text", 1 ) ),
                        fontSize: scParams.get( "font_size_text", "21" ),
                        fontColor: scParams.get( "color_text", "#000000" ),
                        horizontalAlign: scParams.get( "text_orientation_text", "left" ),
                        bold: scParams.asBool( "bold_text" ),
                        italic: scParams.asBool( "italic_text" ),
                        underline: scParams.asBool( "underline_text" ),
                        paddingLeft: scParams.asNumber( "padding_left_text", "10" ),
                        paddingRight: scParams.asNumber( "padding_right_text", "10" ),
                        paddingTop: scParams.asNumber( "padding_top_text", "38" )
                    },
                    dialog: {
                        width: scParams.get( "width_dialog", "530" ),
                        height: scParams.get( "height_dialog", "250" ),
                        border: {
                            width: scParams.get( "border_width_dialog", "0" ),
                            backgroundColor: asRgbaValue( scParams.get( "border_color_dialog", "#ffffff" ), scParams.asNumber( "border_transparency_dialog", 0 ) )
                        },
                        dialog: {
                            backgroundColor: asRgbaValue( scParams.get( "fill_color_dialog", "#ffffff" ), scParams.asNumber( "fill_color_transparency_dialog", 0 ) )
                        },
                        cover: {
                            backgroundColor: asRgbaValue( scParams.get( "fill_color_content_cover_dialog", "#000000" ), scParams.asNumber( "fill_color_transparency_content_cover_dialog", 50 ) )
                        }
                    },
                    accessibilityKeys: {
                        yes: metadata.parameters.get( "accessibility-key-yes", null ),
                        no: metadata.parameters.get( "accessibility-key-no", null ),
                        accessibilityLocation: accessibilityLocation,
                        accessibilityPositionX: accessibilityPositionX,
                        accessibilityPositionY: accessibilityPositionY
                    }
                } ).build();

                jq( context.getPositioningElement() ).closest( '.ttclasssimulation' ).append( closeDialog.getElement() );
            }
            shellElement.append( button.getHotspotElement() );

            accessibilityTooltipClose = new AccessibilityBuilder(accessibilityKeyClose, accessibilityLocation, accessibilityPositionX, accessibilityPositionY, context).build();
            if (accessibilityTooltipClose.getElement()) {
                shellElement.append( accessibilityTooltipClose.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.close", 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_" + metadata.getId(),
                width: metadata.getWidth(),
                height: metadata.getHeight(),
                caption: uiText.get("player.navigation.button.close", 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( isStandardPlayer ) {
					initializeButton();
                }

                context.page.event.bind( instance, "onNextOnLastPage" );

                bindEvents();
                if (!isStandardPlayer && !exludeFromTabControl) {
                    accessibilityTooltipClose.registerTabNavigation(metadata.getId(), accessibilityTabOrder);
                }
                if ( showDialog ) {
                    closeDialog.bindEvents();
                }

                unlockNavigation();
			},
            onExitPage: function() {
                removeEvents();
                if ( showDialog ) {
                    closeDialog.removeEvents();
                }
                context.stage.accessibility.turnAccessibilityModeOff();
            },
            onNextOnLastPage: close,
            onAccessibilityModeChanged: function ( dataHTML5, dataHTML4 ) {
                var params = dataHTML4 || dataHTML5;

                if ( params.isActive ) {
                    accessibilityTooltipClose.show();
                    if ( closeDialog ) {
                        closeDialog.showAccessibilityTooltips();
                    }
                } else {
                    accessibilityTooltipClose.hide();
                    if ( closeDialog ) {
                        closeDialog.hideAccessibilityTooltips();
                    }
                }
            },
            onAccessibilityKeyPressed: function ( dataHTML5, dataHTML4 ) {
                var params = dataHTML4 || dataHTML5;

                if ( params.keyCode == accessibilityTooltipClose.getKeyCode() ) {
                    close();
                }

                if ( closeDialog && closeDialog.isVisible() ) {
                    var accessibilityKeyCodes = closeDialog.getAccessibilityKeyCodes();

                    if ( params.keyCode == accessibilityKeyCodes.noButton ) {
                        context.stage.accessibility.turnAccessibilityModeOff();
                        closeDialog.hideDialog();
                    }
                    if ( params.keyCode == accessibilityKeyCodes.yesButton ) {
                        context.stage.accessibility.turnAccessibilityModeOff();
                        closeDialog.hideDialog();
                        context.stage.navigation.terminate();
                    }
                }
            },
            onTabNavigationSelection: function (dataHTML5, dataHTML4, data) {
                if (data && data.id && data.id == metadata.getId()) {
                    button.focusButton();
                } else {
                    button.blurButton();
                }
            },
            onTabNavigationOff: function (dataHTML5, dataHTML4) {
                button.blurButton();
            },
            onTabNavigationFire: function (dataHTML5, dataHTML4, data) {
                if (data && data.id && data.id == metadata.getId()) {
                    close();
                }
            }
		};
	};
});
