define([
    "jquery",
    "./button.state",
    "./button.toggle.state"
],
function(
    jq,
    ButtonState,
    ButtonToggleState
){

    /**
     * @constructor
     */
    return 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.On ][ ButtonState.Inactive ] = "0 " + (-3 * 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";
        backgroundPositions[ ButtonToggleState.Off ][ ButtonState.Inactive ] = "-" + options.width + "px " + (-3 * 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");
                }
            }

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

        function createButton() {

            var currentState = ButtonState.Default,
                currentToggleState = ButtonToggleState.On,
                textContent = createTextContent(),
                imageButton = jq(document.createElement("button"))
                    .attr({
                        "title" : options.caption,
                        "class" : currentState,
                        "id": options.id,
                        "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"
                    })
                    .addClass("sc-navigation")
                    .addClass("ttsButtonSoundOnOff")
                    .on("touchmove", function(e) {
                        e.preventDefault ? e.preventDefault() : true;
                    });

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

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

            if( textContent ) {
                imageButton.append(textContent);
            }

            function changeState(buttonState, toggleState) {

                if (!toggleState) {
                    toggleState = currentToggleState;
                }

                if (!buttonState) {
                    buttonState = currentState;
                }

                var enabled = buttonState !== ButtonState.Inactive,
                    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": enabled ? "pointer" : "default"
                });
                if (currentToggleState === ButtonToggleState.On) {
                    if (options.ariaLabel || options.caption) {
                        imageButton.attr({
                            "title": options.caption,
                            "aria-label": options.ariaLabel ? options.ariaLabel : options.caption
                        })
                    }
                } else {
                    if (options.ariaLabel || options.caption) {
                        imageButton.attr({
                            "title": options.captionOff,
                            "aria-label": options.ariaLabelOff ? options.ariaLabelOff : options.captionOff
                        })
                    }
                }
            }

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

            return {
                getHotspotElement : function(){
                    return imageButton.get(0);
                },
                changeImage : function( width, height, filename ){

                    backgroundPositions[ ButtonToggleState.On ][ ButtonState.Hover ] = "0 " + (-height) + "px";
                    backgroundPositions[ ButtonToggleState.On ][ ButtonState.Pressed ] = "0 " + (-2 * height) + "px";
                    backgroundPositions[ ButtonToggleState.On ][ ButtonState.Inactive ] = "0 " + (-3 * 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";
                    backgroundPositions[ ButtonToggleState.Off ][ ButtonState.Inactive ] = "-" + width + "px " + (-3 * 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();
                }
            };
        }

        function getClassName( toggleState, buttonState ){
            return toggleState + "_" + buttonState;
        }

        return {
            build : createButton
        };
    };
});
