'use strict';

var Tokenizer = require('../tokenization/tokenizer'),

TokenizerProxy = require('./tokenizer_proxy'),
Utils = require('../common/utils');

//Default options var DEFAULT_OPTIONS = {

decodeHtmlEntities: true,
locationInfo: false

};

//Skipping handler function skip() {

//NOTE: do nothing =)

}

//SimpleApiParser var SimpleApiParser = module.exports = function (handlers, options) {

this.options = Utils.mergeOptions(DEFAULT_OPTIONS, options);
this.handlers = {
    doctype: this._wrapHandler(handlers.doctype),
    startTag: this._wrapHandler(handlers.startTag),
    endTag: this._wrapHandler(handlers.endTag),
    text: this._wrapHandler(handlers.text),
    comment: this._wrapHandler(handlers.comment)
};

};

SimpleApiParser.prototype._wrapHandler = function (handler) {

var parser = this;
handler = handler || skip;
if (this.options.locationInfo) {
    return function () {
        var args = Array.prototype.slice.call(arguments);
        args.push(parser.currentTokenLocation);
        handler.apply(handler, args);
    };
}
return handler;

};

//API SimpleApiParser.prototype.parse = function (html) {

var token = null;
this._reset(html);
do {
    token = this.tokenizerProxy.getNextToken();
    if (token.type === Tokenizer.CHARACTER_TOKEN ||
        token.type === Tokenizer.WHITESPACE_CHARACTER_TOKEN ||
        token.type === Tokenizer.NULL_CHARACTER_TOKEN) {
        if (this.options.locationInfo) {
            if (this.pendingText === null)
                this.currentTokenLocation = token.location;
            else
                this.currentTokenLocation.end = token.location.end;
        }
        this.pendingText = (this.pendingText || '') + token.chars;
    }
    else {
        this._emitPendingText();
        this._handleToken(token);
    }
} while (token.type !== Tokenizer.EOF_TOKEN);

};

//Internals SimpleApiParser.prototype._handleToken = function (token) {

if (this.options.locationInfo)
    this.currentTokenLocation = token.location;
if (token.type === Tokenizer.START_TAG_TOKEN)
    this.handlers.startTag(token.tagName, token.attrs, token.selfClosing);
else if (token.type === Tokenizer.END_TAG_TOKEN)
    this.handlers.endTag(token.tagName);
else if (token.type === Tokenizer.COMMENT_TOKEN)
    this.handlers.comment(token.data);
else if (token.type === Tokenizer.DOCTYPE_TOKEN)
    this.handlers.doctype(token.name, token.publicId, token.systemId);

};

SimpleApiParser.prototype._reset = function (html) {

this.tokenizerProxy = new TokenizerProxy(html, this.options);
this.pendingText = null;
this.currentTokenLocation = null;

};

SimpleApiParser.prototype._emitPendingText = function () {

if (this.pendingText !== null) {
    this.handlers.text(this.pendingText);
    this.pendingText = null;
}

};