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

#include "stdafx.h"
#include "ElevatorsApp.h"
#include "TDetControlSystem.h"
#include "TElevator.h"
#include "TObject.h"

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

TDetControlSystem detControlSystem;

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

TDetControlSystem::TDetControlSystem()
{

}

TDetControlSystem::~TDetControlSystem()
{

}

void TDetControlSystem::messageHandler
( 
   TControlSystemMessages message,
   void *parm
)
{
   switch( message )
   {
      case CSM_PRESS_BUTTON:
         
         effCriteriaCounter.pressButton( ((TCSMPressButtonParm*)parm)->floor,
                                         ((TCSMPressButtonParm*)parm)->up );
         break;
      
      case CSM_UNPRESS_BUTTON:
         effCriteriaCounter.unpressButton( ((TCSMPressButtonParm*)parm)->floor,
                                           ((TCSMPressButtonParm*)parm)->up );
         break;

      case CSM_STEP:
         messageHandler( CSM_EFF_CRITERIA_COUNTER_PRESTEP, NULL );
         controlOne( &object.elev, &object.button );
         break;

      case CSM_EFF_CRITERIA_COUNTER_PRESTEP:
         effCriteriaCounter.prestep();
         break;
      
      case CSM_INIT:
         effCriteriaCounter.init();
         break;

      case CSM_RESET:
         effCriteriaCounter.reset();
         break;

      case CSM_GET_EFF_CRITERIA:
         *(double*)parm = effCriteriaCounter.getEffCriteria();
         break;

      case CSM_GET_POPULEST_FLOOR:
         *(int*)parm = 0;
         break;

      case CSM_GET_REGIME:
         *(CString*)parm = "Управление";
         break;

      case CSM_GET_KSU:
         *(float*)parm = 0.0;
         break;

      case CSM_GET_OLD_KSU:
         *(float*)parm = 0.0;
         break;

      case CSM_GET_SOLVER_IMAGE_NAME:
         strcpy( (char*)parm, "" );
         break;

      default:
         break;
   }
}

void TDetControlSystem::stop( TElevator *elev, TButton *but )
{
   int floor = elev->getFloor();
   int eU = elev->getUpperFloor();
   int eL = elev->getLowerFloor();

   int bU = but->getUpperFloor();
   int bL = but->getLowerFloor();
   int bUD = but->getUpperFloor(0);
   int bLD = but->getLowerFloor(0);
   int bUU = but->getUpperFloor(1);
   int bLU = but->getLowerFloor(1);
   int prevTask = elev->getTask();

   int l = min( bL, eL );
   int u = max( bU, eU );

   if( floor >= u )
   {
      elev->setCmd( ELEV_CMD_STOP );
      elev->setTask( ELEV_TASK_STOP );
   }

   if( l == 100 || u == 0 )
   {
      elev->setCmd( ELEV_CMD_STOP );
      elev->setTask( ELEV_TASK_STOP );
   }
}

void TDetControlSystem::controlOne
(
   TElevator *elev, 
   TButton   *but
)
{
   int floor = elev->getFloor();
   int eU = elev->getUpperFloor();
   int eL = elev->getLowerFloor();

   int bU = but->getUpperFloor();
   int bL = but->getLowerFloor();
   int bUD = but->getUpperFloor(0);
   int bLD = but->getLowerFloor(0);
   int bUU = but->getUpperFloor(1);
   int bLU = but->getLowerFloor(1);
   int prevTask = elev->getTask();

   switch( elev->getDoorsState() )
   {
      case ELEV_DOORS_STATE_OPEN:
         elev->setDoorsCmd( ELEV_DOORS_CMD_CLOSE );
         break;
      
      case ELEV_DOORS_STATE_CLOSE:
         switch( elev->getState() )
         {
            case ELEV_STATE_STOP:
               switch( elev->getTask() )
               {
                  case ELEV_TASK_STOP:
                     if( eU )
                     {
                        if( eU > floor )
                        {
                           elev->setTask( ELEV_TASK_UP );
                           elev->setCmd( ELEV_CMD_UP );
                        }
                        else if( eU < floor )
                        {
                           elev->setTask( ELEV_TASK_DOWN );
                           elev->setCmd( ELEV_CMD_DOWN );
                        }
                        else
                        {
                           elev->setTask( ELEV_TASK_STOP );
                           elev->setCmd( ELEV_CMD_STOP );
                        }
                     }
                     else if( bU )
                     {
                        if( bU > floor )
                        {
                           elev->setTask( ELEV_TASK_UP );
                           elev->setCmd( ELEV_CMD_UP );
                        }
                        else if( bU < floor )
                        {
                           elev->setTask( ELEV_TASK_DOWN );
                           elev->setCmd( ELEV_CMD_DOWN );
                        }
                        else
                        {
                           elev->setTask( ELEV_TASK_STOP );
                           elev->setCmd( ELEV_CMD_STOP );
                        }
                     }
                     break;

                  case ELEV_TASK_UP:
                     elev->setCmd( ELEV_CMD_UP );
                     stop( elev, but );
                     break;

                  case ELEV_TASK_DOWN:
                     elev->setCmd( ELEV_CMD_DOWN );
                     stop( elev, but );
                     break;
               }
               break;

            case ELEV_STATE_MOVING_UP:
               switch( elev->getTask() )
               {
                  case ELEV_TASK_STOP:
                  case ELEV_TASK_DOWN:
                     theApp.DoMessageBox("Этого не может быть", MB_OK, 0);
                     break;

                  case ELEV_TASK_UP:
                     elev->setCmd( ELEV_CMD_UP );
                     stop( elev, but );
                     break;
               }
               break;

            case ELEV_STATE_MOVING_DOWN:
               switch( elev->getTask() )
               {
                  case ELEV_TASK_STOP:
                  case ELEV_TASK_UP:
                     theApp.DoMessageBox("Этого не может быть", MB_OK, 0);
                     break;

                  case ELEV_TASK_DOWN:
                     elev->setCmd( ELEV_CMD_DOWN );
                     stop( elev, but );
                     break;
               }
               break;
         }

         // открытие дверей, если нужно
         switch( prevTask )
         {
            case ELEV_TASK_STOP:
               if( elev->checkButton(floor) ||
                   but->checkButton( floor )  )
               {
                  elev->setDoorsCmd( ELEV_DOORS_CMD_OPEN );
                  elev->setCmd( ELEV_CMD_STOP );
               }
               break;

            case ELEV_TASK_UP:
               if( elev->checkButton(floor)     ||
                   but->checkButton( floor, 1 ) ||
                   (but->checkButton( floor, 0 ) && 
                    elev->getTask() == ELEV_TASK_STOP ) )
               {
                  elev->setDoorsCmd( ELEV_DOORS_CMD_OPEN );
                  elev->setCmd( ELEV_CMD_STOP );
               }
               break;

            case ELEV_TASK_DOWN:
               if( elev->checkButton(floor) ||
                   but->checkButton( floor, 0 ) ||
                   (but->checkButton( floor, 1 ) && 
                    elev->getTask() == ELEV_TASK_STOP ) )
               {
                  elev->setDoorsCmd( ELEV_DOORS_CMD_OPEN );
                  elev->setCmd( ELEV_CMD_STOP );
               }
               break;
         }
         break;
   }
}
