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

	"use strict";

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

        var shellElement,
            instance,
            button,
            m_buttonEnabled = true,
            id = metadata.parameters.get( "id", 1 ),
            currentMode,
            controlMode = metadata.parameters.get( "control_mode", "play" ),
            buttonInitialized = false,
			hasStageTriggerSupport = true,
            isInAuthoringMode = false,
            isInPreviewMode = false,
            isStandardPlayer = context.getPlayerName() === "standard",
            contentLanguage = metadata.stage.getContentLanguage(),
            pageId = metadata.page.getId(),
            pointerUpEventNames,
            pointerDownEventNames,
            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 / 3;
                result.height = this.height / 4;
                deferred.resolve( result );
            };

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

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

            return deferred.promise();
        }

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

            switch ( controlMode ) {
                case "play":
                    currentMode = "PLAY";
                    break;
                case "stop":
                    currentMode = "STOP";
                    break;
                case "pause":
                    currentMode = "PAUSE";
                    break;
                default:
                    currentMode = "PLAY";
            }

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

            initPointerEventNames();

            shellElement.append(button.getHotspotElement());

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

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

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

        function createImageButton() {

            var scParams = metadata.parameters,
                imageButton = new ImageButtonBuilder( {
                    width: metadata.getWidth(),
                    height: metadata.getHeight(),
                    caption: getCaption(),
                    ariaLabel: ((metadata.parameters.get("aria-label", false)|| "").trim() === "") ? false : metadata.parameters.get("aria-label", false),
                    mode: currentMode,
                    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: getCaption(),
                ariaLabel: ((metadata.parameters.get("aria-label", false)||"").trim() === "") ? false : metadata.parameters.get("aria-label", false),
                mode: currentMode,
                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 getText( parameterName, defaultTextName ) {
            var paramValue = ( metadata.parameters.get( parameterName, "" ) || "" ).trim();
            return ( paramValue.length > 0 ) ? paramValue : uiText.get( defaultTextName, contentLanguage );
        }

        function getCaption() {
            switch ( currentMode ) {
                case "PLAY":
                    return getText( "caption", "player.animated.videocontrolbutton.play" );
                case "STOP":
                    return getText( "caption", "player.animated.videocontrolbutton.stop" );
                case "PAUSE":
                    return getText( "caption", "player.animated.videocontrolbutton.pause" );
                default:
            }
        }

        // create an object shield so we are able to select and drag element
		function createAuthoringShield() {
			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 initPointerEventNames() {
            if ( !pointerUpEventNames ) {
                var nodeName = getHotspotElementNodeName();
                pointerDownEventNames = context.device.getDownEvents( nodeName );
                pointerUpEventNames = 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 onMouseOver() {
            if ( isEnabled() ) {
                if ( !button.hasState( ButtonState.Pressed ) ) {
                    button.changeState( ButtonState.Hover );
                    setTimeout( function () {
                        context.page.event.trigger( instance, "tg_mouseover" );
                    }, 10 );
                }
            }
        }

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

        function onMouseUp( e ) {
            cancelEvent( e );
            if ( isEnabled() ) {
                unlockNavigation();
                button.changeState( ButtonState.Default );

                if ( !isOnTarget( e ) ) {
                    return;
                }

                fireTrigger();
            }
        }

        function fireTrigger() {
            setTimeout(function () {
                context.page.event.trigger(instance, "tg_pressed");
                switch (currentMode) {
                    case "PLAY":
                        context.page.event.fire(instance, "onControlButtonPlay", id);
                        break;
                    case "STOP":
                        context.page.event.fire(instance, "onControlButtonStop", id);
                        break;
                    case "PAUSE":
                        context.page.event.fire(instance, "onControlButtonPause", id);
                        break;
                    default:
                        break;
                }
            }, 10);

            context.stage.accessibility.turnAccessibilityModeOff();
        }

        function onMouseLeave() {
            unlockNavigation();
            if ( isEnabled() ) {
                button.changeState( ButtonState.Default );
                setTimeout( function () {
                    context.page.event.trigger( instance, "tg_mouseleave" );
                }, 10 );
            }
        }

        function enableButton() {
            if ( buttonInitialized && !m_buttonEnabled ) {
                button.changeState( ButtonState.Default );
                m_buttonEnabled = true;
            }
        }

        function disableButton() {
            if ( buttonInitialized && m_buttonEnabled ) {
                button.changeState( ButtonState.Inactive );
                m_buttonEnabled = false;
                stopBlinking();
            }
        }

        function isEnabled() {
            return m_buttonEnabled;
        }

        function bindEvents() {
            if ( isInAuthoringMode ) {
                return;
            }

            if ( !button || !buttonInitialized ) {
                return;
            }

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

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

            context.device.removeFirstSupportedEvent( button.getHotspotElement(), pointerDownEventNames, onMouseDown );
            context.device.removeFirstSupportedEvent( button.getHotspotElement(), pointerMoveEventNames, onMouseOver );
            context.device.removeFirstSupportedEvent( button.getHotspotElement(), pointerLeaveEventNames, onMouseLeave );
            context.device.removeFirstSupportedEvent( button.getHotspotElement(), pointerUpEventNames, onMouseUp );
        }

        function cancelEvent( e ) {
            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 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, currentMode );
        }

		// 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");
                }

                shellElement = jq( context.getElement() );

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

                // 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();
                }

                bindEvents();

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

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

            onAccessibilityModeChanged: function (dataHTML5, dataHTML4) {
                 var params = dataHTML4 || dataHTML5;

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

            onAccessibilityKeyPressed: function (dataHTML5, dataHTML4) {
                var params = dataHTML4 || dataHTML5;

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

            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()) {
                    fireTrigger();
                }
            }
		};
	};
});
