// com.tts.initial.html5.navigation.next
// HTML4 / HTML5: No dif
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,
            instance,
            button,
            triggerCloseButton = metadata.parameters.asBool( "trigger_close_button" ),
            useBlinking = metadata.parameters.asBool( "use_blinking", true ),
            currentPlayMode,
            runningAnimations = new Array(),
            delayedAnimations = new Array(),
            finishedAnimations = new Array(),
            blinkingFunction,
            isBlinkingOn = false,
            buttonInitialized = false,
            m_buttonEnabled = true,
            isStandardPlayer = context.getPlayerName() === "standard",
            pageId = metadata.page.getId(),
            hasStageTriggerSupport = true,
            isInAuthoringMode = false,
            pointerUpEventNames,
            pointerDownEventNames,
            pointerMoveEventNames,
            pointerLeaveEventNames,
            accessibilityTooltip,
            accessibilityKey = metadata.parameters.get( "accessibility-key", null ),
            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() + "next.png";
            }

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

            return deferred.promise();
        }

        // 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": "transparent",
                    "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 ( isEnabled() ) {
                if ( !button.hasState( ButtonState.Pressed ) ) {
                    button.changeState( ButtonState.Hover );
                }
            }
        }

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

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

            if ( !isEnabled() ) {
                return;
            }

            button.changeState( ButtonState.Default );

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

        function next() {

            if ( !isEnabled() ) {
                return;
            }

            if ( metadata.page.hasInteraction() && currentPlayMode === "presentation" ) {
                return;
            }

            context.stage.accessibility.turnAccessibilityModeOff();

            var isMainPath = true,
                getLearningPath;

            if ( metadata.page && typeof metadata.page.getLearningPath === "function" ) {
                getLearningPath = metadata.page.getLearningPath();
                if ( typeof getLearningPath.isMainLearningPath === "function" ) {
                    isMainPath = getLearningPath.isMainLearningPath();
                }
            }

            if ( isLastPage() && isMainPath ) {
                if ( triggerCloseButton ) {
                    context.page.event.fire( instance, "onNextOnLastPage" );
                } else {
                    context.stage.navigation.terminate();
                }
            } else {
                context.stage.navigation.nextPage();
            }
        }

        function isEnabled() {
            return m_buttonEnabled;
        }

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

        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 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 ) {
            if ( !isLastPage() ) {
                if ( currentPlayMode === "interactive" ) {
                    e.preventDefault();
                    e.stopPropagation();
                }
            } else {
                    if ( triggerCloseButton ) {
                        e.preventDefault();
                        e.stopPropagation();
                    }
            }
        }

        function isLastPage() {

            var allPages = metadata.stage.pages,
                lastPage;

            if ( !allPages || allPages.length === 0 ) {
                return false;
            }

            lastPage = allPages[allPages.length - 1];

            return lastPage.getId() === metadata.page.getId();
        }

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

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

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

            initPointerEventNames();

            shellElement.append( button.getHotspotElement() );
            if ( accessibilityKey ) {
                accessibilityTooltip = new AccessibilityBuilder( accessibilityKey, accessibilityLocation, accessibilityPositionX, accessibilityPositionY ).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: uiText.get( "player.navigation.button.next", metadata.stage.getContentLanguage() ),
                    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.next", metadata.stage.getContentLanguage() ),
                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 );
        }

        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 initializeButtonMode() {
            var defaultPlayMode = metadata.stage.getDefaultPlayMode(),
                individualPlayMode = metadata.page.getIndividualPlayMode();

            currentPlayMode = individualPlayMode !== "none" ? individualPlayMode : defaultPlayMode;

            if ( isInteractivePage() && currentPlayMode === "interactive" ) {
                disableButton();
                return;
            }

            if ( isDisableNextWhileAnimations() && ( hasRunningAnimations() || hasDelayedAnimations() ) ) {
                disableButton();
                return;
            }

            enableButton();

            if ( !hasRunningAnimations() && !hasDelayedAnimations() && !isFilmmodePage() ) {
                startBlinking();
            }
        }

        function hasRunningAnimations() {
            return (runningAnimations.length > 0) ? true : false;
        }

        function hasDelayedAnimations() {
            return ( delayedAnimations.length > 0 ) ? true : false;
        }

        function isDisableNextWhileAnimations() {
            return metadata.page.getDisableNextWhileAnimations();
        }

        function isInteractivePage() {
            return metadata.page.hasInteraction();
        }

        function isFilmmodePage() {
            return ( currentPlayMode === "film" ) ? true : false;
        }

        function setButtonModeFromOnPlayModeChanged() {
            if ( isInteractivePage() && currentPlayMode === "interactive" ) {
                disableButton();
                return;
            }

            if ( isDisableNextWhileAnimations() && ( hasRunningAnimations() || hasDelayedAnimations() ) ) {
                disableButton();
                return;
            }

            enableButton();

            if ( !hasRunningAnimations() && !hasDelayedAnimations() && !isFilmmodePage() ) {
                startBlinking();
            } else {
                stopBlinking();
            }
        }

        function setButtonModeFromOnAnimationStateChanged( animation ) {
            var indexRunningAnimation = runningAnimations.indexOf( animation.id ),
                indexDelayedAnimation = delayedAnimations.indexOf( animation.id );

            if ( animation.state === "delayed" && finishedAnimations.indexOf( animation.id ) == -1 && delayedAnimations.indexOf( animation.id ) == -1 ) {
                delayedAnimations.push( animation.id );
            }

            if ( animation.state === "started" && finishedAnimations.indexOf( animation.id ) == -1 && runningAnimations.indexOf( animation.id ) == -1) { // || ( animation.state === "repeated" && animation.isFiniteRepeats ) ) {
                    runningAnimations.push( animation.id );
                if ( indexDelayedAnimation > -1 ) {
                    delayedAnimations.splice( indexDelayedAnimation, 1 );
                }
            }

            if ( animation.state === "finished" && finishedAnimations.indexOf( animation.id ) == -1 ) {
                finishedAnimations.push( animation.id );
                if ( indexRunningAnimation > -1 ) {
                    runningAnimations.splice( indexRunningAnimation, 1 );
                }
            }

            if ( isInteractivePage() && currentPlayMode === "interactive" ) {
                disableButton();
                return;
            }

            if ( isDisableNextWhileAnimations() && ( hasRunningAnimations() || hasDelayedAnimations()) ) {
                disableButton();
                return;
            }

            enableButton();

            if ( !hasRunningAnimations() && !hasDelayedAnimations() && !isFilmmodePage() ) {
                startBlinking();
            } else {
                stopBlinking();
            }
        }

        function resetValues() {
            stopBlinking();
            currentPlayMode = null;
            runningAnimations.length = 0;
            delayedAnimations.length = 0;
            finishedAnimations.length = 0;
            m_buttonEnabled = true;
        }

        function startBlinking() {
            if ( isEnabled && !blinkingFunction && useBlinking ) {
                isBlinkingOn = false;
                blinkingFunction = setInterval( function () {
                    if ( isBlinkingOn ) {
                        button.changeState( ButtonState.Default );
                        isBlinkingOn = false;
                    } else {
                        button.changeState( ButtonState.Hover );
                        isBlinkingOn = true;
                    }
                }, 500 );
            }
        }

        function stopBlinking() {
            if ( useBlinking ) {
                clearInterval( blinkingFunction );
                blinkingFunction = null;
            }
        }

		// revealing public API
		return {
			onLoading: function () {

                instance = this;

				context.page.event.bindOnEnter( instance );
                context.page.event.bindOnExit( instance );
                context.stage.event.bindOnPlayModeChanged( instance );
                context.page.event.bindOnAnimationStateChanged( instance );
                context.stage.accessibility.bindOnAccessibilityModeChanged( instance );

				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 () {
                resetValues();
				// because of some problems with loading SVG while it is hidden on page,
				// we initialize SVG button onEnterPage
                if ( !buttonInitialized ) {
                    initializeButton();
                }

                initializeButtonMode();
                bindEvents();
            },

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

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

                currentPlayMode = params.mode;

                setButtonModeFromOnPlayModeChanged();
            },

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

                setButtonModeFromOnAnimationStateChanged( params );
            },

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