//---------------------------------------------------------------------------
#include <windows.h>
#include <vcl.h>
#include <stdio.h>
#include <fstream.h>
#pragma hdrstop
#include "Main.h"
#include "misc.hpp"
//#include "about.hpp"
#include "fruc.h"
//#include "gomsolv.h"
#include "gsolv_c.h"
#include "PrgForm.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
//TMainForm *MainForm;
AnsiString WorkDir;

//---------------------------------------------------------------------------
__fastcall TMainForm::TMainForm(TComponent* Owner)
    : TForm(Owner)
{
}
//---------------------------------------------------------------------------

void __fastcall TMainForm::Button1Click(TObject *Sender)
{
 int alg;
 int i,j;
 TFruc A;
 PSimplexTable st;
 PBoolVector Z;

 st = new TFruc[(n+1)*(n+m+3)+1];
 Z = new bool[(n+m)*(n+1)];

// try{
  for( i=0; i<n; i++ )Z[i] = (clbIntVar->Checked[i]||clbIntVar->State[i] == cbGrayed);
  for( i=n; i<(n+m)*(n+1); i++ )Z[i] = false;
  for (i=n+2;i<n+m;i++)
   Z[i]=true;
  Z[5]=false; Z[6]=false;
  for( i=1; i<=n; i++ )
  {
   if( Q[n] == 0 /*min*/)st[i].x = Q[i-1];else st[i].x = -Q[i-1];
   st[i*(n+2)].x = -1;
  }

  for( i=n+1; i<n+m+1; i++ )
  {
//   Z[i-1]=true;
   for( j=1; j<n+1; j++ )
    if( K[(i-n-1)*(n+2)+n+1] == 0 /*<*/ )
        st[i*(n+1)+j].x = K[(i-n-1)*(n+2)+j-1]; else
        st[i*(n+1)+j].x = -K[(i-n-1)*(n+2)+j-1];

   if( K[(i-n-1)*(n+2)+n+1] == 0 /*<*/ )
       st[i*(n+1)].x = K[(i-n-1)*(n+2)+n]; else
       st[i*(n+1)].x = -K[(i-n-1)*(n+2)+n];
  }

  alg = cbAlg->ItemIndex + 1;
  mRes->Lines->Clear();
  ProgressForm = new TProgressForm( Application );
  ProgressForm->Show();
  bbSolve->Enabled = false;
  solve = new TSolveThread( st, Z, n+m, n, alg, cbEachStep->Checked, mRes->Lines);
  solve->OnTerminate = SolveEnd;
  solve->Resume();
  /*try{
   gomory( st, Z, n+m, n, alg, cbEachStep->Checked, mRes->Lines );
   tsResults->TabVisible = true;
   PageControl->ActivePage = tsResults;
  }
  catch (Exception &e)
  {
   MessageDlg( e.Message, mtError, TMsgDlgButtons() << mbOK, 0 );
  }*/
 //}
// __finally
// {
//  delete[] st;
//  delete[] Z;
// }
}
//---------------------------------------------------------------------------

void __fastcall TMainForm::SolveEnd(TObject *Sender)
{
 ProgressForm->Hide();
 bbSolve->Enabled = true;

 if( Sender != NULL )
 {
  delete ProgressForm;
  if( !((TSolveThread *)Sender)->HaveError )
  {
   tsResults->TabVisible = true;
   PageControl->ActivePage = tsResults;
   TabSheet1->TabVisible = true;
  }else
    MessageDlg( ((TSolveThread *)Sender)->Msg, mtError, TMsgDlgButtons() << mbOK, 0 );
 }else MessageDlg( "Процесс решения прерван пользователем.", mtInformation, TMsgDlgButtons() << mbOK, 0 );
}

const
 char Signs[2] = {'<=','>='};

RECT RectToRECT( TRect &r )
{
 RECT r2;
 r2.top = r.Top;
 r2.bottom = r.Bottom;
 r2.left = r.Left;
 r2.right = r.Right;
 return r2;
}

void __fastcall TMainForm::dwgInput2DrawCell(TObject *Sender, int Col,
      int Row, TRect &Rect, TGridDrawState State)
{
 int Flag;
 char s[10];

 dwgInput2->Canvas->Brush->Color = clBtnFace;
 if( Col < n*2 )
 {
  if( Col%2 != 0 )
  {
   DrawEdge(dwgInput2->Canvas->Handle, &RectToRECT(Rect), EDGE_RAISED, BF_RECT|BF_MIDDLE);
   Rect.Top += 2;
   Rect.Bottom -= 2;
   Rect.Left += 2;
   Rect.Right -= 2;
   sprintf( s, "x%d", Col/2+1 );
   WriteText( dwgInput2->Canvas, Rect, 2, 1, s, taCenter );
  }else
   WriteText( dwgInput2->Canvas, Rect, 2, 3, IntToStr(K[Row*(n+2)+Col/2]), taRightJustify );
 }else if( Col == n*2 )
 {
  if( PressedK && ( Row == PressedRow ) )Flag = BF_FLAT;else Flag = 0;
  DrawEdge(dwgInput2->Canvas->Handle, &RectToRECT(Rect), EDGE_RAISED, BF_RECT|BF_MIDDLE|Flag);
  Rect.Top += 2;
  Rect.Bottom -= 2;
  Rect.Left += 2;
  Rect.Right -= 2;
  WriteText( dwgInput2->Canvas, Rect, 2, 1, Signs[K[Row*(n+2)+n+1]], taCenter );
 }else
  WriteText( dwgInput2->Canvas, Rect, 2, 3, IntToStr(K[Row*(n+2)+n]), taRightJustify );
 if( State.Contains( gdFocused ) )dwgInput2->Canvas->DrawFocusRect( Rect );
}
//---------------------------------------------------------------------------

void __fastcall TMainForm::dwgInput2GetEditText(TObject *Sender, int ACol,
      int ARow, AnsiString &Value)
{
 if( ACol > 2*n )Value = IntToStr( K[ARow*(n+2)+n] );else
  Value = IntToStr( K[ARow*(n+2)+ACol/2] );
 tsResults->TabVisible = false;
 TabSheet1->TabVisible = false;
}
//---------------------------------------------------------------------------

void __fastcall TMainForm::dwgInput2SelectCell(TObject *Sender, int Col,
      int Row, bool &CanSelect)
{
 CanSelect = ((Col%2 == 0)&&(Col < 2*n))||(Col == 2*n+1);
}
//---------------------------------------------------------------------------

void __fastcall TMainForm::dwgInput2SetEditText(TObject *Sender, int ACol,
      int ARow, const AnsiString Value)
{
 try{
  if( ACol > 2*n )
   K[ARow*(n+2)+n] = StrToInt(Value);else
   K[ARow*(n+2)+ACol/2] = StrToInt(Value);
  tsResults->TabVisible = false;
  TabSheet1->TabVisible = false;
  }
 catch(...){}
}
//---------------------------------------------------------------------------

void __fastcall TMainForm::dwgInput2MouseDown(TObject *Sender,
      TMouseButton Button, TShiftState Shift, int X, int Y)
{
 int ACol,ARow;
 TGridDrawState s;

 dwgInput2->MouseToCell( X, Y, ACol, ARow );
 if( ACol == 2*n )
 {
  Draging = true;
  PressedRow = ARow;
  PressedK = true;
  s << gdSelected;
  dwgInput2DrawCell( dwgInput2, 2*n, PressedRow, dwgInput2->CellRect(2*n,PressedRow), s );
  //dwgInput2->Invalidate;
 }
}
//---------------------------------------------------------------------------

void __fastcall TMainForm::dwgInput2MouseMove(TObject *Sender,
      TShiftState Shift, int X, int Y)
{
 int ACol,ARow;
 Boolean OldPress;

 if( Draging )
 {
  dwgInput2->MouseToCell( X, Y, ACol, ARow );
  OldPress = PressedK;
  PressedK = (ARow == PressedRow);
  if( OldPress != PressedK )
  {
   TGridDrawState s;
   s << gdSelected;
   dwgInput2DrawCell( dwgInput2, 2*n, PressedRow, dwgInput2->CellRect(2*n,PressedRow), s );
  }
 }
}

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

void __fastcall TMainForm::dwgInput2MouseUp(TObject *Sender,
      TMouseButton Button, TShiftState Shift, int X, int Y)
{
 int ACol,ARow;
 TGridDrawState s;

 if( Draging )
 {
  Draging = false;
  dwgInput2->MouseToCell( X, Y, ACol, ARow );
  if(( ACol == 2*n )&&( ARow == PressedRow )){
   K[ARow*(n+2)+n+1] = 1 - K[ARow*(n+2)+n+1];
   tsResults->TabVisible = false;
  }
  PressedK = false;
  //dwgInput2->Invalidate;
  s << gdSelected;
  dwgInput2DrawCell( dwgInput2, 2*n, PressedRow, dwgInput2->CellRect(2*n,PressedRow), s );
 }
}

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

const
 char MinMax[2][6] = {"->min","->max"};

void __fastcall TMainForm::dwgInput1DrawCell(TObject *Sender, int Col,
      int Row, TRect &Rect, TGridDrawState State)
{
 int Flag;
 char s[10];

 dwgInput1->Canvas->Brush->Color = clBtnFace;
 if( Col < n*2 )
 {
  if( Col%2 != 0 )
  {
   DrawEdge(dwgInput1->Canvas->Handle, &RectToRECT(Rect), EDGE_RAISED, BF_RECT|BF_MIDDLE);
   Rect.Top += 2;
   Rect.Bottom -= 2;
   Rect.Left += 2;
   Rect.Right -= 2;
   sprintf( s, "x%d", Col/2+1 );
   WriteText( dwgInput1->Canvas, Rect, 2, 1, s, taCenter );
  }else
   WriteText( dwgInput1->Canvas, Rect, 2, 3, IntToStr(Q[Col/2]), taRightJustify );
 }else if( Col == n*2 )
 {
  if( PressedQ && ( Row == PressedRow ) )Flag = BF_FLAT;else Flag = 0;
  DrawEdge(dwgInput1->Canvas->Handle, &RectToRECT(Rect), EDGE_RAISED, BF_RECT|BF_MIDDLE|Flag);
  Rect.Top += 2;
  Rect.Bottom -= 2;
  Rect.Left += 2;
  Rect.Right -= 2;
  WriteText( dwgInput1->Canvas, Rect, 2, 1, MinMax[Q[n]], taCenter );
 }
 if( State.Contains( gdFocused ) )dwgInput1->Canvas->DrawFocusRect( Rect );
}

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

void __fastcall TMainForm::dwgInput1GetEditText(TObject *Sender, int ACol,
      int ARow, AnsiString &Value)
{
 if( ACol < 2*n )Value = IntToStr( Q[ACol/2] );
 tsResults->TabVisible = false;
 TabSheet1->TabVisible = false;
}
//---------------------------------------------------------------------------

void __fastcall TMainForm::dwgInput1SelectCell(TObject *Sender, int Col,
      int Row, bool &CanSelect)
{
 CanSelect = ((Col%2 == 0)&&(Col < 2*n));
}
//---------------------------------------------------------------------------

void __fastcall TMainForm::dwgInput1SetEditText(TObject *Sender, int ACol,
      int ARow, const AnsiString Value)
{
 try{
  if( ACol < 2*n )
   Q[ACol/2] = StrToInt(Value);
  tsResults->TabVisible = false;
  TabSheet1->TabVisible = false;
  }
 catch(...){}
}
//---------------------------------------------------------------------------

void __fastcall TMainForm::dwgInput1MouseDown(TObject *Sender,
      TMouseButton Button, TShiftState Shift, int X, int Y)
{
 int ACol,ARow;
 TGridDrawState s;

 dwgInput1->MouseToCell( X, Y, ACol, ARow );
 if( ACol == 2*n )
 {
  Draging = true;
  PressedRow = ARow;
  PressedQ = true;
  s << gdSelected;
  dwgInput1DrawCell( dwgInput1, 2*n, PressedRow, dwgInput1->CellRect(2*n,PressedRow), s );
  //dwgInput1->Invalidate;
 }
}
//---------------------------------------------------------------------------

void __fastcall TMainForm::dwgInput1MouseMove(TObject *Sender,
      TShiftState Shift, int X, int Y)
{
 int ACol,ARow;
 Boolean OldPress;

 if( Draging )
 {
  dwgInput1->MouseToCell( X, Y, ACol, ARow );
  OldPress = PressedQ;
  PressedQ = (ARow == PressedRow);
  if( OldPress != PressedQ )
  {
   TGridDrawState s;
   s << gdSelected;
   dwgInput1DrawCell( dwgInput1, 2*n, PressedRow, dwgInput1->CellRect(2*n,PressedRow), s );
  }
 }
}

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

void __fastcall TMainForm::dwgInput1MouseUp(TObject *Sender,
      TMouseButton Button, TShiftState Shift, int X, int Y)
{
 int ACol,ARow;
 TGridDrawState s;

 if( Draging )
 {
  Draging = false;
  dwgInput1->MouseToCell( X, Y, ACol, ARow );
  if(( ACol == 2*n )&&( ARow == PressedRow )){
   Q[n] = 1 - Q[n];
   tsResults->TabVisible = false;
   TabSheet1->TabVisible = false;
  } 
  PressedQ = false;
  //dwgInput1->Invalidate;
  s << gdSelected;
  dwgInput1DrawCell( dwgInput1, 2*n, PressedRow, dwgInput1->CellRect(2*n,PressedRow), s );
 }
}

// --------------------------------------------------------------------------
void TMainForm::AllocArrays()
{
 int i;

 if( K != NULL )delete[] K;
 if( Q != NULL )delete[] Q;

 K = new int[(n+2)*m];
 Q = new int[n+1];

 for( i = 0; i < (n+2)*m; i++ )K[i] = 0;
 for( i = 0; i < n+1; i++ )Q[i] = 0;

 dwgInput1->ColCount = n*2+1;
 dwgInput1->Repaint();
 dwgInput2->ColCount = (n+1)*2;
 dwgInput2->RowCount = m;
 dwgInput2->Repaint();
}

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

void __fastcall TMainForm::FormCreate(TObject *Sender)
{
 OpenDialog->InitialDir = WorkDir;
 SaveDialog->InitialDir = WorkDir;

 K = NULL;
 Q = NULL;
 m = 2;
 n = 2;
 AllocArrays();

 cbAlg->ItemIndex = 0;
 UpdateIntVarList();
}

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

void __fastcall TMainForm::FormDestroy(TObject *Sender)
{
 if( K != NULL )delete[] K;
 if( Q != NULL )delete[] Q;
}


void __fastcall TMainForm::seExit(TObject *Sender)
{
 int n1, m1;
 try{
  n1 = StrToInt(edVar->Text);
  m1 = StrToInt(edLim->Text);
  UpdateIntVarList();
 }
 catch(Exception &e)
 {
  MessageDlg( e.Message, mtError, TMsgDlgButtons() << mbOK, 0 );
  ((TEdit *)(Sender))->SetFocus();
 }
 if( (n1!=n) || (m1!=m) ){
  n = n1;
  m = m1;
  tsResults->TabVisible = false;
  TabSheet1->TabVisible = false;
  AllocArrays();
 }
}
//---------------------------------------------------------------------------

void __fastcall TMainForm::seKeyDown(TObject *Sender, WORD &Key,
      TShiftState Shift)
{
 if( Key == VK_RETURN )
 {
  try{
   n = StrToInt(edVar->Text);
   m = StrToInt(edLim->Text);
   UpdateIntVarList();
  }
  catch(Exception &e)
  {
   MessageDlg( e.Message, mtError, TMsgDlgButtons() << mbOK, 0 );
   ((TEdit *)(Sender))->SetFocus();
  }
  AllocArrays();
 }
}
//---------------------------------------------------------------------------



void __fastcall TMainForm::cbAlgChange(TObject *Sender)
{
 clbIntVar->Enabled = (cbAlg->ItemIndex == 1);
 UpdateIntVarList();
}

void TMainForm::UpdateIntVarList()
{
 clbIntVar->Items->Clear();
// for (int i=1;i<=n;i++) clbIntVar->Checked[i-1] = true;
 for( int i=1; i <= n; i++ )
 {
  clbIntVar->Items->Add( Format( "x%d", ARRAYOFCONST(((int)i)) ) );
  clbIntVar->Checked[i-1] = true;
  if( cbAlg->ItemIndex != 1 )clbIntVar->State[i-1] = cbGrayed;

 }
 tsResults->TabVisible = false;
 TabSheet1->TabVisible = false;
}
//---------------------------------------------------------------------------

void __fastcall TMainForm::BitBtn5Click(TObject *Sender)
{
 if( SaveDialog->Execute() )
 {
  int i,j;
  ofstream ofs( SaveDialog->FileName.c_str(), ios::trunc );

  ofs << n << endl << m << endl << endl;
  for( i=0; i<n; i++ )ofs << Q[i] << '\t';
  ofs << Q[n] << endl << endl;

  for( i=0; i<m; i++ )
  {
   for( j=0; j<=n; j++ )
    ofs << K[i*(n+2)+j] << '\t';

   ofs << K[i*(n+2)+n+1] << endl;
  }
  ofs.close();
 }
}
//---------------------------------------------------------------------------

void __fastcall TMainForm::BitBtn4Click(TObject *Sender)
{
 if( OpenDialog->Execute() )
 {
  int i,j;
  ifstream ifs( OpenDialog->FileName.c_str() );

  ifs >> n;
  ifs >> m;
  AllocArrays();

  for( i=0; i<n; i++ )ifs >> Q[i];
  ifs >> Q[n];

  for( i=0; i<m; i++ )
  {
   for( j=0; j<=n; j++ )
    ifs >> K[i*(n+2)+j];

   ifs >> K[i*(n+2)+n+1];
  }
  ifs.close();

  edVar->Text = IntToStr( n );
  edLim->Text = IntToStr( m );
  UpdateIntVarList();
  dwgInput1->Repaint();
  dwgInput2->Repaint();
 }
}
//---------------------------------------------------------------------------

void __fastcall TMainForm::BitBtn6Click(TObject *Sender)
{
 if( SaveDialog->Execute() )
  mRes->Lines->SaveToFile( SaveDialog->FileName );
}
//---------------------------------------------------------------------------


void __fastcall TMainForm::clbIntVarEnter(TObject *Sender)
{
 tsResults->TabVisible = false;
 TabSheet1->TabVisible = false;
}
//---------------------------------------------------------------------------











