var scope = require('../scope'),
    tagMappings = {
        div: 'container',
        ul: 'container'
    };

// require all the supported element types
// without these requires, the browserification process will not work
require('./input');
require('./container');
require('./span');
require('./p');

function HtmlDriver(data, opts) {
    this.data = data;
}

HtmlDriver.prototype.attach = function(target, basePath) {
    var elementPath, binding, handlerType, handler, ii = 0, count,
        path, data = this.data,
        checkChildNodes = true;

    // if the node is text, or a comment abort
    if ((target instanceof Text) || (target instanceof Comment)) return;

    // if the target is already bound, then abort
    if (target._activeBinding) return;

    // initialise the basepath if not already provided
    basePath = basePath || new data.Path();

    // if we have a basepath that is not a Path instance, then convert it to one
    if (! (basePath instanceof data.Path)) {
        basePath = new data.Path(basePath);
    }

    // check to see if we have a path on the element
    binding = target.getAttribute('data-binding');
    count = target.childNodes.length;

    // path relative to the current element
    path = basePath.append(target.getAttribute('data-scope') || target.getAttribute('data-path'));

    // bind if we have a binding
    if (binding) {
        // get the handler type
        handlerType = target.tagName.toLowerCase();

        // check if we should use another handler for the current tag
        handlerType = tagMappings[handlerType] || handlerType;
        handler = require('./' + handlerType);

        // run the handler
        checkChildNodes = handler.call(this, target, data, binding, path);

        // flag as bound
        target._activeBinding = path.append(binding);
    }

    // iterate through the child nodes of the element
    for (; (checkChildNodes || typeof checkChildNodes == 'undefined') && ii < count; ii++) {
        if (target.childNodes[ii]) {
            this.attach(target.childNodes[ii], path);
        }
    }
};

/**
## remove(target)

Debind listening on the node
*/
HtmlDriver.prototype.remove = function(target) {
    // TODO: needs to be more specific
    if (target._activeBinding) {
        this.data.debind(target._activeBinding);
    }

    if (! target.childNodes) return;

    // iterate through the child nodes
    for (var ii = target.childNodes.length; ii--; ) {
        if (target.childNodes[ii] && (! (target.childNodes[ii] instanceof Text))) {
            this.remove(target.childNodes[ii]);
        }
    }
};

module.exports = function(data, opts) {
    return new HtmlDriver(data, opts);
};