#ifndef TF_INDICATORS_CALENDAR_CACHE_MQH
#define TF_INDICATORS_CALENDAR_CACHE_MQH

struct TF_CalendarItem
  {
   ulong value_id;
   ulong event_id;
   datetime event_time;
   string currency;
   string name;
   int importance;
  };

void TF_CalendarAppend(TF_CalendarItem &items[],const TF_CalendarItem &item)
  {
   int size=ArraySize(items);
   ArrayResize(items,size+1);
   items[size]=item;
  }

void TF_CalendarSort(TF_CalendarItem &items[])
  {
   int size=ArraySize(items);
   for(int i=1;i<size;i++)
     {
      TF_CalendarItem key=items[i];
      int j=i-1;
      while(j>=0 && items[j].event_time>key.event_time)
        {
         items[j+1]=items[j];
         j--;
        }
      items[j+1]=key;
     }
  }

bool TF_LoadLiveCalendarCurrency(const string currency,const datetime from_time,const datetime to_time,
                                 const int minimum_importance,TF_CalendarItem &items[],int &error_code)
  {
   MqlCalendarValue values[];
   ResetLastError();
   int count=CalendarValueHistory(values,from_time,to_time,NULL,currency);
   if(count<0)
     {
      error_code=GetLastError();
      return(false);
     }
   for(int i=0;i<count;i++)
     {
      MqlCalendarEvent event;
      ResetLastError();
      if(!CalendarEventById(values[i].event_id,event))
        {
         error_code=GetLastError();
         return(false);
        }
      if((int)event.importance<minimum_importance) continue;
      TF_CalendarItem item;
      item.value_id=values[i].id;
      item.event_id=values[i].event_id;
      item.event_time=values[i].time;
      item.currency=currency;
      item.name=event.name;
      item.importance=(int)event.importance;
      TF_CalendarAppend(items,item);
     }
   error_code=0;
   return(true);
  }

bool TF_SaveCalendarCache(const string filename,const TF_CalendarItem &items[],const datetime last_success)
  {
   int handle=FileOpen(filename,FILE_WRITE|FILE_CSV|FILE_ANSI,',');
   if(handle==INVALID_HANDLE) return(false);
   FileWrite(handle,"TF_CALENDAR_CACHE_V1",(long)last_success,"","","","");
   for(int i=0;i<ArraySize(items);i++)
      FileWrite(handle,(long)items[i].value_id,(long)items[i].event_id,(long)items[i].event_time,
                items[i].currency,items[i].importance,items[i].name);
   FileClose(handle);
   return(true);
  }

bool TF_LoadCalendarCache(const string filename,TF_CalendarItem &items[],datetime &last_success)
  {
   int handle=FileOpen(filename,FILE_READ|FILE_CSV|FILE_ANSI|FILE_COMMON,',');
   if(handle==INVALID_HANDLE) return(false);
   ArrayResize(items,0);
   string marker=FileReadString(handle);
   if(marker!="TF_CALENDAR_CACHE_V1") { FileClose(handle); return(false); }
   last_success=(datetime)(long)FileReadNumber(handle);
   for(int skip=0;skip<4 && !FileIsEnding(handle);skip++) FileReadString(handle);
   while(!FileIsEnding(handle))
     {
      TF_CalendarItem item;
      item.value_id=(ulong)FileReadNumber(handle);
      if(FileIsEnding(handle) && item.value_id==0) break;
      item.event_id=(ulong)FileReadNumber(handle);
      item.event_time=(datetime)(long)FileReadNumber(handle);
      item.currency=FileReadString(handle);
      item.importance=(int)FileReadNumber(handle);
      item.name=FileReadString(handle);
      TF_CalendarAppend(items,item);
     }
   FileClose(handle);
   TF_CalendarSort(items);
   return(true);
  }

bool TF_LoadCalendarFixture(const string filename,TF_CalendarItem &items[],datetime &fixture_time)
  {
   int handle=FileOpen(filename,FILE_READ|FILE_CSV|FILE_ANSI,',');
   if(handle==INVALID_HANDLE) return(false);
   ArrayResize(items,0);
   string first=FileReadString(handle);
   if(first!="value_id") { FileClose(handle); return(false); }
   for(int skip=0;skip<4 && !FileIsEnding(handle);skip++) FileReadString(handle);
   fixture_time=0;
   while(!FileIsEnding(handle))
     {
      TF_CalendarItem item;
      item.value_id=(ulong)FileReadNumber(handle);
      if(FileIsEnding(handle) && item.value_id==0) break;
      item.event_id=(ulong)FileReadNumber(handle);
      item.event_time=StringToTime(FileReadString(handle));
      item.currency=FileReadString(handle);
      item.importance=(int)FileReadNumber(handle);
      item.name=FileReadString(handle);
      TF_CalendarAppend(items,item);
      if(item.event_time>fixture_time) fixture_time=item.event_time;
     }
   FileClose(handle);
   TF_CalendarSort(items);
   return(ArraySize(items)>0);
  }

#endif
