var Graphs = {

	 /**
     * This object keeps data about the option graphs, its filled within init()
     */
    graphs: {},
	
    /**
     * Contains all open positions
     */
    openPositionGraphs: {},

    nextUpdate: null,

    init: function() {
    
		$('#optionsList .graphContainer').each( function (i) {

		   var chart_id = 'assetChart_' + (i+1);

		   $('<div/>').attr('id', chart_id).addClass('assetChart').appendTo(this);

		   Graphs.graphs[chart_id] = {
				series : {},
				options : {},
				currRate: null,
				itemName: null,
				container:  this,
				plot : null,
				lastPos : null
		   };

		   /** Initialize the graphs on Pro platform only
			* (on fast platform the call is at homeCompact::showGraph)
			*/
		   if (AppData.platformMode == 'pro')
			   Graphs.loadChartData(chart_id);
		 
		   Graphs.startStreaming();

		});


    },
	
	startStreaming: function () {

        var page = General.initLightstreamer();

        // Each graph container has an id in this format: graphContainer_<assetId>,
		// near each graph the is the put/call window container in which the customer
		// places his bid.
		// That window contains the option id which advertises that asset in a hidden input.
		//
        // we need to fill up an array of assetIds which will be sent to lightstreamer
        // for subscription.
		//
		// **** There array items are string of the following format:
		//		asset_<assetId>_<optionId>_<whiteLabelName>

        var assetsToSubscribe = [];

		$.each(Graphs.graphs, function(key) {
			if (key.indexOf('assetChart_') !== -1) {

				var assetId =  this.container.id.split('_')[1];
                
				if (AppData.platformMode == 'fast'){
                    var optionContainer = $(this.container).parent().parent().prev().prev();
                    var selectedExpireTime = optionContainer.find('div.expireTimeContainer ul li.selected');
                    if (selectedExpireTime.length){
                        var optionId = selectedExpireTime.attr('id').split('_').splice(2,1);
                        optionContainer.next().find('div.putCallFolder input[name="optionId"]').val(optionId);
                    }else{
                         var optionId = $(this.container).parents('li').prev('.applyPosition').find('input[name=optionId]').val();
                    }
                }
				else{
                   var optionContainer = $(this.container).parent().parent();
                   var selectedExpireTime = optionContainer.find('div.expireTimeContainer ul li.selected');
                   if (selectedExpireTime.length){
                        var optionId = selectedExpireTime.attr('id').split('_').splice(2,1);
                        optionContainer.find('div.putCallFolder input[name="optionId"]').val(optionId);
                   }else{
                       var optionId = $(this.container).parent().parent().find('.putCallFolder').find('input[name=optionId]').val();
                       /* option builder graphs does not have pricing rate, therefore the optionId will be 0 */
                       if (typeof(optionId) == 'undefined')
                           optionId = "0";
                   }
                }

				this.itemName = 'asset_' + assetId + '_' + optionId + '_' + AppData.whiteLabelName;
				assetsToSubscribe.push (this.itemName);

			}
		});

                    if (typeof('SixtySeconds') != 'undefined'  && AppData.platformMode == 'pro' ){
            assetsToSubscribe = SixtySeconds.subscribe(assetsToSubscribe);
        }

        $('div.open_positions ul.positions li.open_position').each(function() {
            var assetId = this.id.split('_')[3];
            var optionId = $(this).attr('optionId');
            var itemName = 'asset_' + assetId + '_' + optionId + '_' + AppData.whiteLabelName;

            /**
             *  Fix bug when the open positions are not updated as win/lose when the option is not opened in the box
             */
            var itemExists = jQuery.inArray(itemName, assetsToSubscribe);
            if (-1 ===  itemExists || typeof(itemExists) == 'undefined') {
                assetsToSubscribe.push ( itemName );
            }
        });

        page.removeTable('assetsTable');
        

        var assetsTable   = new NonVisualTable(assetsToSubscribe, ['rate', 'id', 'lastUpdated', 'color', 'pricingRate'], "MERGE");
        page.addTable(assetsTable, "assetsTable");
        assetsTable.onItemUpdate =  Graphs.onItemUpdate; //Graphs.onItemUpdate;
        //console.log(assetsToSubscribe);
    },

	// This method should be called when user selects another asset from the options drop select box
    notifyAssetChange: function( graphContainer ) {

        var chart_id = graphContainer.find('.assetChart').attr('id');

        if (chart_id) {
            Graphs.loadChartData( chart_id );
        }
    },

	/**
     * Calculate next graph update, at every round 30 seconds,
     * if now the time is 12:11:21 then the update will occur in 12:11:30
     */
    calculateNextUpdate: function() {
        if (General.dateTime == null) return;
        
        var nextUpdate = Math.floor( General.dateTime.getTime() / 30000 ) * 30 + 30;
        return new Date(nextUpdate * 1000);
    },

    /**
     * Loads a given chart data, chart_id is a key in Graphs.graph object,
     * a chart knows which asset data it should load, the asset id is located
     * in its parent container id ( div#graphContainer_<assetId> ).
     *
     * @param string chart_id - chart to update
     */
    loadChartData: function(chart_id, customOption) {
        var graphContainer   = $('#' + chart_id).parent('div.graphContainer');
        var graphContainerId = graphContainer.attr('id');
        if (graphContainerId === null){
            return;
        }
		var assetId = graphContainerId.split('_')[1];

		if (AppData.platformMode == 'pro')
			var boxList = $('#' + chart_id).parent().parent().parent().parent();
		else //Fast (compact) platform
			var boxList = $('#' + chart_id).parent().parent().parent().prev().prev();

		 $.ajax({
                url: AppData.url + 'home/getAssetGraphJSON/' + assetId,
                method: 'GET',
                dataType: 'json',
                success: function (graphData) {
					Graphs.graphs[chart_id].options = graphData.options;
                                        Graphs.graphs[chart_id].options.grid.autoHighlight = true;
					if(graphData.series.length){
						Graphs.graphs[chart_id].series = [];
						$.each(graphData.series, function(i, data){
							Graphs.graphs[chart_id].series.push(data);
						});
					}
					else{
						Graphs.graphs[chart_id].series = [graphData.series];
						graphData.series =  new Array(graphData.series);
					}
					var graphEL = $('#' + chart_id);

					// Get asset id from its parent container's id'
					var assetId = graphEL.parent('div.graphContainer')
									.attr('id').split('_')[1];

					if (AppData.platformMode == 'pro')
						var optionId = $('#' + chart_id).parent('div.graphContainer')
										.parent().parent().find('.putCallFolder').find('input[name=optionId]').val();
					else //Fast (compact) platform
						var optionId = $('#' + chart_id).parents('li').prev('.applyPosition').find('input[name=optionId]').val();


					var itemName = 'asset_' + assetId + '_' + optionId + '_' + AppData.whiteLabelName;

					Graphs.graphs[chart_id].itemName = itemName;

					var feedId = '#feed_asset_' + chart_id.split('_')[1];

					if (graphData.series.length || graphData.series.data.length) { //graph data is available

                         /* if the graph is hidden - it means that we change asset or expire time */
                        if (AppData.platformMode == 'fast'){
                           
                            /* if the graph is not shown */
                            if (graphEL.parent().parent().parent().hasClass('hidden')){
                                Graphs.startStreaming();
                                return;
                            }
                        }

						//draw the graph
                        if($(Graphs.graphs[chart_id].container).parent().is(':visible')){
                            Graphs.redraw(chart_id);
                        }

						//Save current point to graphs array
						Graphs.graphs[chart_id].currRate = graphData.series[0].data.pop();
						var lastRate = Graphs.graphs[chart_id].currRate[1].toFixed(graphData.options.yaxis.tickDecimals);
						$(feedId).html(lastRate);
						if (!customOption) { //Regular option
							if (typeof Position !== 'undefined' && Position.onRateChange) {
								//var positionContainer = $(feedId).parents('.positionContent');
								// fill current rate in the put/call form. (** NOTE: it was disabled before for "fast" platform)
                                // The last rate is now inserted from the DB - Home::getOptionsId
								//Position.onRateChange(positionContainer.find('input.rate'), lastRate);
							}
						}

                        /* TXP-467 */
                        //$(feedId).html(lastRate);
					} else { //No data!
						//Empty graph
						Graphs.graphs[chart_id].series[0].data = new Array();
						Graphs.graphs[chart_id].currRate = null;

						//draw the graph
						Graphs.redraw(chart_id);

						if (graphData === 'Not tradeable') {
							$(feedId).html('<div style="position:absolute;width:200px;">Not Tradeable</div>');
						} else {
							$(feedId).html('N/A');
						}
					}


					/* subscribe the items with the LS */
					Graphs.startStreaming();

					if (AppData.platformMode == 'pro'){
						Home.completeLoadingBoxList(boxList);
					}
					
				} //end success()
            });
                
    },

	 /**
     *
     * Called every lightstreamer clock tick.
     *
     * When called first time, initializes lightstreamer graphs
     *
     * Periodically updates all graphs every round 30 seconds.
     * (e.g 12:20:30 and 12:21:00 are proper update periods)
     *
     * @param timeString - current time in HH:MM:SS format
     */
    onUpdateTime : function () {
        if ( Graphs.nextUpdate == null ) {
            Graphs.nextUpdate = Graphs.calculateNextUpdate();
        }

		//Check if its time to update the graph
        if (  Graphs.nextUpdate <= General.dateTime ) {
            Graphs.nextUpdate = Graphs.calculateNextUpdate();
			//Iterate through all the graphs to update them
			$.each(Graphs.graphs, function(key) {
				
                if (Graphs.graphs[key].series) {
                     
					//If rate is valid (1 element is the rate)
					if ( this.currRate && this.currRate[1]) {
                      
						if ( key.indexOf('assetChart') !== -1 && $(Graphs.graphs[key].container).parent().is(':visible') && Graphs.graphs[key].series[0].data.length >= 119) { //Asset graph
							//Remove the first rate
							Graphs.graphs[key].series[0].data.shift();
							/* Rescale - the scale min is the new first data point time and
							 * the scale max is the latest data point time */
							var firstPoint = Graphs.graphs[key].series[0].data[0];
							Graphs.graphs[key].options.xaxis.min = firstPoint[0];
							Graphs.graphs[key].options.xaxis.max =  this.currRate[0];
						}
                        
						//Add the new rate
                        
                        Graphs.graphs[key].series[0].data.push(this.currRate);
                        

						//Redraw the graph
                        if ($(Graphs.graphs[key].container).parent().is(':visible')){
                            Graphs.redraw(key);
                        }
                        
					}
				}

            }); // end $.each

            Graphs.nextUpdate = Graphs.calculateNextUpdate();
        } // end if
    },

	 /**
     * Lightstreamer callback, update rightmost point of each graph to the
     * newly fetched asset rate.
     */
    onItemUpdate: function(item, itemUpdate, itemName) {
        try{
		if ( Graphs.nextUpdate === null ) {
			Graphs.nextUpdate = Graphs.calculateNextUpdate();
		}
        if (itemUpdate.isValueChanged('pricingRate')) {
            /* if the customer is logged in */
            try{
                if (AppData.isLoggedIn){
                    var pricingRate = itemUpdate.getNewValue('pricingRate');
                    var rate        = itemUpdate.getNewValue('rate');
                }else{
                    var pricingRate = itemUpdate.getNewValue('pricingRate');
                    var rate        = itemUpdate.getNewValue('rate');
                    var tailDigits = pricingRate.indexOf('.');
                    tailDigits = pricingRate.toString().length-tailDigits-1;
                    var signs = new Array('-','+');
                    var randomSign  = signs[Math.round(Math.random())];    /* get random sign */
                    var randomShift = 0.0002+(Math.random()*(0.0004-0.0002)); /* get random number between 0.2 and 0.4 */
                    eval('pricingRate=parseFloat(pricingRate' + randomSign + 'pricingRate*' + randomShift + ').toFixed(' + tailDigits + ')');
                    eval('rate=parseFloat(rate' + randomSign + 'rate*' + randomShift + ').toFixed(' + tailDigits + ')');
                }
            }catch(ex){
                console.log(ex);
            }
            
            // -COLOR HERE
            var color = parseInt(itemUpdate.getNewValue('color'));
            var lastUpdated = itemUpdate.getNewValue('lastUpdated');

            MyPositions.updatePositionPayout(itemName,pricingRate);
            MyPositions.updateMyPayout();



            // Iterate each graph and check if its the one being updated
            $.each(Graphs.graphs, function(key) {
               if (  this.itemName  ==  itemName) {
				   //Update current rate array
				   var unixTime = new Date(AppData.serverDate + " " + lastUpdated);
				   var offset = General.serverOffset + General.browserOffset;
				   this.currRate  = new Array(unixTime.getTime() + offset, parseFloat(pricingRate));

//				   if ($(Graphs.graphs[key].container).parent().is(':visible') && Graphs.graphs[key].series[0].data.length > 0) { //At least 1 point
                    var itemContainerParent = $(Graphs.graphs[key].container).parent();
                    var isVisible = 1;
                    if(itemContainerParent.length === 1 && itemContainerParent.is(':hidden'))
                        var isVisible = 0;
                    
				   if ( isVisible && Graphs.graphs[key].series[0].data.length > 0) { //At least 1 point
					   //At least 2 points
					   if (Graphs.graphs[key].series[0].data.length > 1) {
						   //Remove the last (current) rate
							Graphs.graphs[key].series[0].data.pop();
					   }
						//Add the new rate
						Graphs.graphs[key].series[0].data.push(this.currRate);

						if ( key.indexOf('PositionGraph') !== -1 ) { //Position graph
    
							//Change the graph scaling if the new rate exceeds the current min/max
							if (this.currRate[1] > Graphs.graphs[key].options.yaxis.max) {
								//The new scale max should be current rate + margin fraction%
								Graphs.graphs[key].options.yaxis.max = this.currRate[1] + this.currRate[1] * AppData.positionGraphMarginFraction;
								//Also add it to min, to keep the rate leveled
								Graphs.graphs[key].options.yaxis.min = Graphs.graphs[key].options.yaxis.min - Graphs.graphs[key].options.yaxis.min * AppData.positionGraphMarginFraction;
							}

							if (this.currRate[1] < Graphs.graphs[key].options.yaxis.min) {
								//The new scale min should be current rate - margin fraction%
								Graphs.graphs[key].options.yaxis.min = this.currRate[1] - this.currRate[1] * AppData.positionGraphMarginFraction;
								//Also add it to maxn, to keep the rate leveled
								Graphs.graphs[key].options.yaxis.max = Graphs.graphs[key].options.yaxis.max + Graphs.graphs[key].options.yaxis.max * AppData.positionGraphMarginFraction;
							}

						} else if ( key.indexOf('assetChart') !== -1 ) {
							//Upgrade rate marking on asset graph
                                                                                                                                Graphs.graphs[key].options.xaxis.max =  this.currRate[0];
							Graphs.graphs[key].options.grid.markings[0].yaxis.from = this.currRate[1];
							Graphs.graphs[key].options.grid.markings[0].yaxis.to = this.currRate[1];
                                                        
						}

						/*
                         * If this is pro platform - update the graph always because the graph is always visible
                         */
                        /*console.log('graph item');
                        console.log(key);
                        console.log($('#' + key));
                        */
                        if (AppData.platformMode == 'pro')
                            if ($('#' + key).is(':visible')){

                                Graphs.redraw(key);
                            }else{
                               ; /* the graph is not visible */
                            }
                        else{
                            /* if this is fast platform - update the graph only when the graph is visible */
                            if ($('#' + key).is(':visible')){
                                Graphs.redraw(key);
                            }else{
                                /* the graph is not visible */
                            }
                        }


				   }
                   if ( key.indexOf('assetChart') !== -1 ) {
    				   // index goes from 0..N and denotes the order of rate reporting boxes
					   // first box is 0, second is 1 etc
					   var index = key.split('_')[1];

                       if(color){

                       		if($('#feed_asset_' + index).hasClass('longDisabled')){
                       			$('#feed_asset_' + index).html(pricingRate).css('color', '#BBCBBB');
                       		}
                       		else{
                       			$('#feed_asset_' + index).html(pricingRate).css('color', '#024301');
                       		}
                       }
					   else{
					   		if($('#feed_asset_' + index).hasClass('longDisabled')){
					   			$('#feed_asset_' + index).html(pricingRate).css('color', '#DAC3C3');
					   		}
					   		else{
					   			$('#feed_asset_' + index).html(pricingRate).css('color', '#C30700');
					   		}

                   		}

						/* update the rate in options builder box */
                        if (AppData.optionsBuilderEnabled){
                            if (typeof(OptionsBuilder != 'undefined') && (typeof Graphs.graphs['assetChart_0'] != 'undefined'))
                                OptionsBuilder.onItemUpdate(item,itemUpdate,itemName); //Only call it if there is already a customer (id=0) option builder option
                        }
                   }

				   if (AppData.platformMode == 'fast')
				   // this sets the rate in the box found the put/call form when you click put/call
						$('#putcall_rate_' + index).val(pricingRate);

                   if (typeof Position !== 'undefined' && Position.onRateChange) {
                        var positionContainer = $('#feed_asset_' + index).parents('.positionContent');
                        // fill current rate in the put/call form.
                        Position.onRateChange(positionContainer.find('input.rate'), pricingRate);
                   }

               }

            }); // end $.each
                              if (typeof(SixtySeconds != 'undefined'  && AppData.platformMode == 'pro' )){
                    SixtySeconds.onItemUpdate(item,itemUpdate,itemName);
            }
        }
        }catch(ex){
            console.log(ex);
        }
    }, // end onItemUpdate()

	redraw : function (chart_id) {
        try{
            Graphs.graphs[chart_id].options.lines.lineWidth = 1;
		var graphEL = $('#' + chart_id);
		
		if (Graphs.graphs[chart_id].plot != null) {
			graphEL.unbind();
		}

		// Save the label visibility for after the re-draw
		var labelVisibility = graphEL.find('div.legend').css('visibility');

		//if ($(Graphs.graphs[chart_id].container).parent().is(':visible')){
            Graphs.graphs[chart_id].plot = $.plot(graphEL, Graphs.graphs[chart_id].series, Graphs.graphs[chart_id].options);
        //}

		//Re-set the visility and update the last hovered rate
		if(labelVisibility && labelVisibility == 'visible') {
			var lastHoveredRate = Graphs.graphs[chart_id].series[0].data[Graphs.graphs[chart_id].lastPos];
			Graphs.showLabel(chart_id, lastHoveredRate[0], lastHoveredRate[1], Graphs.graphs[chart_id].plot);
			graphEL.find('div.legend').css('visibility', labelVisibility);
		}

		//Highlight the last rate
		Graphs.graphs[chart_id].plot.highlight(0, Graphs.graphs[chart_id].series[0].data.length-1);


		//Bind the hover event to update the legend with current point
		graphEL.bind("plothover",  function (e, pos, item) {
			Graphs.onGraphHover(pos, Graphs.graphs[chart_id].plot, Graphs.graphs[chart_id].series[0], graphEL);
		});

		graphEL.bind("mouseout",  function (e) {
			graphEL.find('div.legend').css('visibility','hidden');
		});
        }catch(ex){
        }
	},

	onGraphHover : function (pos, plot, series, graphEL) {
		
		if (!series.data.length)
			return;

		var axes = plot.getAxes();
		if (pos.x < axes.xaxis.min || pos.x > axes.xaxis.max ||
			pos.y < axes.yaxis.min || pos.y > axes.yaxis.max) {
			return;
		}

		var j;
		var chart_id = graphEL.attr('id');

		var lastElement = (series.data.length-1);

		// find the nearest points, x-wise
		for (j = 0; j <= lastElement; ++j) {
			if (series.data[j][0] > pos.x) {
				break;
			}
		}

		if (chart_id.indexOf('oneTouchGraph_') == -1) { //Not one touch graph
			//Save the last position (index of the series data) found
			Graphs.graphs[chart_id].lastPos = j;
		}

		var y = 0, p1 = series.data[j-1], p2 = series.data[j];
		if (p1 == null || j == lastElement) { //First or last point - dont interpolate
			y = p2[1];
		}else if (p2 == null) {
			y = p1[1];
		} else //Interpolate
			y = p1[1] + (p2[1] - p1[1]) * (pos.x - p1[0]) / (p2[0] - p1[0]);

		Graphs.showLabel(chart_id, pos.x, y, plot);

	},

	showLabel : function (chart_id, time, rate, plot) {

		var graphOptions = plot.getOptions();
		var graphEL = $('#' + chart_id);

		//Convert time back to UTC
		var time = (time - General.serverOffset);
		var d = new Date(time + AppData.timeZoneOffset);

		var hours =  d.getHours();
		var minutes = d.getMinutes();
		var seconds = d.getSeconds();

		if ( hours < 10) hours     = '0' + hours;
        if ( minutes < 10) minutes = '0' + minutes;
        if ( seconds < 10) seconds = '0' + seconds;

		var labelText = "Rate: " + rate.toFixed(graphOptions.yaxis.tickDecimals) + ' Time: ' + hours + ':' + minutes + ':' + seconds;
		legend = graphEL.find('.legendLabel');
		//Update the label element text
		legend.text(labelText);
		
		if (chart_id.indexOf('oneTouchGraph_') == -1) { //Not one touch graph
			//Update the label in the series options
			Graphs.graphs[chart_id].series[0].label = labelText;
		}

		//Show the label
		graphEL.find('div.legend').css('visibility','visible');
	},

	drawOneTouch : function(graphEl) {
		var optionId = graphEl.attr('optionId');
		
		if (optionId > 0) {
		
			$.ajax({
					url: AppData.url + 'home/getOneTouchGraphJSON/' + optionId,
					method: 'GET',
					dataType: 'json',
					success: function (graphData) {
						var options = graphData.options;
                        options.lines.lineWidth = 1;
						var series = [ graphData.series ];
						var plot = $.plot(graphEl, series, options);

						//Bind the hover event to update the legend with current point
						graphEl.bind("plothover",  function (e, pos, item) {
							Graphs.onGraphHover(pos, plot, series[0], graphEl);
						});

						graphEl.bind("mouseout",  function (e) {
							graphEl.find('div.legend').css('visibility','hidden');
						});
					}
				 });
		}
	},
	
	/**
     * Loads graphs into containers which class is "oneTouchGraph".
     *
     *
     */
    loadOneTouchGraphs: function() {
        // Iterate through containers and initialize their graphs
         $('.oneTouchGraph').each ( function(i) {
			 var el = $(this)
             this.id = 'oneTouchGraph_' + i;
			 Graphs.drawOneTouch(el);
        }); // end $.each

    } // end loadOneTouchGraphs();


};

//Auto init on-ready
$(Graphs.init);
