//+------------------------------------------------------------------+
//|                                                 Trade_Sender.mq4 |
//|                                                    Kenny Hubbard |
//|                                       http://www.compu-forex.com |
//+------------------------------------------------------------------+
#property copyright "Kenny Hubbard"
#property link      "http://www.compu-forex.com"

extern bool       Show_Screen_FeedBack = true;
extern bool       Show_Account_Detail  = true;
extern bool       Show_Equity          = true;
extern string     Note1                = "----Trades to Show---";
extern bool       Show_Market          = true;
extern bool       Show_Pending         = true;
extern bool       Show_Closed          = true;
extern bool       Show_Deleted         = true;
extern bool       Expanded_Order_Info  = true;
extern bool       Show_Trade_Result    = true;
extern bool       Show_Profit          = true;
extern int        Mail_Retry           = 3;

int 
   Order_State_Prev[][2],
   Order_State_New[][2],
   D_Factor = 1;
   
bool  
   First_Run = true;
   
string
   Mail_Header,
   Extra_FeedBack = "";

//+------------------------------------------------------------------+
//| expert initialization function                                   |
//+------------------------------------------------------------------+
int init()
{ 
   if (Digits == 3|| Digits == 5)D_Factor = 10;
   if (Show_Account_Detail)Mail_Header = StringConcatenate(AccountCompany() , " Trade Alert : Acc No " , AccountNumber() , " " , AccountName());
   else Mail_Header = "Trade Alert";
   if (!Show_Trade_Result)Show_Profit = false;
   return(0);
}
//+------------------------------------------------------------------+
//| expert deinitialization function                                 |
//+------------------------------------------------------------------+
int deinit()
  {
//----
   Comment("");
//----
   return(0);
  }
//+------------------------------------------------------------------+
//| expert start function                                            |
//+------------------------------------------------------------------+
int start()
{
double
   Order_Pips,
   My_Profit;
string
   Email_Text,
   Order_text;
int 
   lmail_retry = Mail_Retry;
//----
   if (OrdersTotal() == 0){
      if (First_Run){
         ArrayResize(Order_State_Prev,MathMax(ArraySize(Order_State_New)/2,0));
         First_Run = false;
      }
      Extra_FeedBack = "No Orders Open at Present" + "\n";
   }
   ArrayResize(Order_State_New,MathMax(OrdersTotal(),0));            //make the order array the same size as the number of orders
//=============================================================== load the array with the order details    
   for(int i=0;i<OrdersTotal();i++){
      if(OrderSelect(i,SELECT_BY_POS,MODE_TRADES)){
         Order_State_New[i][0] = OrderType();
         Order_State_New[i][1] = OrderTicket();
      }
   }
//=============================================================== check if this is the first run of the EA   
   if(First_Run){    
      ArrayResize(Order_State_Prev,MathMax(ArraySize(Order_State_New)/2,1));
      ArrayCopy(Order_State_Prev,Order_State_New,0,0,WHOLE_ARRAY);//copy the array for next tick comparison
      First_Run = false;                                          //first run is done, so set flag false for the future
      return(0);
   }
//=============================================================== the arrays are loaded now we can compare to find changes      
   if (OrdersTotal() == ArraySize(Order_State_Prev)/2){
      if (Show_Screen_FeedBack)User_FeedBack(Extra_FeedBack);
      if (StringLen(Extra_FeedBack) > 500)Extra_FeedBack = "";
      return(0);     //nothing has changed so move back to the beginning
   }
//***************************************************************

//+----------------------------------------------------------------------------------------------------------+
//|At this point there is a change in the new array compared to the previous array.........we have 2 options |                                                                |
//+----------------------------------------------------------------------------------------------------------+


//****************** OPTION 1 New Order Added *******************
//===============================================================
   if (OrdersTotal() > ArraySize(Order_State_Prev)/2){           //more orders than before....lets search the open order tickets and compare with old tickets
      for(i=0;i<OrdersTotal();i++){
         OrderSelect(i,SELECT_BY_POS,MODE_TRADES);
         for(int i_2=0;i_2<ArraySize(Order_State_Prev)/2;i_2++){
            if(OrderTicket() == Order_State_Prev[i_2][1])continue; //this order is in the previous array so its not new
         }
      }
//============================================================== at this point we have found the new ticket by elimination so lets alert the user
      Email_Text = OrderSymbol() + Get_Order_Text(OrderType()) + " @ PRICE " + DoubleToStr(OrderOpenPrice(),Digits)+ ", SL " + DoubleToStr(OrderStopLoss(),Digits) +
                                  ", TP " + DoubleToStr(OrderTakeProfit(),Digits);  
      if (Expanded_Order_Info)Email_Text = "Ticket #" + OrderTicket() + " " + Email_Text + " @ " + TimeToStr(OrderOpenTime(),TIME_DATE|TIME_MINUTES);  
      while (lmail_retry > 0){                              
         if (Show_Market && OrderType() <= 1)SendMail(Mail_Header, Email_Text);
         if (Show_Pending && OrderType() >= 2 && OrderType() <= 5)SendMail(Mail_Header, Email_Text);
         if(GetLastError() == 4061)Mail_Retry--;
         else break;
      }
      Print(Mail_Header, Email_Text);
      if (GetLastError() == 4061)Alert("Error Sending Email, please check your settings and service provider");
      else{
         Extra_FeedBack = StringConcatenate(Extra_FeedBack, " New Order Ticket #", OrderTicket(), " email sent.\n");
         if (Show_Screen_FeedBack)User_FeedBack(Extra_FeedBack);
      }
   }
   
//************ OPTION 2 An Order is closed or deleted *****************
//=====================================================================
   if (OrdersTotal() < ArraySize(Order_State_Prev)/2){           //fewer orders than before....lets search the closed order tickets and compare with old tickets
      for(i=0;i<OrdersHistoryTotal();i++){
         if(OrderSelect(i,SELECT_BY_POS,MODE_HISTORY)){
            for(i_2=0;i_2<ArraySize(Order_State_Prev)/2;i_2++){
               if(OrderTicket() != Order_State_Prev[i_2][1])continue;
               else{
                  switch(OrderType()){
                     case OP_BUY  : Order_Pips = (OrderClosePrice() - OrderOpenPrice())/Point/D_Factor;
                                    Email_Text = StringConcatenate(OrderSymbol(), " Buy Order Closed");
                                    break;
                     case OP_SELL : Order_Pips = (OrderOpenPrice() - OrderClosePrice())/Point/D_Factor;
                                    Email_Text = StringConcatenate(OrderSymbol(), " Sell Order Closed");
                                    break;
                     default      : Email_Text = StringConcatenate(Symbol(), Get_Order_Text(OrderType()));
                                    break;
                  }//switch
                  if (Expanded_Order_Info)Email_Text = "Ticket #" + OrderTicket() + " " + Email_Text + " @ " + TimeToStr(OrderOpenTime(),TIME_DATE|TIME_MINUTES); 
                  if (Show_Trade_Result && OrderType() <= 1)Email_Text = Email_Text + "\n" + "Result = " + DoubleToStr(Order_Pips,1) + " Pips.";
                  if (Show_Profit){
                     My_Profit = OrderProfit() - OrderCommission() - OrderSwap();
                     Email_Text = "\n" + Email_Text + " Net Profit/Loss = " + AccountCurrency() + " " + DoubleToStr(My_Profit,2);
                  }
                  if (Show_Equity)Email_Text = "\n" + Email_Text + "\n" + "Your Balance is " + DoubleToStr(AccountBalance(),2) + "/Equity " + DoubleToStr(AccountEquity(),2);
                  while (lmail_retry > 0){
                     if (Show_Closed && OrderType() <= 1)SendMail(Mail_Header, Email_Text);
                     if (Show_Deleted && OrderType() >= 2 && OrderType() <= 5)SendMail(Mail_Header, Email_Text);
                     if(GetLastError() == 4061)Mail_Retry--;
                     else break;
                  }
                  if (GetLastError() == 4061)Alert("Error Sending Email, please check your settings and service provider");
                  else{
                     Extra_FeedBack = StringConcatenate(Extra_FeedBack, " Closed or Deleted Ticket #", OrderTicket(), " email sent.\n");
                     if (Show_Screen_FeedBack)User_FeedBack(Extra_FeedBack);
                  }
                  Print(Mail_Header, Email_Text);
                  break;
               }//else
            }//for(i_2=0;i_2<ArraySize(Order_State_Prev)/2;i_2++){
         }//if(OrderSelect(i,SELECT_BY_POS,MODE_HISTORY)){
      }//for(i=0;i<OrdersHistoryTotal();i++){
   }
   ArrayResize(Order_State_Prev,MathMax(OrdersTotal(),0));
   if (OrdersTotal() == 0)return(0);
   ArrayCopy(Order_State_Prev,Order_State_New,0,0,WHOLE_ARRAY);//copy the array for future comparison
//----
   return(0);
}
//+------------------------------------------------------------------+
string Get_Order_Text(int lOrdertype)
{
   switch (lOrdertype){
      case OP_BUY       :return(" Buy Order");
      case OP_SELL      :return(" Sell Order");
      case OP_BUYLIMIT  :return(" Buy Limit Order");
      case OP_BUYSTOP   :return(" Buy Stop Order");
      case OP_SELLLIMIT :return(" Sell Limit Order");
      case OP_SELLSTOP  :return(" Sell Stop Order");
      default           :return(" Unidentified Order Type");
   }
}
//+------------------------------------------------------------------+
string Bool_to_Text(int lbool)
{
   if (lbool == true)return("True");
   else return("False");
}
//+------------------------------------------------------------------+
void User_FeedBack(string l_extra_text)
{
string 
   cmt = "Trade Sender Information" + "\n";
   cmt = cmt + "------------------------------------" + "\n";
   cmt = cmt + "Show_Account_Detail = " +  Bool_to_Text(Show_Account_Detail) + "\n";
   cmt = cmt + "Show_Equity             = " +  Bool_to_Text(Show_Equity) + "\n";
   cmt = cmt + "Show_Market            = " +  Bool_to_Text(Show_Market) + "\n";
   cmt = cmt + "Show_Pending          = " +  Bool_to_Text(Show_Pending) + "\n";
   cmt = cmt + "Show_Closed           = " +  Bool_to_Text(Show_Closed) + "\n";
   cmt = cmt + "Show_Deleted          = " +  Bool_to_Text(Show_Deleted) + "\n";
   cmt = cmt + "Expanded_Order_Info   = " +  Bool_to_Text(Expanded_Order_Info) + "\n";
   cmt = cmt + "Show_Trade_Result   = " +  Bool_to_Text(Show_Trade_Result) + "\n";
   cmt = cmt + "Show_Profit             = " +  Bool_to_Text(Show_Profit) + "\n";
   cmt = cmt + "------------------------------------" + "\n";
   cmt = cmt + l_extra_text + "\n";
   Comment(cmt);
}

