var LEFT_ALIGN= 'left';
var RIGHT_ALIGN= 'right';
var TOP_ALIGN= 'top';
var BOTTOM_ALIGN= 'bottom';

var WxPopup= Class.create({
    initialize: function(wAnchorContainer, wAnchorSelector, wOptions) {
        this.anchorContainer= $(wAnchorContainer);
        this.anchorSelector= wAnchorSelector;

        this.options= Object.extend( {
            alignX: LEFT_ALIGN,
            alignY: TOP_ALIGN,
            offsetX: 20,
            offsetY: 5,
            autoOpen: true,
            autoClose: true,
            autoCloseDelay: 750, // ms
            ajaxUrl: null,
            ajaxParams: null,
            callbackFindPopup: this._callbackFindPopup,
            callbackInsertPopup: this._callbackInsertPopup,
            callbackUpdatePopup: null,
            callbackHidePopup: null,
            debug: false
        }, wOptions || {});

        if (this.options.alignX != LEFT_ALIGN && this.options.alignX != RIGHT_ALIGN) {
            this.options.alignX= LEFT_ALIGN;
        }
        if (this.options.alignY != TOP_ALIGN && this.options.alignY != BOTTOM_ALIGN) {
            this.options.alignY= TOP_ALIGN;
        }

        this.currentAnchor= null;
        this.currentPopup= null;

        this.clickAnchor= this._clickAnchor.bind(this);

     // this.mouseOverAnchor= this._mouseOverAnchor.bind(this);
     // this.mouseOverPopup= this._mouseOverPopup.bind(this);
     // this.mouseOut= this._mouseOut.bind(this);

        this.mouseEnterAnchor= this._mouseEnterAnchor.bind(this);
        this.mouseEnterPopup= this._mouseEnterPopup.bind(this);
        this.mouseLeave= this._mouseLeave.bind(this);

        this.hidePopup= this._hidePopup.bind(this);
        this.showPopup= this._showPopup.bind(this);

        this.documentLoaded= this._documentLoaded.bind(this);
        this.documentUnloaded= this._documentUnloaded.bind(this);

        this.ajaxComplete= this._ajaxComplete.bind(this);
    },

    initAnchor: function(anchor) {
        if (this.options.autoOpen) {
         // anchor.observe('mouseover', this.mouseOverAnchor);
         // anchor.observe('mouseout', this.mouseOut);
            anchor.observe('mouseenter', this.mouseEnterAnchor);
            anchor.observe('mouseleave', this.mouseLeave);
        } else {
            anchor.observe('click', this.clickAnchor);
        }
    },

    destroyAnchor: function(anchor) {
        if (this.options.autoOpen) {
         // anchor.stopObserving('mouseover', this.mouseOverAnchor);
         // anchor.stopObserving('mouseout', this.mouseOut);
            anchor.stopObserving('mouseenter', this.mouseEnterAnchor);
            anchor.stopObserving('mouseleave', this.mouseLeave);
        } else {
            anchor.stopObserving('click', this.clickAnchor);
        }
    },

    _documentLoaded: function() {
        var anchors= this.anchorContainer.select(this.anchorSelector);

        for (var i= 0, len= anchors.length; i < len; i++) {
            this.initAnchor(anchors[i]);
        }
    },

    _documentUnloaded: function() {
        var anchors= this.anchorContainer.select(this.anchorSelector);

        for (var i= 0, len= anchors.length; i < len; i++) {
            this.destroyAnchor(anchors[i]);
        }

        if (this.currentPopup) {
         // this.currentPopup.stopObserving('mouseover', this.mouseOverPopup);
         // this.currentPopup.stopObserving('mouseout', this.mouseOut);
            this.currentPopup.stopObserving('mouseenter', this.mouseEnterPopup);
            this.currentPopup.stopObserving('mouseleave', this.mouseLeave);
        }
    },

    _ajaxComplete: function(response) {
        var popup= response.request.options.popup;
        var popupContent= popup.down('.popup_content');

        if (response.status == 200) {
            popupContent.replace(response.responseText);
            popupContent= popup.down('.popup_content')

            if (this.options.callbackUpdatePopup) {
                this.options.callbackUpdatePopup(popupContent);
            }
        } else {
            popupContent.update('');

            if (popup == this.currentPopup) {
                this.hidePopup();
            }
        }
    },

    _callbackFindPopup: function(anchor) {
        return anchor.next('.popup');
    },

    _callbackInsertPopup: function(anchor, popup) {
        anchor.insert({after: popup});
    },

    loadPopupContent: function() {
        if (! this.options.ajaxUrl) {
            return ;
        }

        var parameters= {};

        if (this.options.ajaxParams) {
            var _params= this.options.ajaxParams(this.currentAnchor);

            if (_params) {
                parameters= _params;
            }
        }

        new Ajax.Request(this.options.ajaxUrl, {
            parameters: Object.toQueryString(parameters),
            onCreate: WxAjax.overrideMimeType,
            onComplete: this.ajaxComplete,
            popup: this.currentPopup
        } );
    },

    createPopup: function(anchor) {
        var popup= this.options.callbackFindPopup(anchor);
        var popupContent= null;

        if (Object.isUndefined(popup)) {
            popupContent= Builder.node('div', {className: 'popup_content'}, [
                Builder.node('span', {className: 'loading_2'}, 'Loading ...')
            ] );

            popup= Builder.node('div', {className: 'popup'}, [
                Builder.node('div', {className: 'popup_header'}),
                popupContent,
                Builder.node('div', {className: 'popup_footer'})
            ] ) ;

            popup.hide();

            this.options.callbackInsertPopup(anchor, popup);
        }

        this.currentPopup= popup;
        this.currentAnchor= anchor;

        // Will return true if this is a new popup, that needs to be loaded
        return popupContent != null;
    },

    /*
     * Popup Management
     */

    findAnchor: function(event) {
        var anchor= event.findElement();

        if (! anchor.match(this.anchorSelector)) {
            anchor= anchor.up(this.anchorSelector);
        }

        return anchor;
    },

    _clickAnchorImpl: function(anchor) {
        if (this.currentAnchor) {
            var _currentAnchor= this.currentAnchor;

            this.hidePopup();

            if (_currentAnchor == anchor) {
                return ;
            }
        }

        var loadPopupContent= this.createPopup(anchor);

        this.showPopup(loadPopupContent);
    },

    _clickAnchor: function(event) {
        this._clickAnchorImpl(this.findAnchor(event));
    },

    _mouseEnterAnchor: function(event) {
        if (this.options.debug) alert("_mouseEnterAnchor");

        var anchor= this.findAnchor(event);

        this.clearDelay();

        if (this.currentAnchor == anchor) {
            return ;
        }
        if (this.currentPopup) {
            this.hidePopup();
        }

        var loadPopupContent= this.createPopup(anchor);

        this.currentPopup.observe('mouseenter', this.mouseEnterPopup);
        this.currentPopup.observe('mouseleave', this.mouseLeave);

        this.showPopup(loadPopupContent);
    },

    _mouseEnterPopup: function(event) {
        this.clearDelay();
    },

    _mouseLeave: function() {
        if (this.options.autoClose) {
            this.clearDelay();
            this.delay= setTimeout(this.hidePopup, this.options.autoCloseDelay);
        }
    },
/*
    _mouseOverAnchor: function(event) {
        var anchor= this.findAnchor(event);

        this.clearDelay();

        if (this.currentAnchor == anchor) {
            return ;
        }
        if (this.currentPopup) {
            this.hidePopup();
        }

        var loadPopupContent= this.createPopup(anchor);

        this.currentPopup.observe('mouseover', this.mouseOverPopup);
        this.currentPopup.observe('mouseout', this.mouseOut);

        this.showPopup(loadPopupContent);
    },

    _mouseOverPopup: function(event) {
        this.clearDelay();
    },

    _mouseOut: function() {
        if (this.options.autoClose) {
            this.clearDelay();
            this.delay= setTimeout(this.hidePopup, this.options.autoCloseDelay);
        }
    },
*/
    clearDelay: function() {
        if (this.delay) {
            clearTimeout(this.delay);
        }

        this.delay= null;
    },

    /*
     * Show & Hide Popup
     */

    _showPopup: function(loadPopupContent) {
        if (this.currentPopup) {
            this.positionPopup();
            this.currentPopup.show();
            this.positionPopup();

            if (loadPopupContent) {
                this.loadPopupContent();
            }
        }
    },

    _hidePopup: function() {
        this.clearDelay();

        if (this.currentPopup) {
         // this.currentPopup.stopObserving('mouseover', this.mouseOverPopup);
         // this.currentPopup.stopObserving('mouseout', this.mouseOut);
            this.currentPopup.stopObserving('mouseenter', this.mouseEnterPopup);
            this.currentPopup.stopObserving('mouseleave', this.mouseLeave);
            this.currentPopup.hide();

            if (this.options.callbackHidePopup) {
                this.options.callbackHidePopup(this.currentAnchor, this.currentPopup);
            }
        }

        this.currentPopup= null;
        this.currentAnchor= null;
    },

    positionPopup: function() {
        if (! this.currentAnchor) {
            return ;
        }
        if (! this.currentPopup) {
            return ;
        }

        var top, left;

        if (this.options.alignY == TOP_ALIGN) {
            top= this.currentAnchor.getHeight() + this.options.offsetY;
        } else {
            top= this.currentAnchor.getHeight() + this.options.offsetY;
        }

        if (this.options.alignX == LEFT_ALIGN) {
            left= this.options.offsetX;
        } else {
            left= this.currentAnchor.getWidth() - this.currentPopup.getWidth() - this.options.offsetX;
        }

        this.currentPopup.clonePosition(this.currentAnchor, {
            setWidth: false,
            setHeight: false,
            offsetTop: top,
            offsetLeft: left
        } );
    },

    /*
     * Show & Hide Anchors
     */

    showAnchors: function(showPopup) {
        var anchors= this.anchorContainer.select(this.anchorSelector);

        for (var i= 0, len= anchors.length; i < len; i++) {
            anchors[i].show();
        }

        if (showPopup) {
            if (this.currentAnchor) {
                if (this.currentAnchor == anchors[0]) {
                    this.currentPopup.positionPopup();
                }
            } else {
                this._clickAnchorImpl(anchors[0]);
            }
        }
    },

    hideAnchors: function() {
        this._hidePopup();

        var anchors= this.anchorContainer.select(this.anchorSelector);

        for (var i= 0, len= anchors.length; i < len; i++) {
            anchors[i].hide();
        }
    }
} );
