define([
    "jquery"
    ], function(
        jq
    ){

    "use strict";

    /**
     * @constructor
     */

    return function( options, context, metadata ){

        // GLOBAL VARIABLES
        var dropdownField,
            dropdownFieldText,
            dropdownFieldHotspot,
            container,
            pageEvaluatedId,
            isChecked = false,
            BACKGROUND_POSITION_DROPDOWNFIELD = null,
            BACKGROUND_POSITION_ENTRIES = null,
            statePictureDropdownURL = options.dropdownField.autoform.backgroundImageDropdownField.fileNameURL,
            statePictureDropdownHeight = options.dropdownField.autoform.backgroundImageDropdownField.height / 7,
            statePictureDropdownWidth = options.dropdownField.autoform.backgroundImageDropdownField.width,
            statePictureEntriesURL = options.entries.autoform.backgroundImageEntries.fileNameURL,
            statePictureEntriesHeight = options.entries.autoform.backgroundImageEntries.height / 3,
            statePictureEntriesWidth = options.entries.autoform.backgroundImageEntries.width,
            userSelection = "";

        BACKGROUND_POSITION_DROPDOWNFIELD = {
            "DEFAULT": "0px 0px",
            "HOVER": "0px " + -statePictureDropdownHeight + "px",
            "PRESSED": "0px " + (-2 * statePictureDropdownHeight) + "px",
            "WRONG": "0px " + (-3 * statePictureDropdownHeight) + "px",
            "CORRECT": "0px " + (-4 * statePictureDropdownHeight) + "px",
            "SAMPLE_SOLUTION": "0px " + (-5 * statePictureDropdownHeight) + "px",
            "INACTIVE": "0px " + (-6 * statePictureDropdownHeight) + "px"
        };

        BACKGROUND_POSITION_ENTRIES = {
            "DEFAULT": "0px 0px",
            "HOVER": "0px " + -statePictureEntriesHeight + "px",
            "PRESSED": "0px " + (-2 * statePictureEntriesHeight) + "px"
        };

        // HELPER FUNCTIONS

        function getMenuPosition() {

            var dropdownFieldWidth = statePictureDropdownWidth,
                dropdownFieldHeight = statePictureDropdownHeight,
                containerHeight = statePictureEntriesHeight * options.entries.choices.length,
                containerWidth = statePictureEntriesWidth,
                menuPositions,
                locationOption = options.dropdownContainer.autoform.location;

            menuPositions = [
                //bottom
                {
                    "top": dropdownFieldHeight + "px",
                    "left": "0px"
                },
                //top
                {
                    "bottom": containerHeight + "px",
                    "left": "0px"
                },
                //rigth-top
                {
                    "bottom": containerHeight - dropdownFieldHeight + "px",
                    "left": dropdownFieldWidth + "px"
                },
                //right-bottom
                {
                    "top": "0px",
                    "left": dropdownFieldWidth + "px"
                },
                //left-top
                {
                    "bottom": containerHeight - dropdownFieldHeight + "px",
                    "right": containerWidth + "px"
                },
                //left-bottom
                {
                    "top": "0px",
                    "right": containerWidth + "px"
                }
            ];

            if (locationOption != 6) {
                return menuPositions[locationOption];
            } else {
                return {
                    "top": options.dropdownContainer.autoform.locationY + "px",
                    "left": options.dropdownContainer.autoform.locationX + "px"
                };
            }
        }

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

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

            removeEvents();

            if (!context.device.isMobile()) {
                context.device.attachFirstSupportedEvent(dropdownFieldHotspot, options.pointerEvents.pointerMove, onMouseMove);
                context.device.attachFirstSupportedEvent(dropdownFieldHotspot, options.pointerEvents.pointerLeave, onMouseOut);
            }

            context.device.attachFirstSupportedEvent(dropdownFieldHotspot, options.pointerEvents.pointerDown, onButtonPressed);
            context.device.attachFirstSupportedEvent(dropdownFieldHotspot, options.pointerEvents.pointerUp, onButtonReleased);
            context.device.attachFirstSupportedEvent(dropdownFieldHotspot, "touchmove", cancelEvent);

            var entries = container.getEntries();

            for (var i = 0; i < entries.length; i++) {

                if (!context.device.isMobile()) {
                    context.device.attachFirstSupportedEvent(entries[i].getHotspotElement(), options.pointerEvents.pointerMove, entries[i].onMouseMove);
                    context.device.attachFirstSupportedEvent(entries[i].getHotspotElement(), options.pointerEvents.pointerLeave, entries[i].onMouseOut);
                }

                context.device.attachFirstSupportedEvent(entries[i].getHotspotElement(), options.pointerEvents.pointerDown, entries[i].onButtonPressed);
                context.device.attachFirstSupportedEvent(entries[i].getHotspotElement(), options.pointerEvents.pointerUp, entries[i].onButtonReleased);
                context.device.attachFirstSupportedEvent(entries[i].getHotspotElement(), "touchmove", cancelEvent);
            }
        }

        function removeEvents() {
            if (!context.device.isMobile()) {
                context.device.removeFirstSupportedEvent(dropdownFieldHotspot, options.pointerEvents.pointerMove, onMouseMove);
                context.device.removeFirstSupportedEvent(dropdownFieldHotspot, options.pointerEvents.pointerLeave, onMouseOut);
            }

            context.device.removeFirstSupportedEvent(dropdownFieldHotspot, options.pointerEvents.pointerDown, onButtonPressed);
            context.device.removeFirstSupportedEvent(dropdownFieldHotspot, options.pointerEvents.pointerUp, onButtonReleased);
            context.device.removeFirstSupportedEvent(dropdownFieldHotspot, "touchmove", cancelEvent);

            var entries = container.getEntries();

            for (var i = 0; i < entries.length; i++) {

                if (!context.device.isMobile()) {
                    context.device.removeFirstSupportedEvent(entries[i].getHotspotElement(), options.pointerEvents.pointerMove, entries[i].onMouseMove);
                    context.device.removeFirstSupportedEvent(entries[i].getHotspotElement(), options.pointerEvents.pointerLeave, entries[i].onMouseOut);
                }

                context.device.removeFirstSupportedEvent(entries[i].getHotspotElement(), options.pointerEvents.pointerDown, entries[i].onButtonPressed);
                context.device.removeFirstSupportedEvent(entries[i].getHotspotElement(), options.pointerEvents.pointerUp, entries[i].onButtonReleased);
                context.device.removeFirstSupportedEvent(entries[i].getHotspotElement(), "touchmove", cancelEvent);
            }
        }

        function onMouseMove() {
            dropdownField.css({
                "background-position": BACKGROUND_POSITION_DROPDOWNFIELD.HOVER
            })
            dropdownFieldText.css({
                "color": options.dropdownField.text.mouseoverColor
            })
        }

        function onMouseOut() {
            dropdownField.css({
                "background-position": BACKGROUND_POSITION_DROPDOWNFIELD.DEFAULT
            })
            dropdownFieldText.css({
                "color": options.dropdownField.text.color
            })
            unlockNavigation();
        }

        function onButtonPressed(e) {
            cancelEvent(e);
            lockNavigation();
            dropdownField.css({
                "background-position": BACKGROUND_POSITION_DROPDOWNFIELD.PRESSED
            })
            dropdownFieldText.css({
                "color": options.dropdownField.text.mousedownColor
            })
        }

        function onButtonReleased(e) {
            cancelEvent(e);
            unlockNavigation();

            dropdownField.css({
                "background-position": BACKGROUND_POSITION_DROPDOWNFIELD.DEFAULT
            })
            dropdownFieldText.css({
                "color": options.dropdownField.text.color
            })

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

            if (container.isOpen()) {
                container.close();
            } else {
                container.open();
            }
        }

        // CREATER FUNCTIONS
        function createDropdownField() {
            dropdownField = jq(document.createElement("div"))
                .attr({
                    "id": "dropdownField" + options.instanceID
                })
                .css({
                    "background-image": "url(\"" + statePictureDropdownURL + "\")",
                    "background-position": BACKGROUND_POSITION_DROPDOWNFIELD.DEFAULT,
                    "background-repeat": "no-repeat",
                    "width": statePictureDropdownWidth + "px",
                    "height": statePictureDropdownHeight + "px"
                })

            dropdownFieldText = jq(document.createElement("div"))
                .attr({
                    "id": "dropdownFieldText" + options.instanceID
                })
                .css({
                    "position": "absolute",
                    "font-family": options.dropdownField.text.fontFamily,
                    "color": options.dropdownField.text.color,
                    "padding-left": options.dropdownField.text.paddingLeft + "px",
                    "padding-right": options.dropdownField.text.paddingRight + "px",
                    "padding-top": options.dropdownField.text.paddingTop + "px",
                    "padding-bottom": options.dropdownField.text.paddingBottom + "px",
                    "font-size": options.dropdownField.text.fontSize + "px",
                    "width": statePictureDropdownWidth - (options.dropdownField.text.paddingLeft + options.dropdownField.text.paddingRight) + "px",
                    "height": statePictureDropdownHeight - (options.dropdownField.text.paddingTop + options.dropdownField.text.paddingBottom) + "px",
                    "text-align": options.dropdownField.text.orientation
                })

            if (options.isInAuthoringMode) {
                if ((options.settings.sampleSolution||"").trim().length > 0) {
                    dropdownFieldText.text(options.settings.sampleSolution);
                } else {
                    if ((options.settings.defaultText||"").trim().length > 0) {
                        dropdownFieldText.text(options.settings.defaultText);
                    }
                }
            } else {
                if ((options.settings.defaultText||"").length > 0) {
                    dropdownFieldText.text(options.settings.defaultText);
                }
            }

            dropdownFieldHotspot = jq(document.createElement("div"))
                .attr({
                    "id": "dropdownFieldHotspot" + options.instanceID
                })
                .css({
                    "cursor": "pointer",
                    "position": "absolute",
                    "width": statePictureDropdownWidth + "px",
                    "height": statePictureDropdownHeight + "px"
                })

            container = createContainer();

            createContainerContent();

            dropdownField.append(dropdownFieldText);
            dropdownField.append(dropdownFieldHotspot);
            dropdownField.append(container.getElement());
        }

        function createContainer() {
            var isOpen = false,
                entries = new Array,
                containerElement = jq(document.createElement("div"))
                    .attr({
                        "id": "dropdownContainer" + options.instanceID
                    })
                    .css({
                        "position": "relative",
                        "width": statePictureEntriesWidth + "px",
                    })
                    .css(getMenuPosition())
                    .hide();

            return {
                getElement: function () {
                    return containerElement;
                },
                open: function () {
                    if (!isOpen) {
                        containerElement.show();
                        isOpen = true;
                    }
                },
                close: function () {
                    if (isOpen) {
                        containerElement.hide();
                        isOpen = false;
                    }
                },
                isOpen: function () {
                    return isOpen;
                },
                getEntries: function () {
                    return entries;
                },
                addEntry: function (entry) {
                    entries.push(entry);
                    containerElement.append(entry.getElement());
                },
                removeEntry: function (entry) {
                    if (entries.indexOf(entry) !== -1) {
                        entries.splice(entries.indexOf(entry), 1);
                    }
                }
            }
        }

        function createEntry(value, isCorrect, id) {
            var isCorrect = isCorrect,
                value = value,
                entry = jq(document.createElement("div"))
                    .attr({
                        "id": id
                    })
                    .css({
                        "position": "relative",
                        "background-image": "url(\"" + statePictureEntriesURL + "\")",
                        "background-position": BACKGROUND_POSITION_ENTRIES.DEFAULT,
                        "background-repeat": "no-repeat",
                        "width": statePictureEntriesWidth + "px",
                        "height": statePictureEntriesHeight + "px"
                    }),
                text = jq(document.createElement("div"))
                    .attr({
                        "id": id
                    })
                    .css({
                        "position": "absolute",
                        "font-family": options.entries.text.fontFamily,
                        "color": options.entries.text.color,
                        "padding-left": options.entries.text.paddingLeft + "px",
                        "padding-right": options.entries.text.paddingRight + "px",
                        "padding-top": options.entries.text.paddingTop + "px",
                        "padding-bottom": options.entries.text.paddingBottom + "px",
                        "font-size": options.entries.text.fontSize + "px",
                        "width": statePictureEntriesWidth - (options.entries.text.paddingLeft + options.entries.text.paddingRight) + "px",
                        "height": statePictureEntriesHeight - (options.entries.text.paddingTop + options.entries.text.paddingBottom) + "px",
                        "text-align": options.entries.text.orientation
                    })
                    .text(value),
                hotspot = jq(document.createElement("div"))
                    .attr({
                        "id": id
                    })
                    .css({
                        "cursor": "pointer",
                        "position": "absolute",
                        "width": "100%",
                        "height": "100%"
                    });

            entry.append(text);
            entry.append(hotspot);

            return {
                getElement: function () {
                    return entry;
                },
                getHotspotElement: function () {
                    return hotspot;
                },
                isCorrect: function () {
                    return isCorrect;
                },
                getValue: function () {
                    return value;
                },
                onMouseMove: function () {
                    entry.css({
                        "background-position": BACKGROUND_POSITION_ENTRIES.HOVER
                    })
                    text.css({
                        "color": options.entries.text.mouseoverColor
                    })
                },
                onMouseOut: function () {
                    entry.css({
                        "background-position": BACKGROUND_POSITION_ENTRIES.DEFAULT
                    })
                    text.css({
                        "color": options.entries.text.color
                    })
                    unlockNavigation();
                },
                onButtonPressed: function (e) {
                    cancelEvent(e);
                    lockNavigation();
                    entry.css({
                        "background-position": BACKGROUND_POSITION_ENTRIES.PRESSED
                    })
                    text.css({
                        "color": options.entries.text.mousedownColor
                    })
                },
                onButtonReleased: function (e) {
                    cancelEvent(e);
                    unlockNavigation();

                    entry.css({
                        "background-position": BACKGROUND_POSITION_ENTRIES.DEFAULT
                    })
                    text.css({
                        "color": options.entries.text.color
                    })

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

                    container.close();
                    dropdownFieldText.text(value);
                    saveUserSelection(value);
                    setChecked(isCorrect);
                }
            }
        }

        function saveUserSelection(val) {
            userSelection = val;
            context.stage.variable.set(options.elementVariableName, userSelection, options.elementVariableNameSpace);
        }

        function getUserSelection() {
            userSelection = context.stage.variable.get(options.elementVariableName, options.elementVariableNameSpace);
        }

        function createContainerContent() {
            for (var i = 0; i < options.entries.choices.length; i++) {
                if (options.entries.choices[i][0]) {
                    container.addEntry(createEntry(options.entries.choices[i][0], options.entries.choices[i][1], "entry" + i + options.instanceID));
                }
            }
        }

        function isEvaluated() {

            if (options.isInPreviewMode) {
                return false;
            }

            if (options.isStandardPlayer) {
                return context.stage.variable.get(pageEvaluatedId, options.elementVariableNameSpace);
            }

            return context.page.quiz.hasQuestion() && context.page.quiz.getQuestion().isFinalized();
        }

        function reset() {

            if (options.isStandardPlayer) {
                context.stage.variable.set(pageEvaluatedId, false, options.elementVariableNameSpace);
            }

            setChecked(false);
            saveUserSelection("");
            dropdownFieldText.text("");
            setInitialDesign();
            container.close();
        }

        function setChecked(checked) {
            isChecked = checked;
            context.page.quiz.setSelected(options.instance, isChecked);
        }

        function setInitialDesign() {
            dropdownField.css({
                    "background-position": BACKGROUND_POSITION_DROPDOWNFIELD.DEFAULT
                })

            dropdownFieldText.css({
                    "color": options.dropdownField.text.color
                })
        }

        function switchToUserSolution() {
            removeEvents();

            if (options.isStandardPlayer) {
                context.stage.variable.set(pageEvaluatedId, true, options.elementVariableNameSpace);
            }

            unlockNavigation();

            dropdownFieldText.text(userSelection);

            if (isChecked) {
                dropdownField.css({
                    "background-position": BACKGROUND_POSITION_DROPDOWNFIELD.CORRECT
                })
                dropdownFieldText.css({
                    "color": options.dropdownField.text.correctColor
                })
            } else {
                dropdownField.css({
                    "background-position": BACKGROUND_POSITION_DROPDOWNFIELD.WRONG
                })
                dropdownFieldText.css({
                    "color": options.dropdownField.text.wrongColor
                })
            }

            container.close();
            dropdownFieldHotspot.css({
                "cursor": "default"
            })
        }

        function switchToBestPracticeSolution() {
            removeEvents();
            unlockNavigation();

            dropdownField.css({
                "background-position": BACKGROUND_POSITION_DROPDOWNFIELD.SAMPLE_SOLUTION
            })
            dropdownFieldText.css({
                "color": options.dropdownField.text.sampleSolutionColor
            })

            if (!options.settings.sampleSolution) {
                dropdownFieldText.text("");
            } else {
                dropdownFieldText.text(options.settings.sampleSolution);
            }

            container.close();
            dropdownFieldHotspot.css({
                "cursor": "default"
            })
        }

        return {
            build : function(){
                createDropdownField();
                context.page.quiz.add(options.instance, options.settings.groupId, true);

                return {
                    getElement: function () {
                        return dropdownField.get(0);
                    },
                    onEnterPage: function () {
                        pageEvaluatedId = metadata.page.getId() + "_evaluated";

                        if (options.isInAuthoringMode) {
                            return;
                        }

                        if (!options.isStandardPlayer && isEvaluated()) {
                            switchToUserSolution();
                            return;
                        }

                        bindEvents();
                    },
                    onExitPage: function () {
                        removeEvents();
                        if (options.isStandardPlayer) {
                            reset();
                        }
                    },
                    onUserSolution: function () {
                        switchToUserSolution();
                    },
                    onBestPracticeSolution: function () {
                        switchToBestPracticeSolution();
                    }
                };
            }
        };
    }
});
