//---------------------------------------------------------------------------

#include <vcl.h>
#include <clipbrd.hpp>
#pragma hdrstop

#include <winsock2.h>
#include "Unit1.h"
#include "msg.h"
#include <map>
#include <deque>
#include <string>
#include <algorithm>

#include "Unit2.h"
#include "Unit3.h"
#include "Unit4.h"


bool bViewLogs;

int MAX_COUNT;
int CurrentItemIndex;

void MachineIP(char *result,const char *szHostName);
using namespace std;
map <AnsiString,AnsiString> map_tip;

void split (string text, string separators, deque<string> & words)
{
  int n = text.length();
  int start, stop;
  start = text.find_first_not_of(separators);
  while ((start >= 0) && (start < n)) {
     stop = text.find_first_of(separators, start);
     if ((stop < 0) || (stop > n)) stop = n;
     words.push_back(text.substr(start, stop - start));
     start = text.find_first_not_of(separators, stop+1);
     }
}
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma link "Placemnt"
#pragma link "RXSplit"
#pragma resource "*.dfm"
TMainForm *MainForm;

void _stdcall MyFunc(LPCTSTR str);

int begin_increment = 0;
int end_increment = 1;
int max_random_value = 1000;
int min_random_value = 1;

AnsiString port;
AnsiString ip;
AnsiString id;
int msg_count = 0;


DWORD current_message_number = 0;
int current_increment = 0;
//---------------------------------------------------------------------------
__fastcall TMainForm::TMainForm(TComponent* Owner)
        : TForm(Owner)
{
  is_connect = false;
}
//---------------------------------------------------------------------------
void __fastcall TMainForm::SpeedButton1Click(TObject *Sender)
{
  AnsiString str = ComboBoxMsg1->Text;
  if (str.Trim().IsEmpty()) return;
  if (ComboBox1->ItemIndex != 0)
  {
   React react;
   react.StringToMsg(str.c_str());
   str = react.MsgToString();
  }
  ListBox->Items->Add(str);
}
//---------------------------------------------------------------------------
void __fastcall TMainForm::SpeedButton2Click(TObject *Sender)
{
  AnsiString str = ComboBoxMsg2->Text;
  if (str.Trim().IsEmpty()) return;
  if (ComboBox2->ItemIndex != 0)
  {
   React react;
   react.StringToMsg(str.c_str());
   str = react.MsgToString();
  }
  ListBox->Items->Add(str);
}
//---------------------------------------------------------------------------
void __fastcall TMainForm::FormCreate(TObject *Sender)
{
 Slave::hWnd = Handle;
 ComboBoxMsg2->Items->Assign(ComboBoxMsg1->Items);

 map_tip["1111"] = "SLAVE";
 map_tip["900"]  = "VIDEO";
 map_tip["1012"] = "POS";
 map_tip["1030"] = "IIDK interface";
 map_tip["1003"] = "TEST NOTIFY";
 map_tip["1009"] = "ATM";

 IsConnect = false;

 Caption = "IIDK tester [Compiled on " + AnsiString(__DATE__) + "," +
 AnsiString(__TIME__) + "]";
}
//============================================================================
void __fastcall TMainForm::ConnectButtonClick(TObject *Sender)
{
  if (!slave.IsConnected())
  {
	  port = PortEdit->Text;
          ip = IpEdit->Text;
          slave.slave_id = IdEdit->Text.c_str();

	  slave.Connect(ip.c_str(),port.c_str());
          if (!slave.IsConnected())
	  {
		MessageBox(Handle,"Server connect error","Error",MB_ICONERROR);
	  }
  }
  else
  {
      slave.Disconnect();
  }
  IsConnect = slave.IsConnected();
}
//---------------------------------------------------------------------------
void __fastcall TMainForm::SendButton1Click(TObject *Sender)
{
  if (slave.IsConnected())
  {
    if (Clearrecievelogbeforesend1->Checked)
         Memo2->Clear();

    AnsiString str = ParseMsg(ComboBoxMsg1->Text);
    if (ComboBox1->ItemIndex == 0)
    {
       Event event ;
       event = str.c_str();
       slave.Send(event);

       if (Viewlogs1->Checked) Memo1->Lines->Add(str);
    }
    else
    {
       React react;
       react = str.c_str();
       slave.Send(react);

       if (Viewlogs1->Checked) Memo1->Lines->Add(react.MsgToString());
    }
  }
}
//---------------------------------------------------------------------------
void __fastcall TMainForm::FormClose(TObject *Sender, TCloseAction &Action)
{
  if (IsConnect)
  {
      Disconnect(id.c_str());
      IsConnect = false;
  }
}
//---------------------------------------------------------------------------

void __fastcall TMainForm::SendButton2Click(TObject *Sender)
{
  if (slave.IsConnected())
  {
    if (Clearrecievelogbeforesend1->Checked)
         Memo2->Clear();

    AnsiString str = ParseMsg(ComboBoxMsg2->Text);
    if (ComboBox2->ItemIndex == 0)
    {
      Event event;
      event = str.c_str();
      slave.Send(event);

      if (Viewlogs1->Checked) Memo1->Lines->Add(str);
    }
    else
    {
      React react;
      react = str.c_str();
      slave.Send(react);

      if (Viewlogs1->Checked) Memo1->Lines->Add(react.MsgToString());
    }
  }
}
//---------------------------------------------------------------------------
void __fastcall TMainForm::ListBoxKeyDown(TObject *Sender, WORD &Key,
      TShiftState Shift)
{
 if ( Key == VK_DELETE)
 {
  int i = ListBox->ItemIndex;
  if (i!= -1)
  ListBox->Items->Delete(i);
 }
}
//---------------------------------------------------------------------------

void __fastcall TMainForm::TimerTimer(TObject *Sender)
{
 //---------------------------------------------------------------------------
 if (current_increment >= end_increment && Autostopafterend1->Checked)
 {
   Timer->Enabled = false;
   Button4->Caption = "Send";
   CheckBox1->Enabled = true;
   SpeedButton5->Enabled = true;
   current_increment = 0;
   return;
 }
 //---------------------------------------------------------------------------
  if (!IsConnect || !ListBox->Items->Count)
 {
   Timer->Enabled = false;
   Button4->Caption = "Send";
   CheckBox1->Enabled = true;
   SpeedButton5->Enabled = true;
   return;
 }
 //---------------------------------------------------------------------------
 if (!CheckBox1->Checked && MAX_COUNT == 0)
 {
     Timer->Enabled = false;
     Button4->Caption = "Send";
     CheckBox1->Enabled = true;
     SpeedButton5->Enabled = true;
     return;
 }
 //---------------------------------------------------------------------------
 if (CurrentItemIndex == ListBox->Items->Count) CurrentItemIndex = 0;
 AnsiString msg;
 msg = ParseMsg(ListBox->Items->Strings[CurrentItemIndex]);
 if (bViewLogs) Memo1->Lines->Add(msg);
 if (slave.IsConnected())
 {
   Event event;
   event  = msg.c_str();
   slave.Send(event);
 }
 CurrentItemIndex++;
 MAX_COUNT -- ;
}
//---------------------------------------------------------------------------
void __fastcall TMainForm::Button4Click(TObject *Sender)
{
 if (Autoreset1->Checked)    ResetButtonClick(this);
 if (!Timer->Enabled)
 {
   Timer->Interval = StrToIntDef(PeriodEdit->Text,0);
   MAX_COUNT = StrToIntDef(CountEdit->Text,0);
   CurrentItemIndex = 0;
 }
 Timer->Enabled = !Timer->Enabled;
 Button4->Caption = (Timer->Enabled) ? "Stop":"Send";
 CheckBox1->Enabled = (Timer->Enabled) ? false : true;
 SpeedButton5->Enabled = (Timer->Enabled) ? false : true;
}
//---------------------------------------------------------------------------
void __fastcall TMainForm::CheckBox1Click(TObject *Sender)
{
 CountEdit->Enabled = !CheckBox1->Checked;
}
//---------------------------------------------------------------------------
void __fastcall TMainForm::FormStorageRestorePlacement(TObject *Sender)
{
 CountEdit->Enabled = !CheckBox1->Checked;
 PortEditChange(this);
 Viewlogs1Click(this);
}
//---------------------------------------------------------------------------
void __fastcall TMainForm::PortEditChange(TObject *Sender)
{
 LabelInfo->Caption = map_tip[PortEdit->Text];
}
//---------------------------------------------------------------------------
AnsiString __fastcall TMainForm::ParseMsg(AnsiString msg)
{
   StatusBar->SimpleText = "Сообщение " + IntToStr(current_message_number);
   current_message_number++;
   //////////////////////////////////////////////////////////////////////////
   TReplaceFlags flag;
   flag.Clear();
   flag << rfReplaceAll << rfIgnoreCase;
   //////////////////////////////////////////////////////////////////////////
   Randomize();
   int random_value = random(max_random_value);
   random_value = max(random_value,min_random_value);
   //////////////////////////////////////////////////////////////////////////
   msg = StringReplace(msg,"%random%",IntToStr(random_value),flag);
   msg = StringReplace(msg,"%datetime%",DateTimeToStr(Now()),flag);
   msg = StringReplace(msg,"%date%",DateToStr(Now()),flag);
   msg = StringReplace(msg,"%time%",TimeToStr(Now()),flag);
   msg = StringReplace(msg,"%computer_name%",ComputerName,flag);
   msg = StringReplace(msg,"\\n","\r",flag);

   if ( msg.AnsiPos("%inc%"))
   {
      if ( current_increment > end_increment)
           current_increment = begin_increment;
      if ( current_increment < begin_increment)
           current_increment = begin_increment;
      msg = StringReplace(msg,"%inc%",IntToStr(current_increment),flag);
      current_increment++;
   }
   return msg;
}
//---------------------------------------------------------------------------
void __fastcall TMainForm::SetIsConnect(bool value)
{
     is_connect = value;
     ConnectButton->Caption =  is_connect ? "Disconnect" : "Connect";
     StatusBar->SimpleText = is_connect ? "Connected!!!":"Disconnected";
     PortEdit->Enabled = !value;
     IpEdit->Enabled = !value;
     IdEdit->Enabled = !value;
     if (value)
     {
       	  Memo1->Clear();
          Memo2->Clear();
     }
}
//---------------------------------------------------------------------------
bool __fastcall TMainForm::GetIsConnect()
{
     ConnectButton->Caption =  is_connect ? "Disconnect" : "Connect";
     return is_connect;
}
//---------------------------------------------------------------------------
void __fastcall TMainForm::ListBoxDblClick(TObject *Sender)
{
  int n = ListBox->ItemIndex;
  AnsiString NewString = ListBox->Items->Strings[n];
  if (InputQuery("Edit message", "Message text", NewString))
  ListBox->Items->Strings[n] = NewString;
}
//---------------------------------------------------------------------------

void __fastcall TMainForm::Inc1Click(TObject *Sender)
{
  AnsiString NewString = IntToStr(begin_increment);
  if (InputQuery("Counter", "Init value", NewString))
  {
      begin_increment = NewString.ToInt();
      current_increment = begin_increment;
  }
}
//---------------------------------------------------------------------------
void __fastcall TMainForm::Maxrandomnumber1Click(TObject *Sender)
{
  AnsiString NewString = IntToStr(max_random_value);
  if (InputQuery("Max random number", "Enter value:", NewString))
      max_random_value = NewString.ToInt();
}
//---------------------------------------------------------------------------
void __fastcall TMainForm::Help1Click(TObject *Sender)
{
   THelpDlg *dlg = new THelpDlg(this);
   dlg->ShowModal();
   delete dlg;
}
//---------------------------------------------------------------------------
void __fastcall TMainForm::Minrandomnumber1Click(TObject *Sender)
{
  AnsiString NewString = IntToStr(min_random_value);
  if (InputQuery("Min random number", "Enter value:", NewString))
      min_random_value = NewString.ToInt();
}
//---------------------------------------------------------------------------
void __fastcall TMainForm::Incrementendnumber1Click(TObject *Sender)
{
  AnsiString NewString = IntToStr(end_increment);
  if (InputQuery("Counter", "End value", NewString))
      end_increment = NewString.ToInt();
}
//---------------------------------------------------------------------------
void __fastcall TMainForm::FormStorage1StoredValues0Save(
      TStoredValue *Sender, Variant &Value)
{
 Value = begin_increment;
}
//---------------------------------------------------------------------------
void __fastcall TMainForm::FormStorage1StoredValues0Restore(
      TStoredValue *Sender, Variant &Value)
{
  begin_increment = Value;
  current_increment = begin_increment;
}
//---------------------------------------------------------------------------

void __fastcall TMainForm::FormStorage1StoredValues1Restore(
      TStoredValue *Sender, Variant &Value)
{
 end_increment = Value;
}
//---------------------------------------------------------------------------
void __fastcall TMainForm::FormStorage1StoredValues1Save(
      TStoredValue *Sender, Variant &Value)
{
  Value = end_increment ;
}
//---------------------------------------------------------------------------
void __fastcall TMainForm::FormStorage1StoredValues2Restore(
      TStoredValue *Sender, Variant &Value)
{
  min_random_value = Value;
}
//---------------------------------------------------------------------------
void __fastcall TMainForm::FormStorage1StoredValues2Save(
      TStoredValue *Sender, Variant &Value)
{
  Value = min_random_value ;
}
//---------------------------------------------------------------------------
void __fastcall TMainForm::FormStorage1StoredValues3Save(
      TStoredValue *Sender, Variant &Value)
{
 Value = max_random_value        ;
}
//---------------------------------------------------------------------------
void __fastcall TMainForm::FormStorage1StoredValues3Restore(
      TStoredValue *Sender, Variant &Value)
{
  max_random_value = Value;
}
//---------------------------------------------------------------------------
void __fastcall TMainForm::ResetButtonClick(TObject *Sender)
{
  current_increment = begin_increment;
}
//---------------------------------------------------------------------------
void __fastcall TMainForm::ComboBoxMsg1KeyDown(TObject *Sender, WORD &Key,
      TShiftState Shift)
{
 if (Key == 13) SendButton1Click(this);   else
 if (Key == VK_INSERT) SpeedButton1Click(this);
}
//---------------------------------------------------------------------------
void __fastcall TMainForm::ComboBoxMsg2KeyDown(TObject *Sender, WORD &Key,
      TShiftState Shift)
{
 if (Key == 13) SendButton2Click(this);
 if (Key == VK_INSERT) SpeedButton2Click(this);
}
//---------------------------------------------------------------------------

void __fastcall TMainForm::SpeedButton4Click(TObject *Sender)
{
 int n = ListBox->ItemIndex;
 if ( n > 0)
 {
   AnsiString text = ListBox->Items->Strings[n-1];
   ListBox->Items->Strings[n-1] = ListBox->Items->Strings[n];
   ListBox->Items->Strings[n] = text;
   ListBox->ItemIndex = n-1;
 }
}
//---------------------------------------------------------------------------

void __fastcall TMainForm::SpeedButton3Click(TObject *Sender)
{
 int n = ListBox->ItemIndex;
 if ( n != -1 && n < (ListBox->Items->Count-1))
 {
   AnsiString text = ListBox->Items->Strings[n+1];
   ListBox->Items->Strings[n+1] = ListBox->Items->Strings[n];
   ListBox->Items->Strings[n] = text;
   ListBox->ItemIndex = n+1;
 }

}
//---------------------------------------------------------------------------

void __fastcall TMainForm::Copy1Click(TObject *Sender)
{
 Clipboard()->AsText = ListBox->Items->Text;        
}
//---------------------------------------------------------------------------

void __fastcall TMainForm::Paste1Click(TObject *Sender)
{
 ListBox->Items->Text =
 ListBox->Items->Text + Clipboard()->AsText;

}
//---------------------------------------------------------------------------

void __fastcall TMainForm::Clearall1Click(TObject *Sender)
{
 ListBox->Items->Clear();        
}
//---------------------------------------------------------------------------

void __fastcall TMainForm::Random1Click(TObject *Sender)
{
  deque<AnsiString> lst;
  for(int i = 0;i<ListBox->Items->Count;i++)
  lst.push_back(ListBox->Items->Strings[i]);
  random_shuffle(lst.begin(), lst.end());
  ListBox->Items->Clear();
  for(UINT i = 0;i<lst.size();i++)
  ListBox->Items->Add(lst[i]);
}
//---------------------------------------------------------------------------
AnsiString __fastcall TMainForm::GetComputerName()
{
 char buffer[MAX_COMPUTERNAME_LENGTH + 1];
 DWORD size = sizeof(buffer);;
 ::GetComputerName(buffer,&size);
 return AnsiString(buffer);
}
//---------------------------------------------------------------------------
void __fastcall TMainForm::FormMouseMove(TObject *Sender,
      TShiftState Shift, int X, int Y)
{
 if(Shift.Contains(ssLeft))
 {
   ReleaseCapture();
   ::SendMessage(Handle,WM_SYSCOMMAND,0xF012, 0);
 }
}
//---------------------------------------------------------------------------

void __fastcall TMainForm::ListPopupMenuPopup(TObject *Sender)
{
 Count->Caption = "Total : " + IntToStr(ListBox->Items->Count);        
}
//---------------------------------------------------------------------------

void __fastcall TMainForm::Autoreset1Click(TObject *Sender)
{
 Autoreset1->Checked = !Autoreset1->Checked;        
}
//---------------------------------------------------------------------------
void __fastcall TMainForm::OnMyMessage(TMessage &Message)
{
  deque<string> text;
  split(FilterEdit->Text.c_str(),",",text);
  if (!text.empty())
  {
     for(UINT i=0;i<text.size();i++)
     {
       if (text[i] == "*" ||
           AnsiPos(text[i].c_str(),(LPCTSTR)Message.LParam))
       {
          if (bViewLogs)Memo2->Lines->Add((LPCTSTR)Message.LParam);
          break;
       }
     }
  }
  else
  if (bViewLogs) Memo2->Lines->Add((LPCTSTR)Message.LParam);
  if ( strcmp((LPCTSTR)Message.LParam,"DISCONNECTED" ) == 0 )
  {
    if (IsConnect)
    {
       IsConnect = false;
    }
  }
  delete  [] (LPCTSTR)Message.LParam;
}
//---------------------------------------------------------------------------
void __fastcall TMainForm::IpEditKeyDown(TObject *Sender, WORD &Key,
      TShiftState Shift)
{
 if (Key == 13) ConnectButtonClick(this);
}
//---------------------------------------------------------------------------
void __fastcall TMainForm::Clearlogs1Click(TObject *Sender)
{
 Memo1->Clear();
 Memo2->Clear();
}
//---------------------------------------------------------------------------

void __fastcall TMainForm::FormStorageStoredValues5Save(
      TStoredValue *Sender, Variant &Value)
{
 Value = ComboBox1->ItemIndex;        
}
//---------------------------------------------------------------------------

void __fastcall TMainForm::FormStorageStoredValues5Restore(
      TStoredValue *Sender, Variant &Value)
{
 ComboBox1->ItemIndex = Value;        
}
//---------------------------------------------------------------------------

void __fastcall TMainForm::FormStorageStoredValues6Restore(
      TStoredValue *Sender, Variant &Value)
{
  ComboBox2->ItemIndex = Value;        
}
//---------------------------------------------------------------------------

void __fastcall TMainForm::FormStorageStoredValues6Save(
      TStoredValue *Sender, Variant &Value)
{
 Value = ComboBox2->ItemIndex;
}
//---------------------------------------------------------------------------
void __fastcall TMainForm::IPButtonClick(TObject *Sender)
{
  char lpBuffer[MAX_COMPUTERNAME_LENGTH + 1];
  DWORD size = sizeof(lpBuffer);
  ::GetComputerName(lpBuffer,&size);
  char result[MAX_PATH];
  ZeroMemory(&result,sizeof(result));
  MachineIP(result,lpBuffer) ;
  IpEdit->Text = result;
}
//---------------------------------------------------------------------------
void MachineIP(char *result,const char *szHostName)
{
 WSADATA WSAData;
 WSAStartup(MAKEWORD(1,1), &WSAData);

 char dot[6];
 int iResult;
 int i = 0;
 u_long *ppIpNO;
 u_long *pIpNO;
 HOSTENT FAR *lphostent;
 u_long ipHO;
 unsigned char binIp[4];
 int iterations = 0;

 *result = 0;

 //Lok up this host info via supplied name
 lphostent = gethostbyname(szHostName);
 if (lphostent == NULL)
 {
    WSACleanup();
    return ;
 }
 //Retreive first entry (might have multiple connects)
 do
 {
  iterations++;
  ppIpNO = (u_long *)lphostent->h_addr_list;
  if (ppIpNO+i == NULL)
  {
    WSACleanup();
    return ;
  }
  pIpNO = ((u_long *)*(ppIpNO+i));
  if (pIpNO == NULL)
  {
    WSACleanup();
    return ;
  }
  //convert back to host order, since SOCKADDR_IN expects that
  //MessageBox(NULL,"z","x",MB_OK);
  ipHO = ntohl(*pIpNO);

  binIp[0] = (BYTE)((ipHO & 0xff000000) >> 24);
  itoa(binIp[0], dot, 10);
  strcat(result,dot);
  binIp[1] = (BYTE)((ipHO & 0x00ff0000) >> 16);
  itoa(binIp[1], dot, 10);
  strcat(result, "."); strcat(result, dot);
  binIp[2] = (BYTE)((ipHO & 0x0000ff00) >> 8);
  itoa(binIp[2], dot, 10);
  strcat(result, "."); strcat(result, dot);
  binIp[3] = (BYTE)(ipHO & 0x000000ff);
  itoa(binIp[3], dot, 10);
  strcat(result,"."); strcat(result, dot);
  i++;
 } while ((pIpNO != NULL) && (iterations < 6));
 WSACleanup();
 return ;
}
//---------------------------------------------------------------------------

void __fastcall TMainForm::SpeedButton5Click(TObject *Sender)
{
 CountEdit->Text = IntToStr(ListBox->Items->Count);
 CheckBox1->Checked = false;
}
//---------------------------------------------------------------------------

void __fastcall TMainForm::Savecallbacklog1Click(TObject *Sender)
{
 if (Memo2->Lines->Count && SaveDialog->Execute())
     Memo2->Lines->SaveToFile(SaveDialog->FileName);
}
//---------------------------------------------------------------------------

void __fastcall TMainForm::Savesendlog1Click(TObject *Sender)
{
 if (Memo1->Lines->Count && SaveDialog->Execute())
     Memo1->Lines->SaveToFile(SaveDialog->FileName);
}
//---------------------------------------------------------------------------
void __fastcall TMainForm::Viewlogs1Click(TObject *Sender)
{
 bViewLogs = Viewlogs1->Checked;
}
//---------------------------------------------------------------------------




