/**
 * Библиотека FLINE (FonBet Line)
 */


/**
 * AJAX-обмен с сервером через DWR
 */

function FLINE_Dwr(storage, lang){
    this.lang = lang;
    this.storage = storage;
    this.factorId = 1;
    this.version = 0;
    this.structureChanged = false;
    this.lineUpdater = new FLINE_Dwr_Line_Updater(this, lang);
    this.serverTimeDiff = 0;
}
FLINE_Dwr.prototype.execute = function(callback){
    window.setTimeout(callback, 10);
}
FLINE_Dwr.prototype.placeCoupon = function(historyCoupon){
    var betExtraInfo = "source="+BET_EXTRA_INFO_SOURCE;
    var betRequest = {amount: historyCoupon.amount, currency: userGetCurrency(), factorList: new Array(), extraInfo:betExtraInfo, betChangeMode:historyCoupon.changeMode};
    for(var i in historyCoupon.lineList){
	var fct = historyCoupon.lineList[i];
	//var evt = this.storage.getEvent(fct.eventId);
	var betFactor = {
	    num: fct.num,
	    eventId: fct.eventId,
	    codeId: fct.factorTypeId, 
	    value: fct.factorValue,
	    score: fct.eventScore
	};
	if(fct.factorParam != null){
	    betFactor.param = fct.factorParam;
	}
	betRequest.factorList.push(betFactor);
    }
    var dwr = this;
    BetProxy.placeCoupon(betRequest, {
	callback:function(couponInfo){
	    historyCoupon.onCouponInfoReceived(couponInfo);
	},
	errorHandler:function(errorString, exception){
	    FLINE_Log.error('FLINE_Dwr.placeCoupon', errorString);
            dwr.handleBetException(errorString, exception);
	    historyCoupon.onCouponServerErrorReceived();
	}
    });
}
FLINE_Dwr.prototype.checkCouponStatus = function(historyCoupon){
    if(historyCoupon.id == null){
	FLINE_Log.error('FLINE_Dwr.checkCouponStatus', 'Coupon id is null!');
	return;
    }
    var dwr = this;
    BetProxy.checkCouponStatus(historyCoupon.id,{
	callback:function(couponInfo){
	    historyCoupon.onCouponInfoReceived(couponInfo);
	},
	errorHandler:function(errorString, exception){
	    FLINE_Log.error('FLINE_Dwr.checkCouponStatus', errorString);
            dwr.handleBetException(errorString, exception);
	    historyCoupon.onCouponServerErrorReceived();
	}
    });
}
FLINE_Dwr.prototype.changeCoupon = function(historyCoupon, couponChanges){
    if(couponChanges.couponId == null){
	FLINE_Log.error('FLINE_Dwr.checkCouponStatus', 'Coupon id is null!');
	return;
    }
    var dwr = this;
    BetProxy.changeCoupon(couponChanges, {
	callback:function(couponInfo){
	    historyCoupon.onCouponInfoReceived(couponInfo);
	},
	errorHandler:function(errorString, exception){
	    FLINE_Log.error('FLINE_Dwr.changeCoupon', errorString);
        dwr.handleBetException(errorString, exception);
	    historyCoupon.onCouponServerErrorReceived();
	}
    });
}
FLINE_Dwr.prototype.handleBetException = function(errorString, exception){
	    if(exception.javaClassName == "com.fonbet.livebets.webmodule.dwr.UserNotLoggedInException"){
            userLogout();
            alert(lang.get("exceptionUserNotLoggedIn"));
	    }else if(exception.javaClassName == "com.fonbet.livebets.webmodule.dwr.BettingIsProhibitedException"){
            alert(lang.get("exceptionBettingIsProhibited"));
	    }else if(exception.javaClassName == "com.fonbet.livebets.webmodule.dwr.FrequentBetsException"){
            alert(lang.get("exceptionFrequentBets"));
	    }else if( (exception.message != null) && (exception.message != "") ){
            //alert(exception.message); //сообщение будет показано в historyCoupon.onCouponServerErrorReceived();
	    }
}
/* FLINE_Dwr.prototype.sheduleUpdate = function(){
    if(arguments.length == 1) this.updateTimeout = arguments[0]; 
    if(this.timerId != null) window.clearTimeout(this.timerId);
    if(this.updateTimeout == 0) return;
    var me = this;
    this.timerId = window.setTimeout(function(){me.loadUpdates();}, this.updateTimeout);
}*/
FLINE_Dwr.prototype.loadUpdates = function(){
    //FLINE_Log.notice('FLINE_Dwr_Line.loadUpdates','Requesting updates from version '+this.version);
    var me = this;
    LineProxy.getUpdates(this.version, {
	callback:function(updatePacket){
	    //alert(DWRUtil.toDescriptiveString(updatePacket, 4));
	    //FLINE_Log.notice('FLINE_Dwr_Line.loadUpdates','UpdatePacket received. fromVersion: '+updatePacket.fromVersion+', packetVersion: '+updatePacket.packetVersion+', isCleanupRequired: '+updatePacket.isCleanupRequired);
	    me.execute(function(){
		me.loadUpdatePacket(updatePacket);
		me.lineUpdater.finishWaiting();
	    });
	},
	errorHandler:function(errorString, exception){
	    FLINE_Log.error('FLINE_Dwr.loadUpdates', errorString);
	    me.lineUpdater.finishWaiting();
	}
    });
}
FLINE_Dwr.prototype.loadUpdatePacket = function(updatePacket){
    if(updatePacket.packetVersion == 0){ //если версия пакета = 0, значит никаких данных вообще нету
		this.storage.clear();
		line.paint();
		anonsTable.paint();
		return;
    }
    if(this.version >= updatePacket.packetVersion) return; //игнорируем старые пакеты, если случайно пришли (после проблем со связью)
    this.loadUpdatePacketTimeDiff(updatePacket);
    if(updatePacket.isCleanupRequired){
		this.storage.clear();
		this.structureChanged = true;
    }
    this.loadUpdatedSportList(updatePacket.updatedSportList);
	this.loadUpdatedAnonsList(updatePacket.updatedAnonsList);
    this.loadUpdatedEventList(updatePacket.updatedEventList);
    this.loadUpdatedFactorList(updatePacket.updatedFactorList);
    
    this.version = updatePacket.packetVersion;
    
    if(this.structureChanged){
		this.structureChanged = false;
		line.paint();
		anonsTable.paint();
    }
}
FLINE_Dwr.prototype.loadUpdatePacketTimeDiff = function(updatePacket){
    var localTime  = new Date();
    this.serverTimeDiff = localTime.valueOf() - updatePacket.serverTime.valueOf();
}
FLINE_Dwr.prototype.serverTimeToLocal = function(servTime){
    if(servTime == null) return null;
    var localValue = servTime.valueOf() + this.serverTimeDiff;
    return new Date(localValue);
}
FLINE_Dwr.prototype.loadUpdatedSportList = function(list){
    for (var itemIndex in list) {
	var item = list[itemIndex];
	this.loadSport(item);
    }
}
FLINE_Dwr.prototype.loadSport = function(item){
    var sport = this.storage.getSport(item.id);
    if(sport == undefined){
		sport = new FLINE_Sport(item.id, item.num, item.name)
		this.storage.setSport(sport);
		this.structureChanged = true;
    }else{
		if((item.name != undefined) && (item.name != "")){
			sport.name = item.name;
		}
    }
}
FLINE_Dwr.prototype.loadUpdatedAnonsList = function(list){
	for (var itemIndex in list) {
		var item = list[itemIndex];
		this.loadAnons(item);
	}
}
FLINE_Dwr.prototype.loadAnons = function(item){
    if(item.state == 0){
		this.storage.removeAnons(item.id);
		this.structureChanged = true;
		return;
    }
    var anons = this.storage.getAnons(item.id);
    if(anons == undefined){
		anons = new FLINE_Anons(item.id, item.num, item.sportName, item.name, item.state, item.startTime);
		this.storage.setAnons(anons);
		this.structureChanged = true;
		anonsTable.isExpanded=true;
    }else{
		anons.state = item.state;
		if((item.name != undefined) && (item.name != "")){
			anons.name = item.name;
		}
		if(item.startTime != null){
			anons.startTime = item.startTime;
        }
		this.structureChanged = true;
    }
}

FLINE_Dwr.prototype.loadUpdatedEventList = function(list){
    for (var itemIndex in list) {
	var item = list[itemIndex];
	this.loadEvent(item);
    }
}
FLINE_Dwr.prototype.loadEvent = function(item){
    if(item.state == 0){
	this.storage.removeEvent(item.id);
	this.structureChanged = true;
	return;
    }
    
    var event = this.storage.getEvent(item.id);
    if(event == undefined){
	var sport = this.storage.getSport(item.sportId);
	if(sport == undefined){
	    FLINE_Log.error('FLINE_Dwr.loadEvent', 'Sport '+item.sportId+'for event '+item.id+' can not be found.');
	    return;
	}
	event = new FLINE_Event(item.id, item.sportId, item.parent, item.num, item.name);
	if(item.blocked != undefined) event.isEnabled = !item.blocked;
	this.storage.setEvent(event);
	this.createStandartFactors(item.id);
	this.structureChanged = true;
    }else{
	if((item.name != undefined) && (item.name != "")){
	    event.name = item.name;
	}
	if(item.blocked != undefined) event.setEnabled(!item.blocked);
    }
    if(item.comment == undefined) item.comment = null;
    event.setScore(item.score1, item.score2, item.comment);
    event.setTimerData(item.timerDirection, item.timerSeconds, this.serverTimeToLocal(item.timerUpdateTime));
}

FLINE_Dwr.prototype.loadUpdatedFactorList = function(list){
    for (var itemIndex in list) {
	var item = list[itemIndex];
	this.loadFactor(item);
    }
}
FLINE_Dwr.prototype.loadFactor = function(item){
    //проверяем наличие события
    var event = this.storage.getEvent(item.eventId);
    if(event == undefined) return;
    //отказаться от авто-id котировок пока нельзя из-за createStandartFactors()
    var factor = this.storage.findFactor(item.eventId, item.code);
    var itemValue = item.value;
    if(factor == undefined){
	switch(item.type){
	    case 0:
		factor = new FLINE_Factor_OK(this.factorId++, item.eventId, item.code, item.codeId, item.blocked, itemValue)
		break;
	    case 1:
		factor = new FLINE_Factor_PARAM(this.factorId++, item.eventId, item.code, item.codeId, item.blocked, itemValue, item.param)
		break;
	}
	this.storage.setFactor(factor);
	this.structureChanged = true;
    }else{
	factor.setBlocked(item.blocked);
	if(factor.typeId == 0) factor.typeId = item.codeId;
	switch(item.type){
	    case 1:
		factor.updateParam(item.param);
		//break не нужен! 
	    case 0:
		if ( (factor.value == 0 && item.value != 0) ||
		     (factor.value != 0 && item.value == 0)
		    ) this.structureChanged = true;
		factor.updateValue(item.value);
	}
    }
}
FLINE_Dwr.prototype.createStandartFactors =  function(eventId){
    this.storage.setFactor(new FLINE_Factor_OK(this.factorId++, eventId, 'p1', 0 , 0, 0));
    this.storage.setFactor(new FLINE_Factor_OK(this.factorId++, eventId, 'pX', 0 , 0, 0));
    this.storage.setFactor(new FLINE_Factor_OK(this.factorId++, eventId, 'p2', 0 , 0, 0));
    this.storage.setFactor(new FLINE_Factor_OK(this.factorId++, eventId, 'p1X', 0 , 0, 0));
    this.storage.setFactor(new FLINE_Factor_OK(this.factorId++, eventId, 'p12', 0 , 0, 0));
    this.storage.setFactor(new FLINE_Factor_OK(this.factorId++, eventId, 'pX2', 0 , 0, 0));
    this.storage.setFactor(new FLINE_Factor_PARAM(this.factorId++, eventId, 'f1', 0 , 0, 0, 0));
    this.storage.setFactor(new FLINE_Factor_PARAM(this.factorId++, eventId, 'f2', 0 , 0, 0, 0));
    this.storage.setFactor(new FLINE_Factor_PARAM(this.factorId++, eventId, 'tG', 0 , 0, 0, 0));
    this.storage.setFactor(new FLINE_Factor_PARAM(this.factorId++, eventId, 'tL', 0 , 0, 0, 0));
}

function FLINE_Dwr_Line_Updater(dwr, lang) {
    this.dwr = dwr;
    this.lang = lang;
    this.updateTimer = new FTimer(5000, 1000);
    this.waitTimer = new FTimer(60000, 1000);
    this._isWaiting = false;
    var me = this;
    this.updateTimer.onTimeout = function(){me._onUpdateTimeout();};
    this.updateTimer.onDelta = function(){me._onUpdateDelta();};
    this.waitTimer.onTimeout = function(){me._onWaitTimeout();};
    this.waitTimer.onDelta = function(){me._onWaitDelta();};
}
FLINE_Dwr_Line_Updater.prototype.setUpdateTimeout = function(interval){
    this.updateTimer.interval = interval;
}
FLINE_Dwr_Line_Updater.prototype.setWaitTimeout = function(interval){
    this.waitTimer.interval = interval;
}
FLINE_Dwr_Line_Updater.prototype.start = function(){
    this.stop();
    this.updateTimer.start();
    this._isWaiting = false;
}    
FLINE_Dwr_Line_Updater.prototype.finishWaiting = function(){
    this.stop();
    this.updateTimer.start();
    this._isWaiting = false;
}
FLINE_Dwr_Line_Updater.prototype.stop = function(){
    this.updateTimer.cancel();
    this.waitTimer.cancel();
    this._isWaiting = false;
}    
FLINE_Dwr_Line_Updater.prototype._onUpdateTimeout = function(){
    //console.info("UpdateTimer timeout.");
    this.waitTimer.start();
    this._isWaiting = true;
    this.dwr.loadUpdates();
    line.statusUpdated();
}
FLINE_Dwr_Line_Updater.prototype._onUpdateDelta = function(){
    //console.info("UpdateTimer Delta: "+this.updateTimer.getTimeToEnd());
    line.statusUpdated();
}
FLINE_Dwr_Line_Updater.prototype._onWaitTimeout = function(){
    //console.info("WaitTimer timeout.");
    this.updateTimer.start();
    line.statusUpdated();
}
FLINE_Dwr_Line_Updater.prototype._onWaitDelta = function(){
    //console.info("WaitTimer Delta: "+this.waitTimer.getTimeToEnd());
    line.statusUpdated();
}
FLINE_Dwr_Line_Updater.prototype.getStatusText = function(){
    if(this._isWaiting){
	var left = Math.ceil(this.waitTimer.getTimeToEnd()/1000);
	return this.lang.get("line_update_connect", left);
    }else{
	var left = Math.ceil(this.updateTimer.getTimeToEnd()/1000);
	return this.lang.get("line_update_wait", left);
    }
}
loadingJSLoaded++;