(function(requirejs, require, define) {
    define([], function() {
        return State;

        function State(problemId) {
            var state;

            state = {
                'config': null,

                'baseImageEl': null,
                'baseImageLoaded': false,

                'containerEl': null,

                'sliderEl': null,

                'problemId': problemId,

                'draggables': [],
                'numDraggablesInSlider': 0,
                'currentMovingDraggable': null,

                'targets': [],

                'updateArrowOpacity': null,

                'uniqueId': 0,
                'salt': makeSalt(),

                'getUniqueId': getUniqueId
            };

            $(document).mousemove(function(event) {
                documentMouseMove(state, event);
            });

            return state;
        }

        function getUniqueId() {
            this.uniqueId += 1;

            return this.salt + '_' + this.uniqueId.toFixed(0);
        }

        function makeSalt() {
            var text, possible, i;

            text = '';
            possible = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';

            for (i = 0; i < 5; i += 1) {
                text += possible.charAt(Math.floor(Math.random() * possible.length));
            }

            return text;
        }

        function documentMouseMove(state, event) {
            if (state.currentMovingDraggable !== null) {
                state.currentMovingDraggable.iconEl.css(
                'left',
                event.pageX -
                    state.baseImageEl.offset().left -
                    state.currentMovingDraggable.iconWidth * 0.5
                    - state.currentMovingDraggable.iconElLeftOffset
            );
                state.currentMovingDraggable.iconEl.css(
                'top',
                event.pageY -
                    state.baseImageEl.offset().top -
                    state.currentMovingDraggable.iconHeight * 0.5
            );

                if (state.currentMovingDraggable.labelEl !== null) {
                    state.currentMovingDraggable.labelEl.css(
                    'left',
                    event.pageX -
                        state.baseImageEl.offset().left -
                        state.currentMovingDraggable.labelWidth * 0.5
                        - 9 // Account for padding, border.
                );
                    state.currentMovingDraggable.labelEl.css(
                    'top',
                    event.pageY -
                        state.baseImageEl.offset().top +
                        state.currentMovingDraggable.iconHeight * 0.5 +
                        5
                );
                }
            }
        }
    }); // End-of: define([], function () {
}(RequireJS.requirejs, RequireJS.require, RequireJS.define)); // End-of: (function (requirejs, require, define) {
