// com.tts.initial.html5.graphictogglebutton
// HTML4 / HTML5: No differences
define( [
    "./accessibility.builder",
    "jquery"
], function (
        AccessibilityBuilder,
        jq
    ) {

    "use strict";

    var ButtonState = {
        Default: "btn_state_default",
        Hover: "btn_state_hover",
        Pressed: "btn_state_pressed"
    },
        ButtonToggleState = {
            On: "btn_state_on",
            Off: "btn_state_off"
        },
        variableID,
        variableNamespace,

        //Was macht das hier?
        getClassName = function (toggleState, buttonState) {
            return toggleState + "_" + buttonState;
        },

        ImageButtonBuilder = function (options) {

            var backgroundPositions = {};

            backgroundPositions[ButtonToggleState.On] = {};
            backgroundPositions[ButtonToggleState.On][ButtonState.Default] = "0 0";
            backgroundPositions[ButtonToggleState.On][ButtonState.Hover] = "0 " + (-options.height) + "px";
            backgroundPositions[ButtonToggleState.On][ButtonState.Pressed] = "0 " + (-2 * options.height) + "px";

            backgroundPositions[ButtonToggleState.Off] = {};
            backgroundPositions[ButtonToggleState.Off][ButtonState.Default] = "-" + options.width + "px 0";
            backgroundPositions[ButtonToggleState.Off][ButtonState.Hover] = "-" + options.width + "px " + (-options.height) + "px";
            backgroundPositions[ButtonToggleState.Off][ButtonState.Pressed] = "-" + options.width + "px " + (-2 * options.height) + "px";

            function createTextContent() {

                if ((options.text.content||"").trim() === "") {
                    return null;
                }

                var textContainer = jq(document.createElement("div"))
                    .css({
                        "width": options.width + "px",
                        "padding-right": options.text.paddingRight + "px",
                        "padding-left": options.text.paddingLeft + "px",
                        "text-align": options.text.orientation
                    });

                if (options.text.verticalAlignment === "middle") {
                    textContainer.css({
                        "vertical-align": "middle",
                        "display": "table-cell"
                    });
                }
                else {
                    textContainer.css({
                        "position": "absolute",
                        "padding-top": options.text.paddingTop + "px",
                        "padding-bottom": options.text.paddingBottom + "px"
                    });

                    textContainer.css(options.text.verticalAlignment, "0");

                    if (options.text.orientation === "right") {
                        textContainer.css(options.text.orientation, "0");
                    }
                }

                if (options.tooltip) {
                    textContainer
                        .attr({
                            "title": options.tooltip
                        })
                }

                textContainer.html(options.text.content);
                return textContainer;
            }

            function createButton() {

                var currentState = ButtonState.Default,
                    currentToggleState,
                    imageButton = jq(document.createElement("button"))
                        .attr({
                            "class": currentState,
                            "role": "button",
                            "tab-index": "0"
                        })
                        .css({
                            "width": options.width + "px",
                            "height": options.height + "px",
                            "text-align": options.text.orientation,
                            "font-family": options.text.fontFamily,
                            "color": options.color,
                            "-webkit-tap-highlight-color": "rgba(0,0,0,0)",
                            "font-size": Math.min(Math.abs(options.text.fontSize), 100) + "px",
                            "cursor": "pointer",
                            "padding": "0",
                            "border": "none",
                            "background": "none"
                        })
                        .on("touchmove", function (e) {
                            e.preventDefault ? e.preventDefault() : true;
                        });

                if (options.text.verticalAlignment === "middle") {
                    imageButton.css("display", "table");
                }

                if (options.initialState == ButtonToggleState.Off && !options.state.saved) {
                    currentToggleState = ButtonToggleState.Off;
                } else {
                    if (options.initialState == ButtonToggleState.On && !options.state.saved) {
                        currentToggleState = ButtonToggleState.On;
                    } else {
                        if (options.state.saved) {
                            currentToggleState = options.state.saved;
                        } else {
                            currentToggleState = ButtonToggleState.Off;
                        }
                    }
                }

                if (currentToggleState === ButtonToggleState.Off) {
                    if (options.tooltip) {
                        imageButton.attr({
                            "title": options.tooltip
                        })
                    }

                    if (options.ariaLabel || options.tooltip) {
                        imageButton.attr({
                            "aria-label": options.ariaLabel ? options.ariaLabel : options.tooltip
                        })
                    }
                } else {
                    if (options.tooltipOn) {
                        imageButton.attr({
                            "title": options.tooltipOn
                        })
                    }

                    if (options.ariaLabelOn || options.tooltipOn) {
                        imageButton.attr({
                            "aria-label": options.ariaLabelOn ? options.ariaLabelOn : options.tooltipOn
                        })
                    }
                }

                function onBlur() {
                    var buttonState = ButtonState.Default,
                        toggleState = currentToggleState;

                    changeState(buttonState, toggleState);

                    imageButton.off("focusout");
                    imageButton.trigger("blur");
                }

                function onFocus() {
                    var buttonState = ButtonState.Hover,
                        toggleState = currentToggleState;

                    changeState(buttonState, toggleState);

                    imageButton.trigger("focus");
                    imageButton.on("focusout", onBlur);
                }

                function changeState(buttonState, toggleState) {
                    if (!toggleState) {
                        toggleState = currentToggleState;
                    }

                    if (!buttonState) {
                        buttonState = currentState;
                    }

                    var oldClassName = getClassName(currentToggleState, currentState),
                        newClassName = getClassName(toggleState, buttonState);

                    imageButton.removeClass(oldClassName);
                    currentState = buttonState;
                    currentToggleState = toggleState;
                    imageButton.addClass(newClassName);

                    imageButton.css({
                        "background-position": backgroundPositions[toggleState][buttonState],
                        "cursor": "pointer"
                    });

                    if (currentToggleState === ButtonToggleState.Off) {
                        if (options.tooltip) {
                            imageButton.attr({
                                "title": options.tooltip
                            })
                        }

                        if (options.ariaLabel || options.tooltip) {
                            imageButton.attr({
                                "aria-label": options.ariaLabel ? options.ariaLabel : options.tooltip
                            })
                        }
                    } else {
                        if (options.tooltipOn) {
                            imageButton.attr({
                                "title": options.tooltipOn
                            })
                        }

                        if (options.ariaLabelOn || options.tooltipOn) {
                            imageButton.attr({
                                "aria-label": options.ariaLabelOn ? options.ariaLabelOn : options.tooltipOn
                            })
                        }
                    }
                }

                imageButton.append(createTextContent());

                return {
                    getRootElement: function () {
                        return imageButton;
                    },
                    getHotspotElement: function () {
                        return imageButton;
                    },
                    getCurrentToggleState: function () {
                        return currentToggleState;
                    },
                    getVariableID: function () {
                        return variableID;
                    },
                    getVariableNamespace: function () {
                        return variableNamespace;
                    },
                    changeImage: function (width, height, filename) {

                        backgroundPositions[ButtonToggleState.On][ButtonState.Hover] = "0 " + (-height) + "px";
                        backgroundPositions[ButtonToggleState.On][ButtonState.Pressed] = "0 " + (-2 * height) + "px";
                        backgroundPositions[ButtonToggleState.Off][ButtonState.Default] = "-" + width + "px 0";
                        backgroundPositions[ButtonToggleState.Off][ButtonState.Hover] = "-" + width + "px " + (-height) + "px";
                        backgroundPositions[ButtonToggleState.Off][ButtonState.Pressed] = "-" + width + "px " + (-2 * height) + "px";

                        jq(imageButton).css({
                            "width": width + "px",
                            "height": height + "px",
                            "background-image": "url(\"" + filename + "\")",
                            "background-position": backgroundPositions[currentToggleState][currentState]
                        });
                    },
                    hasState: function (buttonState) {
                        return buttonState === currentState;
                    },
                    hasToggleState: function (buttonToggleState) {
                        return buttonToggleState === currentToggleState;
                    },
                    changeState: function (buttonState, toggleState) {
                        changeState(buttonState, toggleState);
                    },
                    focusButton: function () {
                        onFocus();
                    },
                    blurButton: function () {
                        onBlur();
                    }
                };
            }

            return {
                build: createButton
            };
        };

    /**
     * @constructor
     */
    return function (context, metadata) {
        var instance,
            shellElement,
            button,
            buttonInitialized = false,
            hasStageTriggerSupport = true,
            isInAuthoringMode = false,
            isStandardPlayer = context.getPlayerName() === "standard",
            pointerUpEventName,
            pointerDownEventName,
            pointerMoveEventName,
            pointerLeaveEventName,
            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 / 2;
                result.height = this.height / 3;
                deferred.resolve(result);
            };

            if (backgroundImage) {
                backgroundFileName = context.stage.getSharedPath() + backgroundImage.fileName;
            }
            else {
                backgroundFileName = context.getPath() + "toggle.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": "#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, button.getCurrentToggleState() );
            }
        }

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

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

        function isOnTarget( e ) {
            var elem = e.target,
                origEvent = e.originalEvent,
                changedTouch;

            if ( !origEvent ) {
                return true;
            } else {
                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, button.getCurrentToggleState() );

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

            toggleCurrentButtonToggleState();
            fireTrigger();
        }

        function onAccessibilityKeyPressed() {
            button.changeState(ButtonState.Default, button.getCurrentToggleState());
            toggleCurrentButtonToggleState();
            fireTrigger();
        }

        function toggleCurrentButtonToggleState(){
            if(button.hasToggleState(ButtonToggleState.On)){
                button.changeState( ButtonState.Default, ButtonToggleState.Off );
                context.stage.variable.set( button.variableID, ButtonToggleState.Off, button.variableNamespace );
            }else{
                button.changeState( ButtonState.Default, ButtonToggleState.On );
                context.stage.variable.set( button.variableID, ButtonToggleState.On, button.variableNamespace );
            }
        }

        function fireTrigger(){
            setTimeout(function(){
                if( button.getCurrentToggleState() ===  ButtonToggleState.On){
                    context.page.event.trigger(instance , "offToOn");
                } else {
                    context.page.event.trigger(instance, "onToOff");
                }}, 10);
        }

        function initPointerEventNames() {
            if (!pointerUpEventName) {
                var nodeName = getHotspotElementNodeName();

                pointerUpEventName = context.device.getUpEvents(nodeName);
                pointerDownEventName = context.device.getDownEvents(nodeName);
                pointerMoveEventName = context.device.getMoveEvents(nodeName);
                pointerLeaveEventName = context.device.getReleaseEvents(nodeName);
            }
        }

        function getHotspotElementNodeName() {
            return "document";
        }

        function cancelEvent(e){
            e.preventDefault();
            e.stopPropagation();
        }

        function bindEvents() {

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

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

            removeEvents();

            context.device.attachFirstSupportedEvent( button.getHotspotElement(), pointerDownEventName, onMouseDown );
            context.device.attachFirstSupportedEvent( button.getHotspotElement(), pointerMoveEventName, onMouseOver );
            context.device.attachFirstSupportedEvent( button.getHotspotElement(), pointerLeaveEventName, onMouseLeave );
            context.device.attachFirstSupportedEvent( button.getHotspotElement(), pointerUpEventName, onMouseUp );
        }

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

            initPointerEventNames();

            context.device.removeFirstSupportedEvent( button.getHotspotElement(), pointerDownEventName, onMouseDown );
            context.device.removeFirstSupportedEvent( button.getHotspotElement(), pointerMoveEventName, onMouseOver );
            context.device.removeFirstSupportedEvent( button.getHotspotElement(), pointerLeaveEventName, onMouseLeave );
            context.device.removeFirstSupportedEvent( button.getHotspotElement(), pointerUpEventName, onMouseUp );
        }

        function initializeButton(){

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

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

            button = createImageButton();
            button.variableNamespace = "graphicToggle" + button.variableID;
            button.variableID = metadata.parameters.asNumber("id", "1");

            shellElement.append( button.getRootElement() );

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

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

            if (isInAuthoringMode) {
                createAuthoringShield( shellElement );
            }

            button.changeState( ButtonState.Default, button.getCurrentToggleState() );
            refreshSavedState();
        }

        function refreshSavedState(){
            var savedSessionState = context.stage.variable.get( button.variableID, button.variableNamespace );

            if(savedSessionState){
                if(savedSessionState == ButtonToggleState.On){
                    button.changeState( ButtonState.Default, ButtonToggleState.On );
                }else{
                    button.changeState( ButtonState.Default, ButtonToggleState.Off )
                }
            }else{
                context.stage.variable.set( button.variableID, metadata.parameters.get("initial_state", ButtonToggleState.Off), button.variableNamespace );
                button.changeState( ButtonState.Default, metadata.parameters.get("initial_state", ButtonToggleState.Off) );
            };
        }

        function createImageButton(){

            var scParams = metadata.parameters,
                variableID = metadata.parameters.asNumber("id", "1"),
                imageButton = new ImageButtonBuilder({
                    width : metadata.getWidth(),
                    height : metadata.getHeight(),
                    tooltip: ((metadata.parameters.get("tooltip", false) || "").trim() === "") ? false : metadata.parameters.get("tooltip", false),
                    tooltipOn: ((metadata.parameters.get("tooltip-on", false) || "").trim() === "") ? false : metadata.parameters.get("tooltip-on", false),
                    ariaLabel: ((metadata.parameters.get("aria-label", false) || "").trim() === "") ? false : metadata.parameters.get("aria-label", false),
                    ariaLabelOn: ((metadata.parameters.get("aria-label-on", false) || "").trim() === "") ? false : metadata.parameters.get("aria-label-on", false),
                    color : scParams.get("color", "#000000"),
                    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"))
                    },
                    state : {
                        initial : scParams.get("initial_state", ButtonToggleState.Off),
                        saved : context.stage.variable.get( variableID, "graphicToggle" + variableID )
                    },
                    id : metadata.getId()
                }).build();

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

            return imageButton;
        }

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

                initializeButton();
            },

            onEnterPage: function () {
                refreshSavedState();
                bindEvents();
                if (!isStandardPlayer && !exludeFromTabControl) {
                    accessibilityTooltip.registerTabNavigation(metadata.getId(), accessibilityTabOrder);
                }
                fireTrigger();
                unlockNavigation();
            },

            onExitPage: function() {
                removeEvents();
            },

            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()) {
                    onAccessibilityKeyPressed();
                    context.stage.accessibility.turnAccessibilityModeOff();
                }
            },

            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()) {
                    onAccessibilityKeyPressed();
                    context.stage.accessibility.turnAccessibilityModeOff();
                }
            }
        };
    };
});
