//---------------------------------------------------------------------------
#include <Classes.hpp>
#include <string.h>
#include <stdio.h>
#include <math.h>
#include <dir.h>
//---------------------------------------------------------------------------
#pragma hdrstop
#include "fmt_wl.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
//---------------------------------------------------------------------------
double    mj2dt( double);
double    dt2mj( double);
char*     correct_name( char*);

char*     last_name;
//---------------------------------------------------------------------------
void TikerRename( PLG_FMT_DATA* data)
{
  AnsiString ss0, ss1;
  char*      p;


	p = correct_name( data->sName);
	ss0 = data->sDir; ss0 += "\\";
	ss0 += p; free(p);
	ss0 += ".wl";

	p = correct_name( (char*)data->pd);
	ss1 = data->sDir; ss1 += "\\";
	ss1 += p; free(p);
	ss1 += ".wl";

	rename( ss0.c_str(), ss1.c_str());
}
//---------------------------------------------------------------------------
void TikerDelete( PLG_FMT_DATA* data)
{
  AnsiString ss;
  char*      p;


	p = correct_name( data->sName);
	ss = data->sDir; ss += "\\"; ss += p; ss += ".wl";
	remove( ss.c_str());

  free(p);
}
//---------------------------------------------------------------------------
void DatePeriod( PLG_FMT_DATA* data)
{
  AnsiString ss;
  FILE*      ff;
  WLD_HDR    hdr;
  WLD_BAR    wld_bar;
  float      *pc_ch,d1,d2;
  char*      p;


	data->dt1 = 0.0;
	data->dt2 = 0.0;

	p = correct_name( data->sName);
	ss = data->sDir; ss += "\\"; ss += p; ss += ".wl";
	if( (ff = fopen( ss.c_str(), "rb")) != NULL )
	{
	   fread( &hdr, sizeof(WLD_HDR), 1, ff);
	   fread( &wld_bar, sizeof(WLD_BAR), 1, ff);
	   data->dt1 = wld_bar.dDate;

	   fseek( ff,  sizeof(WLD_HDR) + sizeof(WLD_BAR)*(hdr-1), SEEK_SET);
	   fread( &wld_bar, sizeof(WLD_BAR), 1, ff);
	   data->dt2 = wld_bar.dDate;
	   d2 = wld_bar.fClose;

	   fseek( ff,  sizeof(WLD_HDR) + sizeof(WLD_BAR)*(hdr-2), SEEK_SET);
	   fread( &wld_bar, sizeof(WLD_BAR), 1, ff);
	   d1 = wld_bar.fClose;

	   pc_ch  = (float*)malloc( sizeof(float)*4);
	   pc_ch[0] = d2;
	   if( d1 != 0.0 ) pc_ch[1] = ((d2-d1)/d1)*100;
	   else            pc_ch[1] = 0;
	   data->pd = pc_ch;

	   fclose( ff);
	}

  free(p);
}
//---------------------------------------------------------------------------
LST_TICKERS* Tikers( char* dir)
{
  TStringList*  s1   = new TStringList;
  LST_TICKERS*  list = new LST_TICKERS;
  struct ffblk  ffblk;
  int           done;
  AnsiString    str;


	str = dir; str += "\\*.wl";
	done = findfirst( str.c_str(), &ffblk, 0);
	while( !done )
	{
	   s1->Add( ChangeFileExt(ffblk.ff_name,""));
	   done = findnext(&ffblk);
	}

	list->Count = s1->Count;
	list->sName = new char*[list->Count];
	for( int i=0; i < list->Count; i++)
	  list->sName[i] = strdup( s1->Strings[i].c_str());

  delete s1;
  return list;
}
//---------------------------------------------------------------------------
void SeriesAdd( PLG_FMT_DATA* data)
{
  AnsiString    ss;
  FILE          *ff;
  WLD_HDR       hdr;
  WLD_BAR       bar, wld_bars;
  TDateTime     dt1,dt2;
  int           rb=0;
  double        dt;
  char*         p;


	p = correct_name( data->sName);
	ss = data->sDir; ss += "\\"; ss += p; ss += ".wl";
	if( (ff = fopen( ss.c_str(), "r+b")) != NULL )
	{
	   fread( &hdr, sizeof(WLD_HDR), 1, ff);
	   for( int i = hdr; i > 0; i--)
	   {
		  fseek( ff, sizeof(WLD_HDR)+sizeof(WLD_BAR)*hdr - sizeof(WLD_BAR)*(rb+1), SEEK_SET);
		  fread( &bar, sizeof(WLD_BAR), 1, ff);
		  dt1 = mj2dt( bar.dDate);
		  dt2 = mj2dt(((SERIES*)data->pd)->pDate[0]);

		  dt = fabs(dt1 - dt2);
		  if( dt1 >= dt2 ) rb+=1;
		  else
			if( dt < 0.0001 ) rb+=1;
			else break;
	   }

	   fseek( ff,  sizeof(WLD_HDR)+sizeof(WLD_BAR)*hdr - sizeof(WLD_BAR)*rb, SEEK_SET);
	   for( int i=0; i < ((SERIES*)data->pd)->Count; i++)
	   {
		 bar.dDate   = ((SERIES*)data->pd)->pDate[i];
		 bar.fOpen   = ((SERIES*)data->pd)->pfOpen[i];
		 bar.fHigh   = ((SERIES*)data->pd)->pfHigh[i];
		 bar.fLow    = ((SERIES*)data->pd)->pfLow[i];
		 bar.fClose  = ((SERIES*)data->pd)->pfClose[i];
		 bar.fVolume = ((SERIES*)data->pd)->pfVolume[i];
		 fwrite( &bar, sizeof(WLD_BAR), 1, ff);
	   }

	   hdr = hdr - rb + ((SERIES*)data->pd)->Count;
	   fseek( ff, 0, SEEK_SET);
	   fwrite( &hdr, sizeof(WLD_HDR), 1, ff);

	   fclose( ff);
	}

  free(p);
}
//---------------------------------------------------------------------------
void SeriesSet( PLG_FMT_DATA* data)
{
  AnsiString ss;
  FILE*      ff;
  WLD_HDR    hdr;
  WLD_BAR    bar;
  char*      p;


	p = correct_name( data->sName);
	ss = data->sDir; ss += "\\"; ss += p; ss += ".wl";
	if( (ff = fopen( ss.c_str(), "wb")) != NULL )
	{
	   hdr = ((SERIES*)data->pd)->Count;
	   fwrite( &hdr, sizeof(WLD_HDR), 1, ff);

	   for( int i=0; i < ((SERIES*)data->pd)->Count; i++)
	   {
		  bar.dDate   = ((SERIES*)data->pd)->pDate[i];
		  bar.fOpen   = ((SERIES*)data->pd)->pfOpen[i];
		  bar.fHigh   = ((SERIES*)data->pd)->pfHigh[i];
		  bar.fLow	  = ((SERIES*)data->pd)->pfLow[i];
		  bar.fClose  = ((SERIES*)data->pd)->pfClose[i];
		  bar.fVolume = ((SERIES*)data->pd)->pfVolume[i];

		  fwrite( &bar, sizeof(WLD_BAR), 1, ff);
	   }

	   fclose( ff);
	}

  free(p);
}
//---------------------------------------------------------------------------
SERIES* SeriesGet( PLG_FMT_DATA* data)
{
  SERIES*      ser = NULL;
  AnsiString   ss;
  FILE*        ff;
  WLD_HDR      hdr;
  WLD_BAR      bar;
  char*        p;


	p = correct_name( data->sName);
	ss = data->sDir; ss += "\\"; ss += p; ss += ".wl";
	if( (ff = fopen( ss.c_str(), "rb")) != NULL )
	{
	   fread( &hdr, sizeof(WLD_HDR), 1, ff);
	   ser           = new SERIES;
	   ser->Count    = hdr;
	   ser->pDate    = new double[hdr];
	   ser->pfOpen   = new float [hdr];
	   ser->pfHigh   = new float [hdr];
	   ser->pfLow    = new float [hdr];
	   ser->pfClose  = new float [hdr];
	   ser->pfVolume = new float [hdr];
	   ser->pfOpInt  = new float [hdr];
	   ZeroMemory( ser->pDate, sizeof(double)*ser->Count);
	   ZeroMemory( ser->pfOpen  , sizeof(float)*ser->Count);
	   ZeroMemory( ser->pfHigh  , sizeof(float)*ser->Count);
	   ZeroMemory( ser->pfLow   , sizeof(float)*ser->Count);
	   ZeroMemory( ser->pfClose , sizeof(float)*ser->Count);
	   ZeroMemory( ser->pfVolume, sizeof(float)*ser->Count);
	   ZeroMemory( ser->pfOpInt , sizeof(float)*ser->Count);

	   for( int i=0; i < hdr; i++)
	   {
		  fread( &bar, sizeof(WLD_BAR), 1, ff);

		  ser->pDate[i]    = bar.dDate;
		  ser->pfOpen[i]   = bar.fOpen;
		  ser->pfHigh[i]   = bar.fHigh;
		  ser->pfLow[i]    = bar.fLow;
		  ser->pfClose[i]  = bar.fClose;
		  ser->pfVolume[i] = bar.fVolume;
		  ser->pfOpInt[i]  = 0;
	   }

	   fclose( ff);
	}

  free(p);
  return ser;
}
//---------------------------------------------------------------------------
SERIES* SeriesGetEx( char* fn)
{
  SERIES*      ser = NULL;
  AnsiString   ss;
  FILE*        ff;
  WLD_HDR      hdr;
  WLD_BAR      bar;



	last_name = strdup( fn);

	if( (ff = fopen( fn, "rb")) != NULL )
	{
	   fread( &hdr, sizeof(WLD_HDR), 1, ff);
	   ser           = new SERIES;
	   ser->Count    = hdr;
	   ser->pDate    = new double[hdr];
	   ser->pfOpen   = new float [hdr];
	   ser->pfHigh   = new float [hdr];
	   ser->pfLow    = new float [hdr];
	   ser->pfClose  = new float [hdr];
	   ser->pfVolume = new float [hdr];
	   ser->pfOpInt  = new float [hdr];
	   ZeroMemory( ser->pDate, sizeof(double)*ser->Count);
	   ZeroMemory( ser->pfOpen  , sizeof(float)*ser->Count);
	   ZeroMemory( ser->pfHigh  , sizeof(float)*ser->Count);
	   ZeroMemory( ser->pfLow   , sizeof(float)*ser->Count);
	   ZeroMemory( ser->pfClose , sizeof(float)*ser->Count);
	   ZeroMemory( ser->pfVolume, sizeof(float)*ser->Count);
	   ZeroMemory( ser->pfOpInt , sizeof(float)*ser->Count);

	   for( int i=0; i < hdr; i++)
	   {
		  fread( &bar, sizeof(WLD_BAR), 1, ff);

		  ser->pDate[i]    = bar.dDate;
		  ser->pfOpen[i]   = bar.fOpen;
		  ser->pfHigh[i]   = bar.fHigh;
		  ser->pfLow[i]    = bar.fLow;
		  ser->pfClose[i]  = bar.fClose;
		  ser->pfVolume[i] = bar.fVolume;
		  ser->pfOpInt[i]  = 0;
	   }

	   fclose( ff);
	}

  return ser;
}
//---------------------------------------------------------------------------
void SeriesSetEx( SERIES* data)
{
  AnsiString ss;
  FILE*      ff;
  WLD_HDR    hdr;
  WLD_BAR    bar;


	if( (ff = fopen( last_name, "wb")) != NULL )
	{
	   hdr = data->Count;
	   fwrite( &hdr, sizeof(WLD_HDR), 1, ff);

	   for( int i=0; i < data->Count; i++)
	   {
		  bar.dDate   = data->pDate[i];
		  bar.fOpen   = data->pfOpen[i];
		  bar.fHigh   = data->pfHigh[i];
		  bar.fLow	  = data->pfLow[i];
		  bar.fClose  = data->pfClose[i];
		  bar.fVolume = data->pfVolume[i];

		  fwrite( &bar, sizeof(WLD_BAR), 1, ff);
	   }

	   fclose( ff);
	}

	free( last_name);
	last_name = NULL;
}
//---------------------------------------------------------------------------
double round_int( double param)
{
  double integer, fractional;
  double Result = 0.0;


	fractional = modf( param, &integer);

	if(param > 0)
	{
	  if( fractional >= 0.5 )  Result = ceil(param);
	  else                     Result = floor(param);
	}
	else
	{
	  if( fractional <= -0.5 ) Result = floor(param);
	  else                     Result = ceil(param);
	}

	return Result;
}
//---------------------------------------------------------------------------
double mj2dt( double JD)
{
  unsigned long d,m,y;
  unsigned long h,mm,s;
  unsigned long j = JD;


	if( j == 0 ) return 0;

	j += 2415019l; // modified Julian day

	j -= 1721119l;
	y = (4l*j-1l)/146097l;
	d = (4l*j-1l-146097l*y)/4l;
	j = (4l*d+3l)/1461l;
	d = (4l*d+7l-1461l*j)/4l;
	m = (5l*d-3l)/153l;
	d = (5l*d+2l-153l*m)/5l;
	y = 100l*y+j;
	if( m < 10 ) m += 3;
	else       { m -= 9; y++; }

	JD = JD - Int(JD);

//	unsigned long t= JD * 86400;
	double tt = JD*86400.0;             // fucking float conversion!
	unsigned long t = round_int(tt);

	s  = t%60l; t/=60l;
	mm = t%60l;
	h  = t/60l;

  return TDateTime( y, m, d, h, mm, s, 0);
}
//---------------------------------------------------------------------------
double dt2mj( double dd)
{
  ushort    Year=0, Month=0, Day=0, Hour=0, Minute=0, Second=0, ms;
  TDateTime dt = dd;


	dt.DecodeDate( &Year, &Month, &Day);
	dt.DecodeTime( &Hour, &Minute, &Second, &ms);

	if( Month > 2 ) Month -= 3;
	else
	{
	   Month += 9;
	   Year--;
	}

  long   c  = Year/100l;
  long   ya = Year-100l*c;
  double jd, FracDay = Hour / 24.0 + Minute / 1440.0 + Second / 86400.0;

	jd = (146097l*c)/4l+(1461l*ya)/4l+(153l*Month+2l)/5l+Day+1721119l-2415019l;
	jd += FracDay;

   return jd;
}
//---------------------------------------------------------------------------
char* correct_name( char* inname)
{
  char* nots = "/\\:*?«<>|", *p;
  char* outname = strdup( inname);


	for( int i=0; i < strlen(nots); i++)
	{
	   do
	   {
		  p = strrchr( outname, *(nots+i));
		  if( p ) *p = '-';
	   }while( p );
	}

  return outname;
}
//---------------------------------------------------------------------------

