/*
 * Paper.js - The Swiss Army Knife of Vector Graphics Scripting.
 * http://paperjs.org/
 *
 * Copyright (c) 2011 - 2014, Juerg Lehni & Jonathan Puckey
 * http://scratchdisk.com/ & http://jonathanpuckey.com/
 *
 * Distributed under the MIT license. See LICENSE file for details.
 *
 * All rights reserved.
 */

/**
 * @name DomElement
 * @namespace
 * @private
 */
var DomElement = new function() {
    // Handles both getting and setting of vendor prefix values
    function handlePrefix(el, name, set, value) {
        var prefixes = ['', 'webkit', 'moz', 'Moz', 'ms', 'o'],
            suffix = name[0].toUpperCase() + name.substring(1);
        for (var i = 0; i < 6; i++) {
            var prefix = prefixes[i],
                key = prefix ? prefix + suffix : name;
            if (key in el) {
                if (set) {
                    el[key] = value;
                } else {
                    return el[key];
                }
                break;
            }
        }
    }

    return /** @lends DomElement */{
        getStyles: function(el) {
            // If el is a document (nodeType == 9), use it directly
            var doc = el && el.nodeType !== 9 ? el.ownerDocument : el,
                view = doc && doc.defaultView;
            return view && view.getComputedStyle(el, '');
        },

        getBounds: function(el, viewport) {
            var doc = el.ownerDocument,
                body = doc.body,
                html = doc.documentElement,
                rect;
            try {
                // On IE, for nodes that are not inside the DOM, this throws an
                // exception. Emulate the behavior of all other browsers, which
                // return a rectangle of 0 dimensions.
                rect = el.getBoundingClientRect();
            } catch (e) {
                rect = { left: 0, top: 0, width: 0, height: 0 };
            }
            var x = rect.left - (html.clientLeft || body.clientLeft || 0),
                y = rect.top - (html.clientTop || body.clientTop || 0);
            if (!viewport) {
                var view = doc.defaultView;
                x += view.pageXOffset || html.scrollLeft || body.scrollLeft;
                y += view.pageYOffset || html.scrollTop || body.scrollTop;
            }
            return new Rectangle(x, y, rect.width, rect.height);
        },

        getViewportBounds: function(el) {
            var doc = el.ownerDocument,
                view = doc.defaultView,
                html = doc.documentElement;
            return new Rectangle(0, 0,
                view.innerWidth || html.clientWidth,
                view.innerHeight || html.clientHeight
            );
        },

        getOffset: function(el, viewport) {
            return DomElement.getBounds(el, viewport).getPoint();
        },

        getSize: function(el) {
            return DomElement.getBounds(el, true).getSize();
        },

        /**
         * Checks if element is invisibile (display: none, ...)
         */
        isInvisible: function(el) {
            return DomElement.getSize(el).equals(new Size(0, 0));
        },

        /**
         * Checks if element is visibile in current viewport
         */
        isInView: function(el) {
            // See if the viewport bounds intersect with the windows rectangle
            // which always starts at 0, 0
            return !DomElement.isInvisible(el)
                    && DomElement.getViewportBounds(el).intersects(
                        DomElement.getBounds(el, true));
        },

        /**
         * Gets the given property from the element, trying out all browser
         * prefix variants.
         */
        getPrefixed: function(el, name) {
            return handlePrefix(el, name);
        },

        setPrefixed: function(el, name, value) {
            if (typeof name === 'object') {
                for (var key in name)
                    handlePrefix(el, key, true, name[key]);
            } else {
                handlePrefix(el, name, true, value);
            }
        }
    };
};
