/**
 * @param string _mode = 'platform' || 'pro' || 'fast'
 * @parm bool or object _loadRelated
 * @param string step
 * @callbacks object after stepChanged
 */

function Option(id, init, loadRelated, mode, step, stepChangeCallbacks){
	
	//public properties
	this.minPosition = AppData.minPosition || 25;
	this.maxPosition = AppData.maxPosition || 1000;
	/*
	 * countdown object, used to update how much time left before
	 * option expiry
	 */
	this.countdown   = new Countdown();
	/*
	 * for general purposes
	 */
	this.userCountdown = new Countdown();
	this.timeLeft    = false;
	/* indicates when object is fully loaded */
	this.completed = false;
	/*
	 * additional properties, not directly from `options` table
	 * */
	this.assetName;
	this.optionEndDate;
	//satus flag, if true all positions of this option
	// can be rollovered
	this.rolloverPosible = true;
	
	this.sellPosible = null;
	//private properties
	var _mode = mode || 'pro';
	
	var _step = step;
	
	var _stepChangeCallbacks = stepChangeCallbacks;
	
	var _that = this;
	var _loadRelated = loadRelated;
	
	var _relatedClasses = {
		assetId: 'Asset'	
	};
	//those field are in MYSQL TIMESTAMP formats
	var _timeFields = new Array('startDate', 'endDate');
	//those fields are in minutes, related to the endDate
	var _relativeTimeFields = new Array('noPositionTime', 'lastPositionTime', 'noRolloverTime', 'maxBuyOutTime');
	
	var _booleanFields = new Array('bmoSuspended');
	//private methods
	
	var retrieveData = function(data){
		$.each(data, function(name, value){	
			var ansInArray = $.inArray(name, _timeFields);
			if(typeof ansInArray != 'undefined' && ansInArray != -1){//convert time string to ms(in correct time zone
				_that[name + 'MS'] = iOkun.strtotime(value) * 1000 + General.browserOffset;
				
				if(name == 'endDate'){
					_that.countdown.init(parseInt((_that[name + 'MS'] - getCurrentTime())/1000), false, false, _that.updateTimeLeftToExpiry);	
				}	
			}
			ansInArray = $.inArray(name, _relativeTimeFields);
			if(typeof ansInArray != 'undefined' && ansInArray != -1){
				_that[name + 'MS'] = iOkun.strtotime(data['endDate']) * 1000 + General.browserOffset - value * 60 * 1000;
			}
			
			ansInArray = $.inArray(name, _booleanFields);
			if(typeof ansInArray != 'undefined' && ansInArray != -1){
				value = parseInt(value);
			}
			_that[name] = value;
		});
		
		if(_loadRelated){
			if(typeof _loadRelated == 'object'){
				//in this case _loadRelated contains object of related classes
				$.each(_loadRelated, function(idRelated, relatedObject){
					_that[idRelated] = relatedObject;
				});
				_loadRelated = true;
			}
			else{
				$.each(_relatedClasses, function(idRelated, className){
					//load related objects
					_that[idRelated] = new window[className](_that[idRelated]);
				});
			}
		}
		//object is loaded
		_that.completed = true;
	}
	/**
	 * returns unix time in ms according site time
	 */
	var getCurrentTime = function(){
		var d = new Date();
		return General.dateTime.getTime() + General.browserOffset;
	}
	/* called every second, and updates this.sellPosible
	 * return true when status has been changed
	 */
	var updateSellStatus = function(){
		
		var currentSellStatus = _that.sellPosible;
		
		if(getCurrentTime() > _that.noPositionTimeMS || _that.bmoSuspended || getCurrentTime() < _that.maxBuyOutTimeMS){
			_that.sellPosible = false;
		}
		else{
			_that.sellPosible = true;
		}
//		if(parseInt(_that.id) == 1778836){
//			console.log(_that.noPositionTimeMS + ' no position time');
//			console.log(getCurrentTime() +  ' current time');
//			console.log(_that.maxBuyOutTimeMS + ' max buy out time');
//			console.log(_that.bmoSuspended + ' bmosuspended');
//		}
		
		
		return (currentSellStatus == _that.sellPosible) ? false : true;
	}
	
	
	//public methods
	this.setStepChangeCallbacks = function(callbacks){
		_stepChangeCallbacks = callbacks;
	}
	
	this.setStep = function(step){
		var availableSteps = ['open', 'beforeExpiry', 'closedForNewPosition', 'expired'];
		var ansInArray = $.inArray(step, availableSteps)
		if(typeof ansInArray != 'undefined' && ansInArray != -1){
			_step = step;
			if(typeof _stepChangeCallbacks[_step] == 'function'){
				 _stepChangeCallbacks[_step](_that);
			}
		}
		else{
			alert('Unavailable step status');
			return false;
		}
	}
	
	this.getStep = function(){return _step}
	
	this.initGraph = function(container, feedId){
		if(!_loadRelated){
			alert('Can\'t initiliaze graphs, please load related object');
			return;
		}
		if (_mode == 'platform'){ 
			var isPlatform = true;
			var isRescale = false;
		}
		else{
			var isPlatform = false;
			var isRescale = true;
		}
		var showPosition = (AppData.isLoggedIn) ? true : false;
		
		_that.graph = new Graph(container, feedId, isPlatform, isRescale, showPosition, this);
		
	}
	/**
	 * this method called in every countdown tick,
	 * propose of this method is to determine in wich step the option situated
	 * right now, and change the step accordingly
	 */
	this.updateTimeLeftToExpiry = function(){
		if(_that.completed){
			_that.timeLeft = _that.countdown.getTimeLeft();
			if(updateSellStatus() && typeof Option.onSellStatusChangedCallback == 'function'){
				Option.onSellStatusChangedCallback(_that);
			}
			
			if(getCurrentTime() > _that.noRolloverTimeMS && typeof Option.noRolloverCallback == 'function' && _that.rolloverPosible){
				console.log('no rollover')
				Option.noRolloverCallback(_that);
				_that.rolloverPosible = false;
			}
			
			switch(_that.getStep()){
				case 'open':				if( getCurrentTime() > _that.lastPositionTimeMS){
												console.log('from open to beforeExpiry')
												//update coundown time left - reduce the gup between lightstreamer and the counter
												_that.countdown.updateTimeLeft(parseInt((_that['endDateMS'] - getCurrentTime())/1000));
												_that.setStep('beforeExpiry');
											} 
											break;
				case 'beforeExpiry':		if(getCurrentTime() > _that.noPositionTimeMS){
												console.log('from beforeExpiry to closedForNewPosition');	
												_that.setStep('closedForNewPosition');
											}
											break;
				case 'closedForNewPosition':if(getCurrentTime() > _that.endDateMS){
												console.log('from closedForNewPosition to  expired')
												_that.setStep('expired');
												
												
											}
											break;
				case 'expired':				break;
			}
		}
		//lastPositionTime
		//noPositionTime
	}
	
	this.calculateProfitLoss = function(investment){
		var positionProfit = 0;
		var positionLoss   = 0;
		if (investment > 0) {
			positionProfit = ((100 + parseInt(_that.profit)) * investment)/100;
			positionLoss = ((100-parseInt(_that.loss)) * investment)/100;	
		}
		return new Array(positionProfit, positionLoss);
	}
	
	this.destruct = function(){
		if(typeof _that.graph == 'object')
			_that.graph.destruct();
		_that.countdown.destruct();
		_that.userCountdown.destruct();
		delete _that;
		console.log('destruct option')
	}
	
	if(!(init)) AjxMgr.request(AjxMgr.pathAjax + 'getOptions' , 'POST', {ids: id}, 'json', false, retrieveData);
	else retrieveData(init);
	
	
}
//static properties
//we can not consider "noRollover" as step, so we handaling
// this differently
Option.noRolloverCallback = null;

Option.onSellStatusChangedCallback = null;
//static methods
/**
 * get options as object
 */
Option.getOptions = function(ids){
	var optionArr = new Array();
	
	var retrieveData = function(data){
		$.each(data, function(key, props){
			optionArr.push(new Option(false, props));
		});		
	}
	//synchronic call, but the browser 
	//did not stop because of threading approach
	AjxMgr.request(AjxMgr.pathAjax + 'getOptions', 'POST', {ids: JSON.stringify(ids)}, 'json', false, retrieveData);
	
	return optionArr;	
}

