/*
This file is part of Ext JS 4.2

Copyright (c) 2011-2013 Sencha Inc

Contact:  http://www.sencha.com/contact

Commercial Usage
Licensees holding valid commercial licenses may use this file in accordance with the Commercial
Software License Agreement provided with the Software or, alternatively, in accordance with the
terms contained in a written agreement between you and Sencha.

If you are unsure which license is appropriate for your use, please contact the sales department
at http://www.sencha.com/contact.

Build date: 2013-09-18 17:18:59 (940c324ac822b840618a3a8b2b4b873f83a1a9b1)
*/
/**
 * This override adds RTL positioning methods to Ext.dom.Element.
 */
Ext.define('Ext.rtl.dom.Element_position', {
    override: 'Ext.dom.Element',

    _positionTopRight: ['position', 'top', 'right'],

    statics: {
        getXY: function(el) {
            var doc = document,
                bd = doc.body,
                docEl = doc.documentElement,
                leftBorder = 0,
                topBorder = 0,
                ret = [0,0],
                x, box, scroll;

            el = Ext.getDom(el);

            if(el !== doc && el !== bd){
                // IE has the potential to throw when getBoundingClientRect
                // is called on an element not attached to dom
                if (Ext.isIE) {
                    try {
                        box = el.getBoundingClientRect();
                        // In some versions of IE, the documentElement (HTML element)
                        // will have a 2px border that gets included, so subtract it off
                        topBorder = docEl.clientTop || bd.clientTop;
                        leftBorder = docEl.clientLeft || bd.clientLeft;
                    } catch (ex) {
                        box = { left: 0, top: 0 };
                    }
                } else {
                    box = el.getBoundingClientRect();
                }

                doc = Ext.fly(document, '_getXY');
                if (Ext.rootHierarchyState.rtl) {
                    scroll = doc.rtlGetScroll();
                    x = Ext.Element.getViewportWidth() - box.right + scroll.left;
                } else {
                    scroll = doc.getScroll();
                    x = box.left + scroll.left;
                }
                ret = [
                    Math.round(x - leftBorder),
                    Math.round(box.top + scroll.top - topBorder)
                ];
            }
            return ret;
        },

        setXY: function(el, xy) {
            (el = Ext.fly(el, '_setXY')).position();

            var pts = el.translatePoints(xy),
                style = el.dom.style,
                pos;

            style[Ext.rootHierarchyState.rtl ? 'left' : 'right'] = 'auto';
            for (pos in pts) {
                if (!isNaN(pts[pos])) {
                    style[pos] = pts[pos] + 'px';
                }
            }
        }
    },

    getPositioning: function(autoPx){
        var xStyle = Ext.rootHierarchyState.rtl ? 'right' : 'left',
            styles = this.getStyle([xStyle, 'top', 'position', 'z-index']),
            dom = this.dom;

        if(autoPx) {
            if(styles[xStyle] === 'auto') {
                styles[xStyle] = (xStyle === 'left') ? (dom.offsetLeft + 'px') :
                    (dom.offsetParent.offsetWidth - dom.offsetLeft - dom.offsetWidth);
            }
            if(styles.top === 'auto') {
                styles.top = dom.offsetTop + 'px';
            }
        }

        return styles;
    },

    rtlGetLocalX: function() {
        var me = this,
            offsetParent = me.dom.offsetParent,
            x = me.getStyle('right');

        if (!x || x === 'auto') {
            x = 0;
        } else if (me.pxRe.test(x)) {
            x = parseFloat(x);
        } else {
            x = me.getX();
            if (offsetParent) {
                x -= Ext.fly(offsetParent, '_rtlGetLocalX').getX();
            }
        }

        return x;
    },

    rtlGetLocalXY: function() {
        var me = this,
            offsetParent = me.dom.offsetParent,
            style = me.getStyle(['right', 'top']),
            x = style.right,
            y = style.top;

        if (!x || x === 'auto') {
            x = 0;
        } else if (me.pxRe.test(x)) {
            x = parseFloat(x);
        } else {
            x = me.getX();
            if (offsetParent) {
                x -= Ext.fly(offsetParent, '_rtlGetLocalXY').getX();
            }
        }

        if (!y || y === 'auto') {
            y = 0;
        } else if (me.pxRe.test(y)) {
            y = parseFloat(y);
        } else {
            y = me.getY();
            if (offsetParent) {
                y -= Ext.Element.getY(offsetParent);
            }
        }

        return [x, y];
    },

    rtlSetLocalX: function(x) {
        var style = this.dom.style;

        // clear left style just in case it was previously set by setXY/setLocalXY
        style.left = 'auto';
        style.right = (x === null) ? 'auto' : x + 'px';
    },

    rtlSetLocalXY: function(x, y) {
        var style = this.dom.style;

        // clear left style just in case it was previously set by setXY/setLocalXY
        style.left = 'auto';

        if (x && x.length) {
            y = x[1];
            x = x[0];
        }

        if (x === null) {
            style.right = 'auto';
        } else if (x !== undefined) {
            style.right = x + 'px';
        }

        if (y === null) {
            style.top = 'auto';
        } else if (y !== undefined) {
            style.top = y + 'px';
        }
    },

    rtlSetX: function(x, animate) {
        return this.rtlSetXY([x, this.getY()], animate);
    },

    rtlSetXY: function(xy, animate) {
        var me = this,
            pts, style, pos;

        if (!animate || !me.anim) {
            pts = me.rtlTranslatePoints(xy);
            style = me.dom.style;

            // left position may have been previously set by setXY or setLocalXY
            // so clear it here just in case.
            style.left = 'auto';
            for (pos in pts) {
                if (!isNaN(pts[pos])) {
                    style[pos] = pts[pos] + "px";
                }
            }
        } else {
            if (!Ext.isObject(animate)) {
                animate = {};
            }
            me.animate(Ext.applyIf({ to: { x: xy[0], y: xy[1] } }, animate));
        }
        return me;
    },

    rtlSetY: function(y, animate) {
        return this.rtlSetXY([this.getX(), y], animate);
    },

    rtlTranslatePoints: function(x, y) {
        var pos = this.rtlTranslateXY(x, y);

        return {
            right: pos.x,
            top: pos.y
        };
    },

    rtlTranslateXY: function(x, y) {
        var me = this,
            styles = me.getStyle(me._positionTopRight),
            relative = styles.position == 'relative',
            right = parseFloat(styles.right),
            top = parseFloat(styles.top),
            xy = me.getXY(),
            dom = me.dom,
            doc, body, offsetParentWidth, offsetParent;

        if (x && x.length) {
             y = x[1];
             x = x[0];
        }
        if (isNaN(right)) {
            doc = document;
            body = doc.body;
            if (dom === body) {
                // translateXY can sometimes be called on the body element.
                // e.g. in Renderable#afterFirstLayout if the "container" is a viewport
                right = 0;
            } else {
                offsetParent = dom.offsetParent;
                offsetParentWidth = (offsetParent &&
                    offsetParent !== body && offsetParent !== doc.documentElement) ?
                        offsetParent.scrollWidth : Ext.Element.getViewportWidth();
                right = offsetParentWidth - dom.offsetLeft - me.getWidth();
            }
        }
        if (isNaN(top)) {
            top = relative ? 0 : me.dom.offsetTop;
        }
        right = (typeof x == 'number') ? x - xy[0] + right : undefined;
        top = (typeof y == 'number') ? y - xy[1] + top : undefined;
        return {
            x: right,
            y: top
        };
    },

    setX: function(x, animate) {
        return Ext.rootHierarchyState.rtl ? this.rtlSetX(x, animate) :
            this.callParent(arguments);
    },

    setXY: function(xy, animate) {
        return Ext.rootHierarchyState.rtl ? this.rtlSetXY(xy, animate) :
            this.callParent(arguments);
    },

    setY: function(y, animate) {
        return Ext.rootHierarchyState.rtl ? this.rtlSetY(y, animate) :
            this.callParent(arguments);
    },

    translatePoints: function(x, y) {
        return Ext.rootHierarchyState.rtl ? this.rtlTranslatePoints(x, y) : 
            this.callParent(arguments);
    },

    translateXY: function(x, y) {
        return Ext.rootHierarchyState.rtl ? this.rtlTranslateXY(x, y) : 
            this.callParent(arguments);
    }
});
