if (window.opera) render='optimizeSpeed';
else render='crispEdges';

num_length=6;


 function zoom_in()
 {
  if (r_settings['candles_max']<=25) return false;
  loading(1);
  r_settings['candles_max']=Math.round(r_settings['candles_max']/1.5);
  redraw();
 }

 function get_redraw()
 {
  omax=r_settings['offset']?r_settings['offset']:tgmax;
  if (tgmin>omax-r_settings['candles_max'])
  r_sc(r_settings.url+'?js=1&symbol='+symbol+'&period='+period+'&max='+tgmin+'&c='+(r_settings['candles_max']-(omax-tgmin)),0);
  else redraw();
 }

 function zoom_out()
 {
  if (r_settings['candles_max']>=350) return false;
  loading(1);
  r_settings['candles_max']=Math.round(r_settings['candles_max']*1.5);
  get_redraw();
 }

 function backwards()
 {
  loading(1);
  omax=r_settings['offset']?r_settings['offset']:tgmax;
  r_settings['offset']=omax-Math.round(r_settings.candles_max/2);
  get_redraw();
 }

 function forwards()
 {
  if (!r_settings.offset) return false;
  loading(1);
  omax=r_settings['offset']?r_settings['offset']:tgmax;
  r_settings['offset']=omax+Math.round(r_settings.candles_max/2);
  if (r_settings.offset>=tgmax) r_settings.offset=0;
  redraw();
 }

 function play_stop()
 {
  if (quotes_g_query) // play
  {
   // need to retrieve latest data
   r_sc(r_settings.url+'?js=1&symbol='+symbol+'&period='+period+'&max=0&c=10',1);
   quotes_g_query=0;
	//document.getElementById('play_stop_image').src='/images/graph/stop.gif';
	setPlayStopButton('stop');
   loading(1);redraw();
  }
  else // stop
  {
   quotes_g_query=1;
	setPlayStopButton('play');
	//document.getElementById('play_stop_image').src='/images/graph/play.gif';
  }
 }



function loading(v)
{
 if (r_settings.nopreloaderimage) return false;
 document.getElementById('holder').style.backgroundImage=v?'url(/images/graph/rotation.gif)':'';
}
/*
function l(s)
{
 return false;
 if (document.getElementById('log')) document.getElementById('log').innerHTML+=s+'<br />';
}
*/

function str_replace(s,r)
{
 for (k in r) {s=s.replace(new RegExp(k,'g'),r[k]);}
 return s;
}

function date(format,timestamp)
{
 var d=new Date((timestamp+(new Date().getTimezoneOffset()+120)*60)*1000);

 var dr={
         'H':d.getHours(),
         'i':d.getMinutes(),
         's':d.getSeconds(),
         'Y':d.getFullYear(),
         'm':d.getMonth()+1,
         'd':d.getDate()
        };
 dr['M']=(['Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec'])[dr['m']-1];
 dr['N']=dr['Y']*12+dr['m'];

 for (var i in dr) if ((''+dr[i]).length<2) dr[i]='0'+dr[i];
 return str_replace(format,dr);
}




 function dg(m)
 {
  m=Math.abs(m);
  //l('dg: '+m);
  var f=1,tmp=0;
  if (f>m)
  {
   while (f>m) {f/=10;}
   if ((tmp=2*f)>=m) return tmp;
   if ((tmp=5*f)>=m) return tmp;
   return 10*f;
  }
  else if (f<m)
  {
   while (f<m) {f*=10;}
   if ((tmp=f/5)>=m) return tmp;
   if ((tmp=f/2)>=m) return tmp;
   return f;
  }
  return f;
 }

 function format(v)
 {
  v=''+v;
  if (-1==v.indexOf('.')) v+='.';
  while (v.length<num_length) v+='0';
  return v;
 }

 function js_round(v) {return (Math.round(v*1000000)/1000000+'').substring(0,10)*1;}




function redraw()
{
 //l('redrawing');

 if (!r_settings.holder) r_settings.holder='holder';

 document.getElementById(r_settings.holder).innerHTML='';

 var cx=document.getElementById(r_settings.holder).offsetWidth,cy=document.getElementById(r_settings.holder).offsetHeight;
 r = Raphael(r_settings.holder,cx,cy);
 r.c=r_settings;

 if (!r.c.type) r.c.type='candle';


 // find global max/min
 qgmin=-1;qgmax=-1;tgmin=-1;tgmax=-1;
 num_length=-1;

 if ('candle'==r.c.type)
 {
  for (d in data)
  {
   if (-1==tgmin || tgmin>d) tgmin=d;if (-1==tgmax || tgmax<d) tgmax=d;
   for (var i=0;i<4;i++)
   {
    if (-1==qgmin || qgmin>data[d][i]) qgmin=data[d][i];
    if (-1==qgmax || qgmax<data[d][i]) qgmax=data[d][i];
    if (-1==num_length || num_length<data[d][i].length) num_length=data[d][i].length;
   }
  }
 }
 else if ('line'==r.c.type)
 {
  for (d in data)
  {
   if (-1==num_length || num_length<data[d].length) num_length=data[d].length;
   data[d]=1*data[d];
   if (-1==tgmin || tgmin>d) tgmin=d;if (-1==tgmax || tgmax<d) tgmax=d;
   if (-1==qgmin || qgmin>1*data[d]) qgmin=data[d];
   if (-1==qgmax || qgmax<1*data[d]) qgmax=data[d];
  }
 }

///////////////////////////////////

 var tmax=r.c.offset?r.c.offset:tgmax;
 var tmin=tgmin;
 if (-1==r.c.candles_min) tmin=tmax-r.c.candles_max;
 else tmin=tgmin>tmax-r.c.candles_max?
           (tgmin<tmax-r.c.candles_min?
             tgmin:
             tmax-r.c.candles_min):
           tmax-r.c.candles_max;


 // find local max/min
 if ('candle'==r.c.type)
 {
  qmin=qmax=data[tgmax][2];
  for (d in data)
  {
   if (d>=tmin && d<=tmax)
   for (var i=0;i<4;i++)
   {
    if (qmin>data[d][i]) qmin=data[d][i];
    if (qmax<data[d][i]) qmax=data[d][i];
   }
  }
 }
 else if ('line'==r.c.type)
 {
  qmin=qmax=data[tgmax];
  for (d in data)
  {
   if (d>=tmin && d<=tmax)
   if (qmin>data[d]) qmin=data[d];
   if (qmax<data[d]) qmax=data[d];
  }
 }
 //l('t: '+tmin+'/'+tmax+', q: '+qmin+'/'+qmax);

// if (r.c.debug) {alert(tmin+':'+qmin+' '+tmax+':'+qmax);return false;}

 r.c['wing']=Math.floor(cx/(3*(tmax-tmin+1))); // candle halfwidth

 r.cx=cx-r.c.pr;
 r.cy=cy-r.c.pb;
 r.xmin=1*tmin-1;
 r.xmax=1*tmax;
 r.ymin=0.9999*qmin;
 r.ymax=1.0001*qmax;

 r.ydg=js_round(dg(r.c.yg*(r.ymax-r.ymin)/r.cy)); // vertical grid step in graph units
 r.ymin=js_round(Math.floor(r.ymin/r.ydg)*r.ydg);
 r.ymax=js_round(Math.ceil(r.ymax/r.ydg)*r.ydg);

 r.xdg=js_round(dg(r.c.xg*(r.xmax-r.xmin)/r.cx)); // vertical grid step in graph units

 r.tx=function(x) {return Math.round((this.cx-r.c.wing)*(x-this.xmin)/(this.xmax-this.xmin));}
 r.ty=function(y) {return Math.round((this.cy)*(y-this.ymax)/(this.ymin-this.ymax));}

 r.draw_current=function()
 {
      for (i in this.current) this.current[i].hide();

      var q=data[tgmax][2];

	  this.current=[];
	  this.current.push(this.path({'stroke':r.c['current_'+direction],'shape-rendering':render}).toBack().moveTo(0,this.ty(q)).lineTo(this.cx,this.ty(q)));
	  this.current.push(this.rect(this.cx+3, this.ty(q)-7,this.c.pr-3,14).attr({'fill':r.c['current_'+direction],'stroke':r.c['current_'+direction],'shape-rendering':render}));
	  this.current.push(this.text(this.cx+5, this.ty(q), format(js_round(q))).attr({'text-anchor':'start','fill':'#fff'}));
 }


 /////////////////////////////////////////////
 // grid
 var g = r.path({stroke: r.c.grid,'shape-rendering':render,'stroke-dasharray':'-'}).toBack(); 
 // horizontal lines
 var y=r.ymin;
 while (y<=r.ymax)
 {
  g.moveTo(0,r.ty(y)).lineTo(r.cx,r.ty(y));
  if (y!=r.ymax) r.text(r.cx+5, r.ty(y), format(js_round(y))).attr({'text-anchor':'start'});
  y=js_round(y+r.ydg);
 }
 // vertical lines
 var x=r.xmin;
 while (x<=r.xmax)
 {
  g.moveTo(r.tx(x),0).lineTo(r.tx(x),r.cy);
  if (x!=r.xmin) r.text(r.tx(x)-2, r.cy+10, date(date_format,count2ts(x))).attr({'text-anchor':'start'});
  else r.text(r.tx(x)+2, r.cy-10, date("d M Y",count2ts(x))).attr({'text-anchor':'start'});
  x+=r.xdg;
 }
 ///////////////////////////////////////////////////

 if (!r.c.nobglogo) r.image("/images/graph/logo_gr.gif", 10, 10, 200, 56);
 r.path({stroke: r.c.grid,'shape-rendering':render}).moveTo(0,r.cy).lineTo(r.cx,r.cy).moveTo(r.cx,0).lineTo(r.cx,r.cy);

 r.candle=function(t,d)
 {
  var left=this.tx(t)-this.c.wing;
  if (d[1]<d[2]) // opened less than closed (rise)
  {
   var top=this.ty(d[1]);
   var bottom=this.ty(d[2]);
   var fill=this.c.fill_rise;
  }
  else if (d[1]>d[2]) // opened more than closed (fall)
  {
   var top=this.ty(d[2]);
   var bottom=this.ty(d[1]);
   var fill=this.c.fill_fall;
  }
  else // equal opened and closed
  {
   var fill='';
   var top=this.ty(d[2]);
  }

  this.ly=d[2];

  this.last_candle=[];

//  if (!(fill && pxmax==top && pxmin==bottom))
  this.last_candle.push(this.path({'stroke': this.c.stroke,'shape-rendering':render}).moveTo(this.tx(t), this.ty(d[0])).lineTo(this.tx(t), this.ty(d[3])));

  var attr={'fill':fill,'stroke':this.c.stroke,'shape-rendering':render};
  if (!r.c.notitle) attr['title']=date(date_format,count2ts(t))+' O:'+d[1]+', H:'+d[3]+', L:'+d[0]+', C:'+d[2];
  if (fill) this.last_candle.push(rect=this.rect(left,bottom,2*this.c.wing,top-bottom).attr(attr));
  else this.last_candle.push(this.path({'stroke': this.c.stroke,'shape-rendering':render}).moveTo(left, top).lineTo(left+2*this.c.wing, top));
 }

 r.drawline=function(t,d)
 {
  var x=this.tx(t);
  var y=this.ty(d);
  if (this.last_point) 
   this.path({'stroke':this.c.stroke}).moveTo(this.last_point[0],this.last_point[1]).lineTo(x,y);
  this.last_point=[x,y];

  this.circle(x,y,3).attr({fill:this.c.stroke,title:date(date_format,count2ts(t))+': '+d});

 }


 if ('candle'==r.c.type)
 {
  for (d=tmin;d<=tmax;d++)
   if (data[d]) r.candle(d,data[d]);
 }
 else if ('line'==r.c.type) 
 {
  for (d=tmin;d<=tmax;d++)
   if (data[d]) r.drawline(d,data[d]);
 }

/*
 for (d in data)
  if (d>=tmin && d<=tmax) 
  {
   if ('candle'==r.c.type) r.candle(d,data[d]);
   else if ('line'==r.c.type) r.drawline(d,data[d]);
  }
*/
 r.draw_current();

 loading(0);
}


	function r_sc(href,rnd)
	{
	if (rnd) href+=(/\?/.test(href)?'&':'?')+"rnd="+(new Date().getTime())
	var script = document.createElement('SCRIPT')
	script.type='text/javascript' 
	script.src=href
	document.documentElement.firstChild.appendChild(script)
	}

	function from_M1(c_m1)
	{
     var c=c_m1;
	 switch (period) {
	  case 'M1': c=c_m1;break;
	  case 'M5': c=c_m1/5;break;
	  case 'M15': c=c_m1/15;break;
	  case 'M30': c=c_m1/30;break;
	  case 'H1': c=c_m1/60;break;
	  case 'H4': c=(c_m1-120)/240;break;
	  case 'D1': c=(c_m1-120)/1440;break;
	  case 'W1': c=(c_m1-7320)/10080;break;
	  case 'MN': c=date('N',c_m1*60);
	 }
	 return Math.floor(c);
	}

	function count2ts(c) { // no MN here
	 c*=60;
	 switch (period) {
	  case 'M1': return c;
	  case 'M5': return c*5;
	  case 'M15': return c*15;
	  case 'M30': return c*30;
	  case 'H1': return c*60;
	  case 'H4': return c*240+120;
	  case 'D1': return c*1440+120;
	  case 'W1': return c*10080+7320;
	  case 'MN': return Math.floor(Date.parse(Math.floor(c/12)+'/'+(c % 12)+'/1')/1000);
	 }
	}


    function graph_fx4u_update_quotes(q)
    {
     if (!r) return false;
     var d=q['data'][symbol];
     direction=d['dir'];

     //l(d['ut']);
     d['ut']=from_M1(d['ut']);


     //l(d['ut']+': '+d['bid']);

     if (!data[d['ut']]) 
     {
      data[d['ut']]=[d['bid'],d['bid'],d['bid'],d['bid']];
      //l('data added');
      if (r.c.offset) {r.ly=d['bid'];r.draw_current();}
      else {loading(1);redraw();}
     }
     else if (data[d['ut']][2]!=d['bid']) 
     {
      data[d['ut']][0]=Math.min(data[d['ut']][0],d['bid']);
      data[d['ut']][2]=d['bid'];
      data[d['ut']][3]=Math.max(data[d['ut']][3],d['bid']);
      //l('data_updated');
      //l('min/max: '+qmin+'/'+qmax);
      if (d['bid']<=qmin || d['bid']>=qmax) {redraw();return;}

      for (i in r.last_candle) r.last_candle[i].hide();
      //l('candle hidden');
      r.candle(d['ut'],data[d['ut']]);
      //l('candle drawn');
      
      r.draw_current();
      //l('current redrawn');
     }
    }


if (typeof fx4u_update_quotes_callback=='undefined') fx4u_update_quotes_callback={};
fx4u_update_quotes_callback['graph']=graph_fx4u_update_quotes;


