//+------------------------------------------------------------------+
//|                                                  GavinSystem.mq4 |
//|                      Copyright © 2011, MetaQuotes Software Corp. |
//|                                        http://www.metaquotes.net |
//+------------------------------------------------------------------+
#property copyright "Copyright © 2011, MetaQuotes Software Corp."
#property link      "http://www.metaquotes.net"

#include <WinUser32.mqh>


#property indicator_chart_window

extern int SequenceMaxBars = 25;

string sequences[][3];

string signList[26];
int nbSigns;

int sequenceFound[];
int nbSequenceFound;

datetime lastBarTime;

//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int init()
  {
//---- indicators
//----
   ArrayResize(sequences, 20);
   ArrayResize(sequenceFound, 3);
   ArrayResize(signList, 26);
   
   sequences[0][0] = "SOW1";
   sequences[0][1] = "SOW104";
   sequences[0][2] = "SOW199";
   
   sequences[1][0] = "SOW26";
   sequences[1][1] = "SOW7";
   sequences[1][2] = "SOW146";
   
   sequences[2][0] = "SOW90";
   sequences[2][1] = "SOW26";
   sequences[2][2] = "SOW198";
   
   sequences[3][0] = "SOW134";
   sequences[3][1] = "SOW10";
   sequences[3][2] = "SOW134";
   
   sequences[4][0] = "SOW5";
   sequences[4][1] = "SOW2";
   sequences[4][2] = "SOW6";
   
   sequences[5][0] = "SOW89";
   sequences[5][1] = "SOW86";
   sequences[5][2] = "SOW96";
   
   sequences[6][0] = "SOW97";
   sequences[6][1] = "SOW10";
   sequences[6][2] = "SOW106";
   
   sequences[7][0] = "SOW108";
   sequences[7][1] = "SOW10";
   sequences[7][2] = "SOW193";
   
   sequences[8][0] = "SOW159";
   sequences[8][1] = "SOW101";
   sequences[8][2] = "SOW127";
   
   sequences[9][0] = "SOW21";
   sequences[9][1] = "SOW28";
   sequences[9][2] = "SOW34";
   
   
   sequences[10][0] = "SOS147";
   sequences[10][1] = "SOS134";
   sequences[10][2] = "SOS198";
   
   sequences[11][0] = "SOS137";
   sequences[11][1] = "SOS135";
   sequences[11][2] = "SOS96";
   
   sequences[12][0] = "SOS78";
   sequences[12][1] = "SOS116";
   sequences[12][2] = "SOS86";
   
   sequences[13][0] = "SOS74";
   sequences[13][1] = "SOS146";
   sequences[13][2] = "SOS199";
   
   sequences[14][0] = "SOS57";
   sequences[14][1] = "SOS134";
   sequences[14][2] = "SOS198";
   
   sequences[15][0] = "SOS45";
   sequences[15][1] = "SOS49";
   sequences[15][2] = "SOS199";
   
   sequences[16][0] = "SOS36";
   sequences[16][1] = "SOS39";
   sequences[16][2] = "SOS30";
   
   sequences[17][0] = "SOS122";
   sequences[17][1] = "SOS11";
   sequences[17][2] = "SOS81";
   
   sequences[18][0] = "SOS83";
   sequences[18][1] = "SOS134";
   sequences[18][2] = "SOS147";
   
   sequences[19][0] = "SOS99";
   sequences[19][1] = "SOS198";
   sequences[19][2] = "SOS199";
      
   nbSigns = 0;

   

   return(0);
  }
//+------------------------------------------------------------------+
//| Custom indicator deinitialization function                       |
//+------------------------------------------------------------------+
int deinit()
  {
//----
   
//----
   return(0);
  }
//+------------------------------------------------------------------+
//| Custom indicator iteration function                              |
//+------------------------------------------------------------------+
int start()
  {
   int    counted_bars=IndicatorCounted();
   
   lastBarTime = iTime(NULL, Period(), 1);
   
   ClearSignList();
   SetSignList();
   
   nbSequenceFound = 0;
   
   FindSequence();
   DisplayResult();
   
//----
   /*if (iTime(NULL, Period(), 1) > lastBarTime) {
      lastBarTime = iTime(NULL, Period(), 1);
      
      UpdateSignList();
      
      nbSequenceFound = 0;
      FindSequence();
      DisplayResult();
   }*/
//----
   return(0);
  }
//+------------------------------------------------------------------+

void ClearSignList() {
   for (int i = 0; i <= 26; i++) {
      signList[i] = "";
   }
}

void SetSignList() {
   int obj_total = ObjectsTotal();
   
   string name;
   
   for (int i = 0; i < obj_total; i++) {
      name = ObjectName(i);
      int shift = StrToInteger(GetBarShift(name));
      
      if (shift <= 25) {
         signList[shift] = GetSign(name);
      }   
   }
}

void UpdateSignList() {
   int i;
   
   for (i = 25; i > 1; i--) {
      signList[i] = signList[i-1];
   }
   
   int obj_total = ObjectsTotal();
   
   string name;
   
   for (i = 0; i < obj_total; i++) {
      name = ObjectName(i);
      int shift = StrToInteger(GetBarShift(name));
      
      if (shift == 1) {
         signList[1] = GetSign(name);
      }   
   }
}

string GetBarShift(string signName) {
   string shift;
   
   // 6 for length of "VSABAR"
   int semicolonPos = StringFind(signName, ";", 6);
   shift = StringSubstr(signName, 6, semicolonPos - 6);  
   
   return(shift);
}

string GetSign(string signName) {
   string sign;
   
   int semicolonPos = StringFind(signName, ";", 6);
   sign = StringSubstr(signName, semicolonPos + 1, StringLen(signName) - 1 - semicolonPos);
   
   return(sign);
}

void FindSequence() {
   string signListStr = ";";
   int i;
   
   for (i = 25; i > 0; i--) {
      signListStr = signListStr + signList[i] + ";";
   }
   //Alert("Base: " + signListStr);  
   
   //Alert(signListStr);
   
   for (i = 0; i < 20; i++) {
      string tmpSignList = signListStr;
      
      bool isValidSequence = true;
      
      for (int j = 0; j < 3; j++) {
         int pos = StringFind(tmpSignList, ";" + sequences[i][j] + ";", 0);
         
         if (pos != -1) {
             string str1 = StringSubstr(tmpSignList, 0, pos + 1);
             string str2 = StringSubstr(tmpSignList, pos + 1 + StringLen(sequences[i][j]));
             tmpSignList = str1 + str2;
             //Alert(tmpSignList);  
         }
         else {
            isValidSequence = false;
            break;
         } 
      }
      
      
      if (isValidSequence) {
         sequenceFound[nbSequenceFound] = i;
         //Alert("sequence: " + sequenceFound[nbSequenceFound]);
         nbSequenceFound = nbSequenceFound + 1;
      }
   }
}

void DisplayResult() {
   string message, sequence;
   
   message = "VSA Sequence(s) found on " + Period() + " period chart of " + Symbol();
   
   if (nbSequenceFound > 0) {
      for (int i = 0; i < nbSequenceFound; i++) {
         //Alert("sequence: " + sequenceFound[0]);
         sequence = sequences[sequenceFound[i]][0] + " " + sequences[sequenceFound[i]][1] + " " + sequences[sequenceFound[i]][2];
         message = message + " / " + sequence;
      }
      
      if (iTime(NULL, Period(), 1) > lastBarTime) {
         lastBarTime = iTime(NULL, Period(), 1);
         Alert(message);
         SendMail("Gavin System Alert", message);
         WriteInFile(message);
      }
   }
}

void WriteInFile(string message) {
   int handle;
   
   handle = FileOpen("GavinSystem.csv", FILE_CSV|FILE_READ|FILE_WRITE, ';');
   if (handle > 0) {
      FileSeek(handle, 0, SEEK_END);
      FileWrite(lastBarTime, message);
      FileClose(handle); 
   }
}

/*void FilterValidSigns() {
   for (int i = 25; i > 0; i--) {
      if (signList[i] == "SOW1") {
         if (!IsNextBarDown(i)) signList[i] = "";   
      }
      else if (signList[i] == "SOW104") {
         if (!(Close[i-1] < Close[i])) signList[i] = ""; 
      }
      else if (signList[i] == "SOW199") {
         if (!(Close[i-1] < Close[i])) signList[i] = ""; 
      }
      else if (signList[i] == "SOW26") {
         if (!(Close[i-1] < Close[i])) signList[i] = ""; 
      }
      else if (signList[i] == "SOW7") {
         if (!(Close[i-1] < Close[i])) signList[i] = ""; 
      }
      else if (signList[i] == "SOW146") {
         if (!(Close[i-1] < Close[i])) signList[i] = ""; 
      }
      else if (signList[i] == "SOW90") {
         if (!(Close[i-1] < Close[i])) signList[i] = ""; 
      }
      else if (signList[i] == "SOW26") {
         if (!(Close[i-1] < Close[i])) signList[i] = ""; 
      }
      else if (signList[i] == "SOW198") {
         if (!(Close[i-1] < Close[i])) signList[i] = ""; 
      }
      else if (signList[i] == "SOW134") {
         if (!(Close[i-1] < Close[i])) signList[i] = ""; 
      }
      else if (signList[i] == "SOW10") {
         if (!(Close[i-1] < Close[i])) signList[i] = ""; 
      }
      else if (signList[i] == "SOW5") {
         if (!(Close[i-1] < Close[i])) signList[i] = ""; 
      }
      else if (signList[i] == "SOW2") {
         if (!(Close[i-1] < Close[i])) signList[i] = ""; 
      }
      else if (signList[i] == "SOW6") {
         if (!(Close[i-1] < Close[i])) signList[i] = ""; 
      }
      else if (signList[i] == "SOW89") {
         if (!(Close[i-1] < Close[i])) signList[i] = ""; 
      }
      else if (signList[i] == "SOW86") {
         if (!(Close[i-1] < Close[i])) signList[i] = ""; 
      }
      else if (signList[i] == "SOW96") {
         if (!(Close[i-1] < Close[i])) signList[i] = ""; 
      }
      else if (signList[i] == "SOW97") {
         if (!(Close[i-1] < Close[i])) signList[i] = ""; 
      }
      else if (signList[i] == "SOW106") {
         if (!(Close[i-1] < Close[i])) signList[i] = ""; 
      }
      else if (signList[i] == "SOW108") {
         if (!(Close[i-1] < Close[i])) signList[i] = ""; 
      }
      else if (signList[i] == "SOW193") {
         if (!(Close[i-1] < Close[i])) signList[i] = ""; 
      }
      else if (signList[i] == "SOW159") {
         if (!(Close[i-1] < Close[i])) signList[i] = ""; 
      }
      else if (signList[i] == "SOW101") {
         if (!(Close[i-1] < Close[i])) signList[i] = ""; 
      }
      else if (signList[i] == "SOW127") {
         if (!(Close[i-1] < Close[i])) signList[i] = ""; 
      }
      else if (signList[i] == "SOW21") {
         if (!(Close[i-1] < Close[i])) signList[i] = ""; 
      }
      else if (signList[i] == "SOW28") {
         if (!(Close[i-1] < Close[i])) signList[i] = ""; 
      }
      else if (signList[i] == "SOW34") {
         if (!(Close[i-1] < Close[i])) signList[i] = ""; 
      }
      else if (signList[i] == "SOS147") {
         if (!(Close[i-1] < Close[i])) signList[i] = ""; 
      }
      else if (signList[i] == "SOS134") {
         if (!(Close[i-1] < Close[i])) signList[i] = ""; 
      }
      else if (signList[i] == "SOS198") {
         if (!(Close[i-1] < Close[i])) signList[i] = ""; 
      }
      else if (signList[i] == "SOS137") {
         if (!(Close[i-1] < Close[i])) signList[i] = ""; 
      }
      else if (signList[i] == "SOS135") {
         if (!(Close[i-1] < Close[i])) signList[i] = ""; 
      }
      else if (signList[i] == "SOS96") {
         if (!(Close[i-1] < Close[i])) signList[i] = ""; 
      }
      else if (signList[i] == "SOS78") {
         if (!(Close[i-1] < Close[i])) signList[i] = ""; 
      }
      else if (signList[i] == "SOS116") {
         if (!(Close[i-1] < Close[i])) signList[i] = ""; 
      }
      else if (signList[i] == "SOS86") {
         if (!(Close[i-1] < Close[i])) signList[i] = ""; 
      }
      else if (signList[i] == "SOS74") {
         if (!(Close[i-1] < Close[i])) signList[i] = ""; 
      }
      else if (signList[i] == "SOS146") {
         if (!(Close[i-1] < Close[i])) signList[i] = ""; 
      }
      else if (signList[i] == "SOS199") {
         if (!(Close[i-1] < Close[i])) signList[i] = ""; 
      }
      else if (signList[i] == "SOS57") {
         if (!(Close[i-1] < Close[i])) signList[i] = ""; 
      }
      else if (signList[i] == "SOS45") {
         if (!(Close[i-1] < Close[i])) signList[i] = ""; 
      }
      else if (signList[i] == "SOS49") {
         if (!(Close[i-1] < Close[i])) signList[i] = ""; 
      }
      else if (signList[i] == "SOS36") {
         if (!(Close[i-1] < Close[i])) signList[i] = ""; 
      }
      else if (signList[i] == "SOS29") {
         if (!(Close[i-1] < Close[i])) signList[i] = ""; 
      }
      else if (signList[i] == "SOS30") {
         if (!(Close[i-1] < Close[i])) signList[i] = ""; 
      }
      else if (signList[i] == "SOS122") {
         if (!(Close[i-1] < Close[i])) signList[i] = ""; 
      }
      else if (signList[i] == "SOS11") {
         if (!(Close[i-1] < Close[i])) signList[i] = ""; 
      }
      else if (signList[i] == "SOS81") {
         if (!(Close[i-1] < Close[i])) signList[i] = ""; 
      }
      else if (signList[i] == "SOS83") {
         if (!(Close[i-1] < Close[i])) signList[i] = ""; 
      }
      else if (signList[i] == "SOS147") {
         if (!(Close[i-1] < Close[i])) signList[i] = ""; 
      }
      else if (signList[i] == "SOS99") {
         if (!(Close[i-1] < Close[i])) signList[i] = ""; 
      }
   }
}*/

bool IsNextBarDown(int shift) {
   bool isNextBarDown = Close[shift-1] < Close[shift];
   return(isNextBarDown);   
}

bool IsNextBarUp(int shift) {
   bool isNextBarUp = Close[shift-1] > Close[shift];
   return(isNextBarUp);   
}

