//forEach is a JavaScript extension to the ECMA-262 standard;
if (!Array.prototype.forEach)
{
    Array.prototype.forEach = function(fun /*, thisp*/)
    {
        var len = this.length;
        if (typeof fun != "function")
            throw new TypeError();

        var thisp = arguments[1];
        for (var i = 0; i < len; i++)
        {
            if (i in this)
                fun.call(thisp, this[i], i, this);
        }
    };
}

function TableModel(args) {
    this.dataService = args.dataService;
    this.table = args.table;
};

TableModel.prototype.updateAllRows = function() {
    this.dataService.getAllLeagues(this, "onAllRowsArrived");
};

TableModel.prototype.updateScrollRows = function() {
    this.dataService.getAllLeagues(this, "onScrollRowsArrived");
};
TableModel.prototype.updateRows = function(rows) {
    this.dataService.findLeagues(rows, this, "onUpdatedRowsArrived");
};

TableModel.prototype.getAllRows = function() {
    return this.allRows;
};

// Unsupported
TableModel.prototype.getRows = function(ids) {
    return this.lastUpdated;
};

TableModel.prototype.getLastUpdatedRows = function() {
    return this.lastUpdated;
};

TableModel.prototype.onAllRowsArrived = function(data) {
    this.allRows = data;
    this.table.onUpdateAllRowsClb();
};
TableModel.prototype.onScrollRowsArrived = function(data) {
    this.allRows = data;
    this.table.onUpdateScrollRowsClb();
};
TableModel.prototype.onUpdatedRowsArrived = function(rowIds, data) {
    this.lastUpdated = data;
    this.table.onRowsUpdatedClb(data);
};

function Table(ctx) {
    this.ctx = ctx;
    this.container = ctx.container;
    this.model = ctx.model;
    // TODO [eugenek] put observ
    this.model.table = this;
    if (ctx.renderer) {
        this.renderer = ctx.renderer;
    } else {
        this.renderer = new TableRenderer({});
    }
    this.renderer.rootId = this.container;
    this.subscribers = [];
};

Table.prototype.onUpdateAllRowsClb = function() {
	  // this.updateElement($(this.container), this.renderer.renderRoot(this.model.getAllRows()));
    this.updateElement(document.getElementById(this.container), this.renderer.renderRoot(this.model.getAllRows()));
};
Table.prototype.onUpdateScrollRowsClb = function() {
	  // this.updateElement($(this.container), this.renderer.renderRoot(this.model.getAllRows()));
    this.updateElement(document.getElementById(this.container), this.renderer.renderScrollRoot(this.model.getAllRows()));
};

Table.prototype.onRowsUpdatedClb = function(ids) {
    var data = this.model.getRows().data;
    this.updateRows(data);
};

Table.prototype.updateRows = function(data) {
    var isUnknownExists = false;
    for (var i = 0; i < data.length; i++) {
        var id = data[i]['id'];
        var txt = data[i]['txt'];
        var elem = document.getElementById(id);
        if (elem) {
            this.updateElement(elem, txt);

        }
    }
};

Table.prototype.updateElement = function(e, val) {
    e.innerHTML = val;
    this.notifyElementUpdated(e);
};

Table.prototype.notifyElementUpdated = function(e) {
    try{
        this.renderer.tableElementUpdated(e);
    }
    catch(e){
    }

    var data = e;

    this.subscribers.forEach(function(i) {
        try{
            i['updated'](data);
        }catch(e) {
            
        }
    });
};

Table.prototype.addOnUpdateListener = function(listener) {
    var candidate = listener;
    var alreadyExists = undefined;
    this.subscribers.forEach(
            function (el) {
                if (el === candidate) {
                   alreadyExists = true;
                }
            }
            );
    if(!alreadyExists){
        this.subscribers.push(listener);
    }

};