// TElevator.cpp: implementation of the TElevator class.
//
//////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "TElevator.h"
#include "TObject.h"
#include "TControlSystem.h"

#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
TElevator::TElevator( int begNumber, int floorNumbers, int begFloor )
{
   for( int i = 0; i < MAX_FLOOR_NUMBER; i++ )
      buttons[i] = 0;

   number = begNumber; 
   floor = begFloor;
   floorNumbers = floorNumbers;

   movedFloorsNumber = 1;
}

void TElevator::reset()
{
   floor = 1;
   
   for( int b = 0; b < MAX_FLOOR_NUMBER; b++ )
      buttons[b] = 0;

// состояние лифта
   doorsState = ELEV_DOORS_STATE_CLOSE;
   state = ELEV_STATE_STOP;
   task = ELEV_TASK_STOP;

   cmd = ELEV_CMD_STOP;
   doorsCmd = ELEV_DOORS_CMD_CLOSE;

   openDoorsCount = 0;

   movedFloorsNumber = 1;
}

TElevator::~TElevator()
{

}

void TElevator::draw( CDialog *wnd, CPaintDC *dc )
{
   // get our client rectangle
   CRect clientRect;
   wnd->GetClientRect( &clientRect );

   int x1 = 20 + number*ELEVATOR_XDISTANCE;
   int x2 = 20 + number*ELEVATOR_XDISTANCE + ELEVATOR_WIDE;

   if( number >= 5 ) 
   {
      x1 += ELEVATOR_GROUP_DISTANCE;
      x2 += ELEVATOR_GROUP_DISTANCE;
   }

   CBrush dbrush(RGB(150,150,150));
   CPen dpen( PS_SOLID, 1, RGB(150,150,150) );
   CBrush* pOldBrush = dc->SelectObject( &dbrush );
   CPen* pOldPen = dc->SelectObject( &dpen );

   dc->Rectangle(CRect( x1, clientRect.bottom - ELEVATOR_YCONST - 7*ELEVATOR_HEIGHT, 
                        x2, clientRect.bottom - ELEVATOR_YCONST - 1*ELEVATOR_HEIGHT ));
   dc->Rectangle(CRect( x1, clientRect.bottom - ELEVATOR_YCONST - 12*ELEVATOR_HEIGHT, 
                        x2, clientRect.bottom - ELEVATOR_YCONST - 10*ELEVATOR_HEIGHT ));
   dc->Rectangle(CRect( x1, clientRect.bottom - ELEVATOR_YCONST - 15*ELEVATOR_HEIGHT, 
                        x2, clientRect.bottom - ELEVATOR_YCONST - 13*ELEVATOR_HEIGHT ));
   
   if( number <= 4 )
      dc->Rectangle(CRect( x1, clientRect.bottom - ELEVATOR_YCONST - 23*ELEVATOR_HEIGHT, 
                           x2, clientRect.bottom - ELEVATOR_YCONST - 22*ELEVATOR_HEIGHT ));
   CBrush brush;
   brush.CreateSysColorBrush(COLOR_WINDOW);
   dc->SelectObject( &brush );

   CPen pen( PS_SOLID, 1, RGB( 0, 0, 0 ) );
   dc->SelectObject( &pen );

   dc->MoveTo( x1, clientRect.bottom - ELEVATOR_YCONST );
   dc->LineTo( x1, clientRect.bottom - ELEVATOR_YCONST - floorNumbers*ELEVATOR_HEIGHT );

   dc->MoveTo( x2, clientRect.bottom - ELEVATOR_YCONST );
   dc->LineTo( x2, clientRect.bottom - ELEVATOR_YCONST - floorNumbers*ELEVATOR_HEIGHT );

   for( int i = 0; i <= floorNumbers; i++ )
   {
      dc->MoveTo( x1, clientRect.bottom - ELEVATOR_YCONST - i*ELEVATOR_HEIGHT );
      dc->LineTo( x2, clientRect.bottom - ELEVATOR_YCONST - i*ELEVATOR_HEIGHT );

   }

   if( getDoorsState() == ELEV_DOORS_STATE_OPEN )
   {
      CPen ePen( PS_SOLID, 3, RGB( 0, 255, 0 ) );
      dc->SelectObject( &ePen );

      dc->Rectangle(CRect( x1, clientRect.bottom - ELEVATOR_YCONST - floor*ELEVATOR_HEIGHT, 
                           x2, clientRect.bottom - ELEVATOR_YCONST - (floor-1)*ELEVATOR_HEIGHT ));
   }
   else
   {
      CPen ePen( PS_SOLID, 3, RGB( 255, 0, 0 ) );
      dc->SelectObject( &ePen );

      dc->Rectangle(CRect( x1, clientRect.bottom - ELEVATOR_YCONST - floor*ELEVATOR_HEIGHT, 
                           x2, clientRect.bottom - ELEVATOR_YCONST - (floor-1)*ELEVATOR_HEIGHT ));
   }

   CPen kpen( PS_SOLID, 1, RGB(0,0,255) );
   CPen* kOldPen = dc->SelectObject( &kpen );

   for( i = 0; i < floorNumbers; i++ )
   {
      if( buttons[i] )
         dc->Ellipse( x1 + (ELEVATOR_XDISTANCE - ELEVATOR_WIDE)/2 -3,
                      clientRect.bottom - ELEVATOR_YCONST - (i+1)*ELEVATOR_HEIGHT + ELEVATOR_HEIGHT/2 - 3,
                      x1 + (ELEVATOR_XDISTANCE - ELEVATOR_WIDE)/2 +3,
                      clientRect.bottom - ELEVATOR_YCONST - (i+1)*ELEVATOR_HEIGHT + ELEVATOR_HEIGHT/2 + 3 );
   }
   dc->SelectObject(kOldPen);


   dc->SelectObject(pOldBrush);
   dc->SelectObject(pOldPen);
}

void TElevator::step()
{
   if( !openDoorsCount ) // если openDoorsCount - значит фальшивый цикл
   {
      switch( cmd )
      {
         case ELEV_CMD_STOP:
            state = ELEV_STATE_STOP;
            switch( task )
            {
               case ELEV_TASK_STOP:
                  if( doorsCmd == ELEV_DOORS_CMD_OPEN )
                  {
                     if( object.button.checkButton( floor, 1 ) )
                        object.button.unpressButton( floor, 1 );
                     else if( object.button.checkButton( floor, 0 ) )
                        object.button.unpressButton( floor, 0 );
                     if( checkButton( floor ) ) unpressButton( floor );
                  }
                  break;

               case ELEV_TASK_UP:
                  if( doorsCmd == ELEV_DOORS_CMD_OPEN )
                  {
                     if( object.button.checkButton( floor, 1 ) )
                        object.button.unpressButton( floor, 1 );
                     if( checkButton( floor ) ) unpressButton( floor );
                  }
                  break;

               case ELEV_TASK_DOWN:
                  if( doorsCmd == ELEV_DOORS_CMD_OPEN )
                  {
                     if( object.button.checkButton( floor, 0 ) )
                        object.button.unpressButton( floor, 0 );
                     if( checkButton( floor ) ) unpressButton( floor );
                  }
                  break;
            }
            break;

         case ELEV_CMD_UP:
            floor++;
            movedFloorsNumber++;
            state = ELEV_STATE_MOVING_UP;
            break;
   
         case ELEV_CMD_DOWN:
            floor--;
            movedFloorsNumber++;
            state = ELEV_STATE_MOVING_DOWN;
            break;
      }
      cmd = ELEV_CMD_STOP;
   }

   switch( doorsCmd )
   {
      case ELEV_DOORS_CMD_NONE:
         break;

      case ELEV_DOORS_CMD_OPEN:
         doorsState = ELEV_DOORS_STATE_OPEN;
         openDoorsCount = OPEN_DOORS_STOP_STEPS;
         break;

      case ELEV_DOORS_CMD_CLOSE:
         if( openDoorsCount )
            openDoorsCount--;
         else
            doorsState = ELEV_DOORS_STATE_CLOSE;
         break;
   }
   doorsCmd = ELEV_DOORS_CMD_NONE;
}

void TElevator::pressButton( int floor ) 
{ 
   if( !checkButton( floor ) )   
   {
      TCSMPressButtonParm parm;
      parm.floor = floor;

      controlSystem->messageHandler( CSM_PRESS_ELEV_BUTTON, &parm );
   }

   if( TElevator::floor != floor ) 
      buttons[floor-1] = 1; 
}


int  TElevator::checkButtons() 
{ 
   int result = 0;
   for( int f = 1; f <= MAX_FLOOR_NUMBER; f++ )
      if( checkButton( f ) ) result++;

   return result;
}

int TElevator::getUpperFloor()
{
   for( int f = MAX_FLOOR_NUMBER; f >= 1; f-- )
      if( checkButton( f ) ) return f;

   return 0;
}

int TElevator::getLowerFloor()
{
   for( int f = 1; f <= MAX_FLOOR_NUMBER; f++ )
      if( checkButton( f ) ) return f;

   return 100;
}
