define( [
    "jquery",
    "./togglebutton.builder",
    "./accessibility.builder",
    "css!./togglebutton.css",
    "css!./playmodes.css"
],
function (
    jq,
    ToggleButtonBuilder,
    AccessibilityBuilder
){

    "use strict";

    /**
     * @constructor
     */

     return function( options, context, metadata ){

        var playmodesButton,
            button,
            playmodesButtonHotSpotElement,
            playmodesContainer,
            menuItemInteractive,
            menuItemPresentation,
            menuItemFilm,
            accessibilityTooltipInteractive,
            accessibilityTooltipPresentation,
            accessibilityTooltipFilm,
            availablePlayModes,
            individualPlayMode;
        
        //HELPER FUNCTION
        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 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;
        }

        // PLAYMODES CREATION FUNCTIONS
        function createPlaymodes()  {

            var imageOptions = options.image.button;

            playmodesButton = jq(document.createElement("div"))
                .attr({
                    "id": "playmodesButton" + options.instanceID,
                    "title" : options.caption
                })
                .css({
                    "width": (imageOptions.width / 3) + "px",
                    "height": (imageOptions.height / 3) + "px"
                })
                .addClass("playmodesButton");

            playmodesButtonHotSpotElement = jq(document.createElement("div"))
                .attr({
                    "id": "playmodesButtonHotSpotElement" + options.instanceID,
                    "title" : options.caption
                })
                .css({
                    "width": (imageOptions.width / 3) + "px",
                    "height": (imageOptions.height / 3) + "px"
                })
                .addClass("playmodesButtonHotSpotElement");

            button = new ToggleButtonBuilder({
                fileNameURL : imageOptions.fileNameURL,
                width : imageOptions.width / 3,
                height : imageOptions.height / 3,
                name : "playmodesButton",
                captionText: options.caption
            }, context, metadata ).build();

            playmodesContainer = createPlaymodesContainer();

            playmodesButton.append(button.getElement());
            playmodesButton.append(playmodesButtonHotSpotElement);
            playmodesButton.append(playmodesContainer.getElement());
        }

        function createPlaymodesContainer() {

            var items = new Array(),
                isContainerOpen = false,
                position = getMenuPosition(),
                fillColor = options.fillColor,
                fillTransparency = options.fillTransparency,
                borderColor = options.borderColor,
                borderTransparency = options.borderTransparency,
                container = jq(document.createElement("div"))
                    .attr({
                        "id": "playmodesContainer" + options.instanceID
                    })
                    .css({
                        "width": options.menuWidth + "px",
                        "height": options.menuHeight + "px",
                        "border": options.borderWidth + "px solid " + asRgbaValue(borderColor, borderTransparency),
                        "background-color" : asRgbaValue(fillColor, fillTransparency)
                    })
                    .css(position)
                    .addClass("playmodesContainer")
                    .on(options.pointerEvents.pointerDown, function(e){
                        cancelEvent(e);
                        lockNavigation();
                    })
                    .on(options.pointerEvents.pointerUp, function(e){
                        cancelEvent(e);
                        unlockNavigation();
                    })
                    .on("dblclick", cancelEvent );

                context.page.interaction.provokesFeedback( container, false );
                context.page.interaction.provokesAutosolve( container, false );

            if(options.AuthoringMode && options.showMenuInAuthoringMode){
                container.css({
                    "opacity" : "0.15",
                    "background-image" : "url(\"" + context.getPath() + "invis.png\")",
                    "text-align" : "center",
                    "line-height" : options.menuHeight + "px",
                    "font-size" : "24px"
                })
                .text( "Play modes" )
                .show();
            }else{
                container.hide();
            }

            return {
                getElement : function(){
                    return container.get(0);
                },
                addItem : function(item){             
                    items.push(item);
                    container.append(item.getElement());
                },
                getItems : function(){
                    return items;
                },
                hideContainer : function(){
                    isContainerOpen = false;
                    container.hide();
                },
                showContainer : function(){
                    isContainerOpen = true;
                    container.show();
                },
                isOpen : function(){
                    return isContainerOpen;
                },
                resetPlaymodesContainer : function(){
                    items.length = 0;
                    container.empty();
                }
            }
        }

        function createPlaymodesContent( menuContainer ) {

            availablePlayModes = metadata.stage.getAvailablePlayModes(),
            individualPlayMode = getIndividualPlayMode();

            if ( ( individualPlayMode === "none" || individualPlayMode === "interactive" ) && availablePlayModes.interactive ) {
                menuItemInteractive = createMenuItem( "interactive", options.entryTexts.interactive, function ( e ) {
                    cancelEvent( e );
                    unlockNavigation();
                    context.stage.accessibility.turnAccessibilityModeOff();
                    setInteractiveMode();
                } );
                menuContainer.addItem( menuItemInteractive );
                if ( options.accessibilityKeys.interactive ) {
                    accessibilityTooltipInteractive = new AccessibilityBuilder( options.accessibilityKeys.interactive, options.accessibilityKeys.accessibilityLocation, options.accessibilityKeys.accessibilityPositionX, options.accessibilityKeys.accessibilityPositionY ).build();
                    menuItemInteractive.addAccessibilityTooltip( accessibilityTooltipInteractive.getElement() );
                }
            }

            if ( ( individualPlayMode === "none" || individualPlayMode === "presentation" ) && availablePlayModes.presentation ) {
                menuItemPresentation = createMenuItem( "presentation", options.entryTexts.presentation, function ( e ) {
                    cancelEvent( e );
                    unlockNavigation();
                    context.stage.accessibility.turnAccessibilityModeOff();
                    setPresentationMode();
                } );
                menuContainer.addItem( menuItemPresentation );
                if ( options.accessibilityKeys.presentation ) {
                    accessibilityTooltipPresentation = new AccessibilityBuilder( options.accessibilityKeys.presentation, options.accessibilityKeys.accessibilityLocation, options.accessibilityKeys.accessibilityPositionX, options.accessibilityKeys.accessibilityPositionY ).build();
                    menuItemPresentation.addAccessibilityTooltip( accessibilityTooltipPresentation.getElement() );
                }
            }

            if ( ( individualPlayMode === "none" || individualPlayMode === "film" ) && availablePlayModes.film ) {
                menuItemFilm = createMenuItem( "film", options.entryTexts.film, function ( e ) {
                    cancelEvent( e );
                    unlockNavigation();
                    context.stage.accessibility.turnAccessibilityModeOff();
                    setFilmMode();
                } );
                menuContainer.addItem( menuItemFilm );
                if ( options.accessibilityKeys.film ) {
                    accessibilityTooltipFilm = new AccessibilityBuilder( options.accessibilityKeys.film, options.accessibilityKeys.accessibilityLocation, options.accessibilityKeys.accessibilityPositionX, options.accessibilityKeys.accessibilityPositionY ).build();
                    menuItemFilm.addAccessibilityTooltip( accessibilityTooltipFilm.getElement() );
                }
            }
        }

         function getIndividualPlayMode() {

             if( metadata.page && metadata.page.getIndividualPlayMode ){
                 metadata.page.getIndividualPlayMode();
             }

             return "none";
         }

         function createMenuItem( id, caption, action ) {

            var item,
                marker,
                elementId = id,
                textColor = options.textColor,
                hoverColor = options.textHoverColor,
                separatorColor = options.separatorColor,
                separatorTransparency = options.separatorTransparency,
                itemPaddingLeft = parseInt(options.paddingLeft),
                itemPaddingRight = parseInt(options.paddingRight) + parseInt(options.image.marker.width) + 10,
                itemWidth = parseInt(options.menuWidth) - itemPaddingLeft - itemPaddingRight;

            item = jq(document.createElement("div"))
            .attr( "id", id + "-item" + options.instanceID )
            .css({
                "border-bottom": options.separatorWidth + "px solid " + asRgbaValue(separatorColor, separatorTransparency),
                "color": textColor,
                "font-family": options.fontFamily,
                "padding-left": itemPaddingLeft + "px",
                "padding-right": itemPaddingRight  + "px",
                "padding-top": options.paddingTop + "px",
                "padding-bottom": options.paddingBottom + "px",
                "font-size": options.fontSize + "px",
                "width" : itemWidth + "px",
            })
            .addClass("item text")
            .text(caption)
            .on(options.pointerEvents.pointerDown, function(e){
                cancelEvent(e);
                lockNavigation();
            })
            .on(options.pointerEvents.pointerUp, action)
            .on(options.pointerEvents.pointerMove, function(){
                jq(this).css("color", hoverColor);
            })
            .on(options.pointerEvents.pointerLeave, function(){
                jq(this).css("color", textColor);
            })
            .on("dblclick", cancelEvent );

            if(id == "film"){
                item.css({
                    "border-bottom": "none"
                })
            }

            marker = jq(document.createElement("img"))
                .attr({
                    "id" : id + "-marker" + options.instanceID,
                    "src" : options.image.marker.fileNameURL
                })
                .css({
                    "width": options.image.marker.width + "px",
                    "height": options.image.marker.height + "px"
                })
                .addClass("marker")
                .hide();

             item.append( marker );

            return {
                getId : function(){
                    return elementId;
                },
                getElement : function(){
                    return item;
                },
                getHotspotElement: function () {
                    return item.get(0);
                },
                setMarked : function(){
                    marker.show();
                },
                unsetMarked : function(){
                    marker.hide();
                },
                addAccessibilityTooltip: function (tooltip) {
                    item.append(tooltip);
                }
            }
        }

        // PLAYMODES HELPER FUNCTIONS

        function getMenuPosition(){

            var buttonWidth = options.image.button.width / 3,
                buttonHeight = options.image.button.height / 3,
                menuWidth = options.menuWidth,
                menuHeight = options.menuHeight,
                border = options.borderWidth,
                menuPositions = [
                    //bottom-left
                    {
                        "top": buttonHeight + "px",
                        "right": menuWidth + (border * 2) + "px"
                    },
                    //top-left
                    {
                        "bottom": menuHeight + (border * 2) + "px",
                        "right": menuWidth + (border * 2) + "px"
                    },
                    //top-centered
                    {
                        "bottom": menuHeight + (border * 2) + "px",
                        "right": (menuWidth + (border * 2) - buttonWidth) / 2 + "px"
                    },
                    //top-right
                    {
                        "bottom": menuHeight + (border * 2) + "px",
                        "left": buttonWidth + "px"
                    },
                    //right-centered
                    {
                        "bottom": (menuHeight + (border * 2) - buttonWidth) / 2 + "px",
                        "left": buttonWidth + "px"
                    },
                    //bottom-right
                    {
                        "top": buttonHeight + "px",
                        "left": buttonWidth + "px"
                    },
                    //bottom-centered
                    {
                        "top": buttonHeight + "px",
                        "right": (menuWidth + (border * 2) - buttonWidth) / 2 + "px"
                    },
                    //left-centered
                    {
                        "bottom": (menuHeight + (border * 2) - buttonWidth) / 2 + "px",
                        "right": menuWidth + (border * 2) + "px"
                    }
                ],
                posOption = options.position;

            if(posOption != 8){
                return menuPositions[ posOption ];
            }else{
                return {
                    "top": options.menuPositionY + "px",
                    "left": options.menuPositionX + "px"
                };
            }
        }

        function setMarker( id ){
            var items = playmodesContainer.getItems();
            jq.each( items, function(index,item){
                item.unsetMarked();
                if( item.getId() === id ){
                    item.setMarked();
                }
            });
        }

        // EVENT HELPER FUNTIONS
        function lockNavigation() {
            if (context.stage.isInAuthoringMode() || (typeof(context.stage.trigger) === "undefined")) {
                return;
            }
            context.stage.trigger.lock( metadata.getId() );
        }

        function unlockNavigation() {
            if (context.stage.isInAuthoringMode() || (typeof(context.stage.trigger) === "undefined")) {
                return;
            }
            context.stage.trigger.unlock( metadata.getId() );
        }

        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 cancelEvent( e ){
            e.preventDefault();
            e.stopPropagation();
         }

        function toggleMenu() {
            if ( playmodesContainer.isOpen() ) {
                playmodesContainer.hideContainer();
            } else {
                playmodesContainer.showContainer();
            }
         }

         function setInteractiveMode() {
             if ( playmodesContainer.isOpen() ) {
                 toggleMenu();
                 context.stage.navigation.switchToInteractiveMode();
             }
            setMarker( "interactive" );
            button.changeToggleState( "btn_state_interactive" );
        }

         function setPresentationMode() {
             if ( playmodesContainer.isOpen() ) {
                 toggleMenu();
                 context.stage.navigation.switchToPresentationMode();
             }
            setMarker( "presentation" );
            button.changeToggleState( "btn_state_presentation" );
        }

         function setFilmMode() {
             if ( playmodesContainer.isOpen() ) {
                 toggleMenu();
                 context.stage.navigation.switchToFilmMode();
             }
            setMarker( "film" );
            button.changeToggleState( "btn_state_film" );
        }

        return {
            build : function(){
                createPlaymodes();
                return {
                    getElement : function(){
                        return playmodesButton.get(0);
                    },
                    getHotSpotElement : function(){
                        return playmodesButtonHotSpotElement.get(0);
                    },
                    onMouseLeave : function(){
                        button.onMouseLeave();
                    },
                    onMouseOver : function(){
                        button.onMouseOver();
                    },
                    onMouseDown : function(e){
                        lockNavigation();
                        cancelEvent( e );

                        button.onMouseDown(e);
                    },
                    onMouseUp : function(e){
                        unlockNavigation();
                        cancelEvent( e );

                        button.onMouseLeave();
                        
                        if(!isOnTarget(e)) {
                            return;
                        }

                        toggleMenu();

                        button.onMouseUp(e);
                    },
                    onEnterPage : function() {
                        createPlaymodesContent(playmodesContainer);         
                    },
                    onExitPage : function() {
                        playmodesContainer.hideContainer();
                        playmodesContainer.resetPlaymodesContainer();
                        button.onMouseLeave();
                    },
                    isOpen: function () {
                        return playmodesContainer.isOpen();
                    },
                    toggleMenu: toggleMenu,

                    setInteractiveMode: setInteractiveMode,
                    setPresentationMode: setPresentationMode,
                    setFilmMode: setFilmMode,

                    getAccessibilityKeyCodes: function () {
                        var result = {};

                        if ( ( individualPlayMode === "none" || individualPlayMode === "interactive" ) && availablePlayModes.interactive ) {
                            result.interactive = accessibilityTooltipInteractive.getKeyCode();
                        }
                        if ( ( individualPlayMode === "none" || individualPlayMode === "presentation" ) && availablePlayModes.presentation ) {
                            result.presentation = accessibilityTooltipPresentation.getKeyCode();
                        }
                        if ( ( individualPlayMode === "none" || individualPlayMode === "film" ) && availablePlayModes.film ) {
                            result.film = accessibilityTooltipFilm.getKeyCode();
                        }
                        return result;
                    },
                    showAccessibilityTooltips: function () {
                        if (( individualPlayMode === "none" || individualPlayMode === "interactive" ) && availablePlayModes.interactive ) {
                            accessibilityTooltipInteractive.show();
                        }
                        if ( ( individualPlayMode === "none" || individualPlayMode === "presentation" ) && availablePlayModes.presentation ) {
                            accessibilityTooltipPresentation.show();
                        }
                        if ( ( individualPlayMode === "none" || individualPlayMode === "film" ) && availablePlayModes.film ) {
                            accessibilityTooltipFilm.show();
                        }
                    },
                    hideAccessibilityTooltips: function () {
                        if ( ( individualPlayMode === "none" || individualPlayMode === "interactive" ) && availablePlayModes.interactive ) {
                            accessibilityTooltipInteractive.hide();
                        }
                        if ( ( individualPlayMode === "none" || individualPlayMode === "presentation" ) && availablePlayModes.presentation ) {
                            accessibilityTooltipPresentation.hide();
                        }
                        if ( ( individualPlayMode === "none" || individualPlayMode === "film" ) && availablePlayModes.film ) {
                            accessibilityTooltipFilm.hide();
                        }
                    }
                };
            }
        }
    };
});
