define('kadro/dom/DOM', ['kadro/dom/KHTMLElement'], function() {
    return function DOM() {

        this.createElement = function(element) {
            return new KHTMLElement(document.createElement(element));
        };

        /**
         * findByID
         * Find element by it's ID
         *
         * @param  {string} id    Element unique ID
         *
         * @return {KHTMLElement} Element that has the specified ID
         */
        this.findByID = function(id, parent) {
            var _parent = getParentNativeElement(parent);

            var element;

            if (_parent.getElementById) {
                element = new KHTMLElement(_parent.getElementById(id) || []);
            } else {
                element = this.findByQuery('#' + id, parent);
            }

            return element;
        };

        /**
         * findByClass
         * Find elements that has a specified class
         *
         * @param  {string}       class  Class name to filter the elements
         * @param  {KHTMLElement} parent Parent element of the elements to find
         *
         * @return {KHTMLElement}        Element that has the specified class
         */
        this.findByClass = findBy.bind(this, 'getElementsByClassName', '.');

        /**
         * findByTag
         * Find elements that has a specified tag name
         *
         * @param  {string}       tag    Tag name to filter the elements
         * @param  {KHTMLElement} parent Parent element of the elements to find
         *
         * @return {KHTMLElement}        Element that has the specified tag name
         */
        this.findByTag = findBy.bind(this, 'getElementsByTagName', '');

        /**
         * findByQuery
         * Find elements that match a css query
         *
         * @param  {string}       query  Query to search the elements for
         * @param  {KHTMLElement} parent Parent element of the elements to find
         *
         * @return {KHTMLElement}        [description]
         */
        this.findByQuery = function(query, parent) {
            var _parent = getParentNativeElement(parent);

            var elements = _parent.querySelectorAll(query);

            return new KHTMLElement(collectionToArray(elements));
        };

        function findBy(fn, prefix, filter, parent) {
            var _parent = getParentNativeElement(parent);

            var elements;
            if(_parent[fn]) {
                elements = _parent[fn](filter);
                elements = new KHTMLElement(collectionToArray(elements));
            } else {
                elements = this.findByQuery(prefix + filter, parent);
            }

            return elements;
        }

        function getParentNativeElement(parent) {
            return (parent && parent.getNativeElements()[0]) || document;
        }

        function collectionToArray(collection) {
            var elements = [];
            for (var i = 0; i < collection.length; i++) {
                elements.push(collection[i]);
            }

            return elements;
        }
    };
});
