/**
 * Dialog for aligning and positioning Navigationelements in Quick- and AdvancedDesign
 * 
 * The `de_epages.designUiAlignmentdialog` method creates a dialog for aligning and positioning Navigationelements in Quick- and AdvancedDesign.
 * 
 * @class jQuery.ui.designUiAlignmentdialog
 * @extends jQuery.widget
 * 
 * @uses jQuery.ui.widget
 * @uses ep.ui.simpledialog
 * @uses de_epages
 * @since 6.16.0
 */

/**
 * @cfg {Object} dojoWidget Corresponding dojo widget of type Navigationelement
 */

/**
 * @cfg {Function} getNavBarContainers Function that returns an array of Navigationbars. Reference to findNavBarContainer function defined in DE_EPAGES/Design/Templates/MBO/StyleWizard/MBO-StyleWizard.Script-Initialize.html
 */

/**
 * @cfg {Object} top$ Reference to jQuery in the top document
 */

/**
 * @cfg {Object} topDocument Reference to the top document
 */

/**
 * See `jQuery.ui.designUiAlignmentdialog` for details.
 * 
 * @param {Object} options A map of additional options pass to the method.
 * @param {Object} dojoWidget Corresponding dojo widget of type Navigationelement
 * @param {Function} getNavBarContainers Function that returns an array of Navigationbars. Reference to findNavBarContainer function defined in DE_EPAGES/Design/Templates/MBO/StyleWizard/MBO-StyleWizard.Script-Initialize.html
 * @param {Object} top$ Reference to jQuery in the top document
 * @param {Object} topDocument Reference to the top document
 * 
 * @method designUiAlignmentdialog
 * @member jQuery
 * 
 * @since 6.16.0
 */

/*
 * @Copyright   Copyright 2006-2013, epages GmbH, All Rights Reserved.
 *
 * @module      de_epages.design.ui.alignmentdialog
 *
 * @revision    $$
 */
/*jslint nomen: true, browser: true*/
/*global define*/
define('de_epages/design/ui/alignmentdialog', [
    'jquery/ui/widget',
    'ep/ui/simpledialog',
    'de_epages',
    '$dict!./alignmentdialog',
    '$tmpl!./alignmentdialog'
], function ($, ep, de_epages, dictAlignmentdialog, template) {
    'use strict';
    // The actual widget.
    $.widget('ui.designUiAlignmentdialog', {
        /*
        options:
          dojoWidget - Corresponding *dojo* widget of type *Navigationelement*
          see javascript/epages/cartridges/de_epages/design/widget/Navigationelement.js

          getNavBarContainers - Reference to *findNavBarContainer* function defined in
          DE_EPAGES/Design/Templates/MBO/StyleWizard/MBO-StyleWizard.Script-Initialize.html

          top$ - Reference to *top.jQuery*

          topDocument - Reference to *top.document*
        }
        */

        // Helper to be able to chain *_on()* calls.
        _on: function () {
            this._superApply(arguments);
            return this;
        },

        // Let's create some widgets!
        _create: function () {
            var o = this.options;

            // Render template, soon to be *content* of our *simpledialog*.
            this.content = template(o)
                .dictParse(dictAlignmentdialog, true).find('li i').dictParseAttr(dictAlignmentdialog, 'title').end();

            // Register ui elements: *reset* (button), *left*, *right*, *up*, *down* (arrows) and *leftAlign*, *rightAlign* (icons).
            $.extend(this, $.tmplItem(this.content, 'elements'));

            // Bind *click*-event handlers to ui elements.
            this
                ._on(this.left, {
                click: this._setPosition
            })
                ._on(this.right, {
                click: this._setPosition
            })
                ._on(this.up, {
                click: this._setPosition
            })
                ._on(this.down, {
                click: this._setPosition
            })
                ._on(this.reset, {
                click: this._resetPosition
            })
                ._on(this.leftAlign, {
                click: this._setLeftAlign
            })
                ._on(this.rightAlign, {
                click: this._setRightAlign
            })
                ._on({
                open: function (e) {
                    this
                        ._on($('body'), {
                        keydown: this._shortcuts
                    })
                        ._on($(this.options.top$('body')), {
                        keydown: this._shortcuts
                    });
                    // Indicate the currently selected element.
                    $(this.options.dojoWidget.contentNode)
                        .children('[id^="Element"]')
                        .children()
                        .not('script')
                        .first()
                        .addClass('de_epages-designUiAlignmentdialog-selectedItem');
                    // Check whether to show/hide the left/right *alignment* part of this dialog.
                    this._toggleAlign();
                },
                close: function (e) {
                    // Remove event handlers from outside the widget.
                    this._off($('body'), 'keydown');
                    this._off($(this.options.top$('body')), 'keydown');
                    $(this.options.dojoWidget.contentNode)
                        .children('[id^="Element"]')
                        .children()
                        .not('script')
                        .first()
                        .removeClass('de_epages-designUiAlignmentdialog-selectedItem');
                }
            });

            // Init the actual *simpledialog*.
            this.element.uiSimpledialog({
                zIndex: 10000, // To get over the *.EffectLayer* and *.SelectionGuide*.
                content: this.content,
                autoOpen: true
            });

            // Register callback to close dialog, when some navbar is clicked.
            // Sadly (Advanced-/QuickDesign) *dojo* stops the click events from bubbling to the root html
            // so we cannot rely on the usual *simpledialog* auto close functionality.
            this._on($(o.getNavBarContainers(document)), {
                click: function (e) {
                    this.element.data('uiUiSimpledialog')
                        ._close(e);
                }
            });
        },

        // *epages.event* adapter for firing *change* events *dojo widgets* may listen to (i.e. *dojo.connect*).
        _fireChange: function (domNode, onTop) {
            var event;
            if (onTop) {
                event = this.options.topDocument.createEvent('HTMLEvents');
            } else {
                event = document.createEvent('HTMLEvents');
            }
            event.initEvent('change', true, true);
            domNode.dispatchEvent(event);
            // *epages.event* works with "real" *HTMLEvents*.
        },

        _toggleAlign: function () {
            switch (this.options.dojoWidget.orientation) {
            case 'UpDown':
                this.align.hide();
                this.positioning.addClass('positioning-single-column');
                this.reset.addClass('positioning-reset');
                this.content
                    .removeClass('ep-contentBox-listCol2')
                    .addClass('ep-contentBox-listCol1');
                break;
            case 'LeftRight':
                this.content
                    .removeClass('ep-contentBox-listCol1')
                    .addClass('ep-contentBox-listCol2');
                this.align.show();
                this.positioning.removeClass('positioning-single-column');
                this.reset.removeClass('positioning-reset');
                break;
            }
        },

        // Set *left* or *top* value of *options.dojoWidget*.
        _setPosition: function (e) {
            var currentTarget = e.currentTarget,
                $positionNode,
                newPositionValue;
            if (currentTarget === this.left.get(0) || currentTarget === this.right.get(0)) {
                $positionNode = $(this.options.dojoWidget.leftNode);
            } else {
                $positionNode = $(this.options.dojoWidget.topNode);
            }
            // Init numeric value. (Could e.g. be "auto" or "").
            if (!$.isNumeric($positionNode.val())) {
                $positionNode.val(0);
            }
            // Set new (numeric) position (i.e. left or top) value of *dojoWidget*.
            newPositionValue = parseInt($positionNode.val(), 10);
            if (e.currentTarget === this.left.get(0) || currentTarget === this.up.get(0)) {
                newPositionValue = newPositionValue - 1;
            } else {
                newPositionValue = newPositionValue + 1;
            }
            $positionNode.val(newPositionValue);
            // Tell the *dojo* event listeners about what just happended.
            this._fireChange($positionNode.get(0));
        },

        // Reset *left* or *top* value of *options.dojoWidget* to "auto".
        _resetPosition: function (e) {
            var $leftNode = $(this.options.dojoWidget.leftNode),
                $topNode = $(this.options.dojoWidget.topNode);
            if ($leftNode.val() !== 'auto') {
                this._fireChange($leftNode.val('auto')
                    .get(0));
            }
            if ($topNode.val() !== 'auto') {
                this._fireChange($topNode.val('auto')
                    .get(0));
            }
        },

        // Set *alignment* of *dojoWidget* and set *Align* value of surrounding navbar to *custom*
        _setLeftAlign: function (e) {
            var myDojoWidget = this.options.dojoWidget,
                alignNode = myDojoWidget.alignmentNode,
                navBarName = $(myDojoWidget.navbarNode())
                    .data('navbarAlias'),
                $alignSelect = this.options.top$('select[name$="' + navBarName + 'Align"]'),
                oldAlignNavbar,
                navElements,
                loopLength,
                i,
                widget;
            if (!$alignSelect.length) {
                return;
            }
            oldAlignNavbar = $alignSelect.val();
            if (oldAlignNavbar === 'left') {
                return;
            }
            if (oldAlignNavbar !== 'custom') {
                $alignSelect.val('custom');
                this._fireChange($alignSelect.get(0), true);
                // Move the *left* i.e. standard siblings to the new *right* part of the navbar.
                navElements = [].concat(myDojoWidget.siblingWidgets());
                loopLength = navElements.length;
                for (i = 0; i < loopLength; i = i + 1) {
                    widget = navElements[i];
                    if (myDojoWidget !== widget) {
                        widget.alignmentNode.value = "Right";
                        this._fireChange(widget.alignmentNode);
                    }
                }
            }
            if (alignNode.value !== 'Left') {
                alignNode.value = 'Left';
                this._fireChange(alignNode);
            }
        },

        // Set *alignment* of *dojoWidget* and set *Align* value of surrounding navbar to *custom*.
        _setRightAlign: function (e) {
            var alignNode = this.options.dojoWidget.alignmentNode,
                $alignSelect,
                oldAlignNavbar;
            if (alignNode.value !== 'Right') {
                // Set navbar's alignment to *custom*, if necessary.
                $alignSelect = this.options.top$('select[name$="' + $(this.options.dojoWidget.navbarNode())
                    .data('navbarAlias') + 'Align"]');
                if (!$alignSelect.length) {
                    return;
                }
                oldAlignNavbar = $alignSelect.val();
                if (oldAlignNavbar === 'right') {
                    return;
                }
                if (oldAlignNavbar !== 'custom') {
                    $alignSelect.val('custom');
                    this._fireChange($alignSelect.get(0), true);
                }
                alignNode.value = 'Right';
                this._fireChange(alignNode);
            }
        },

        // For the shortcut haxx0rs.
        _shortcuts: function (e) {
            switch (e.which) {
            case $.ui.keyCode.LEFT:
                this.left.triggerHandler('click');
                e.preventDefault();
                break;
            case $.ui.keyCode.UP:
                this.up.triggerHandler('click');
                e.preventDefault();
                break;
            case $.ui.keyCode.RIGHT:
                this.right.triggerHandler('click');
                e.preventDefault();
                break;
            case $.ui.keyCode.DOWN:
                this.down.triggerHandler('click');
                e.preventDefault();
                break;
            }
        },

        // Destroy widget and its components.
        destroy: function () {
            var self = this;
            self.element.uiSimpledialog('destroy');
            return self._superApply(arguments);
        }
    });

    return de_epages;

});