/*----------------------------------------------------------------------*/
/* (C) Copyright 1994 Stefanos Kiakas                                   */
/* All rights reserved.                                                 */
/*----------------------------------------------------------------------*/

#import <appkit/appkit.h>

#import "NCommon.h"
#import "NPipeCell.h"
#import "VerticalPipe.h"
#import "HorizontalPipe.h"
#import "UpperRightQuarterCircle.h"
#import "UpperLeftQuarterCircle.h"
#import "LowerLeftQuarterCircle.h"
#import "LowerRightQuarterCircle.h"
#import "UnassignedSquare.h"
#import "Source.h"
#import "IntersectingPipe.h"
#import "Obstacle.h"


@implementation NPipeCell
/*----------------------------------------------------------------------*/
/* Purpose      : Initalize the cell to be used for drawing into and    */
/*                let it take the role of an unassigned piece.          */
/*                                                                      */
/* Parameters   : none                                                  */
/*                                                                      */
/* Return value : none                                                  */
/*----------------------------------------------------------------------*/
- init
{
   [super initIconCell:""];
   role = PIPE_UNASSIGNED;
   return self;
}






/*----------------------------------------------------------------------*/
/* Purpose     : To indicate if the pipe assigned ta the cell can be    */
/*               replaced by another pipe.                              */
/*                                                                      */
/* Parameters  : none                                                   */
/*                                                                      */
/* Return value: TRUE -> pipe can be replaced.                          */
/*               FALSE -> pipe should not be replaced.                  */
/*----------------------------------------------------------------------*/
- (int) isPipeReplaceable
{
   if( flowLevelA == 0 && flowLevelB == 0 && role != PIPE_SOURCE && role != PIPE_OBSTACLE )
      return TRUE;
   return FALSE;
}


/*----------------------------------------------------------------------*/
/* Purpose      :                                                       */
/* Parameters   :                                                       */
/* Return value :                                                       */
/*----------------------------------------------------------------------*/
- (Direction_t) exitDirection
{
   return( entry2exit( role, flowEntryDirection) );
}

/*----------------------------------------------------------------------*/
/* Purpose      :                                                       */
/* Parameters   :                                                       */
/* Return value :                                                       */
/*----------------------------------------------------------------------*/
- setFlowEntryDirection: (Direction_t ) entry
{
   if( PIPE_VERTICAL_BIDIRECTIONAL <= role && role <= PIPE_INTERSECTION )
      score = BIDIRECTIONAL_PIECE_POINTS;
   else if( PIPE_VERTICAL_ONEWAY_UP <= role && role <= PIPE_HORIZONTAL_ONEWAY_RIGHT )
      score = BIDIRECTIONAL_PIECE_POINTS;

   if( flowLevelA > 0 || flowLevelB > 0 )
      bonus = INTERSECTION_BONUS_POINTS;

   flowEntryDirection = entry;
   return self;
}


/*----------------------------------------------------------------------*/
/* Purpose      :                                                       */
/* Parameters   :                                                       */
/* Return value :                                                       */
/*----------------------------------------------------------------------*/
- assignPipe: (NPipe_t) pipe
{
   flowLevelA = 0;
   flowLevelB = 0;
   role = (int) pipe;
   return self;
}

/*----------------------------------------------------------------------*/
/* Purpose      :                                                       */
/* Parameters   :                                                       */
/* Return value :                                                       */
/*----------------------------------------------------------------------*/
- (int) isFlowPossible
{
   if( entry2exit( role, flowEntryDirection) == INVALID_DIR )
      return FALSE;
   else
      return TRUE;
}

/*----------------------------------------------------------------------*/
/* Purpose      :                                                       */
/* Parameters   :                                                       */
/* Return value :                                                       */
/*----------------------------------------------------------------------*/
- continueFlow
{
   if( role != PIPE_INTERSECTION )
      flowLevelA++;
   else
   {
      if( flowEntryDirection == WEST || flowEntryDirection == EAST )
         flowLevelA++;
      else
         flowLevelB++;
   }
   return self;
}




/*----------------------------------------------------------------------*/
/* Purpose      :                                                       */
/* Parameters   :                                                       */
/* Return value :                                                       */
/*----------------------------------------------------------------------*/
- (int) isOverFlow
{
   static levels[] = { 0, 0, 80, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10 };
   int cFlow = 0;

   if( role != PIPE_INTERSECTION || flowEntryDirection == WEST || flowEntryDirection == EAST )
      cFlow = flowLevelA;
   else
      cFlow = flowLevelB;
   if( cFlow > levels[(int)role] )
      return TRUE;
   else
      return FALSE;
}

/*----------------------------------------------------------------------*/
/* Purpose      :                                                       */
/* Parameters   :                                                       */
/* Return value :                                                       */
/*----------------------------------------------------------------------*/
- (int) getScorePoints
{
   int rScore = 0;

   rScore = score;
   score = 0;
   return(rScore);
}

/*----------------------------------------------------------------------*/
/* Purpose      :                                                       */
/* Parameters   :                                                       */
/* Return value :                                                       */
/*----------------------------------------------------------------------*/
- (int) getBonusPoints
{
   int rBonus = 0;

   rBonus = bonus;
   bonus = 0;
   return(rBonus);
}

/*----------------------------------------------------------------------*/
/* Purpose      :                                                       */
/* Parameters   :                                                       */
/* Return value :                                                       */
/*----------------------------------------------------------------------*/
- drawInside:(const NXRect *)cellFrame inView:aView;
{
   int isNorthward;
   int isEastward;
   int isClockWise;
   int rotation;

   if(role == PIPE_OBSTACLE)
	   NXSetColor(NX_COLORLTGRAY);
   else
	   NXSetColor(NXConvertRGBToColor(0.0, .3333, .06666));

   NXRectFill(cellFrame);
   NXSetColor(NX_COLORBLACK);
   NXFrameRect(cellFrame);


   switch( role )
   {
      case PIPE_OBSTACLE:
//!         Obstacle( NX_X(cellFrame), NX_Y(cellFrame) );
         break;
      case PIPE_UNASSIGNED:
//!         UnassignedSquare( NX_X(cellFrame), NX_Y(cellFrame) );
         break;
      case PIPE_SOURCE:
         Source( flowLevelA, NX_X(cellFrame), NX_Y(cellFrame) );
         break;
      case PIPE_VERTICAL_BIDIRECTIONAL:
         isNorthward = ( flowEntryDirection == SOUTH ? TRUE : FALSE );
         VerticalPipe( isNorthward, flowLevelA, INVALID_DIR, NX_X(cellFrame), NX_Y(cellFrame) );
         break;
      case PIPE_HORIZONTAL_BIDIRECTIONAL:
         isEastward = ( flowEntryDirection == WEST ? TRUE : FALSE );
         HorizontalPipe( isEastward, flowLevelA, INVALID_DIR, NX_X(cellFrame), NX_Y(cellFrame) );
         break;
      case PIPE_UPPER_LEFT:
      case PIPE_UPPER_RIGHT:
      case PIPE_LOWER_LEFT:
      case PIPE_LOWER_RIGHT:
         rotation = (int) direction2rotation( role, flowEntryDirection );
         if( flowLevelA > 0 )
         {
            if( rotation == INVALID_ROT )
            {
               fprintf(stderr,"Role %d, flow direction %d.\n", role, flowEntryDirection );
               fprintf(stderr,"Invalid direction of rotation. [ %s, %d ]\n", __FILE__, __LINE__ );
               exit( 1 );
            }
            isClockWise = ( rotation == CLOCKWISE ? TRUE : FALSE );
         }
         else
            isClockWise = FALSE;
         if( role == PIPE_UPPER_LEFT )
            UpperLeftQuarterCircle( isClockWise, flowLevelA, NX_X(cellFrame), NX_Y(cellFrame) );
         if( role == PIPE_UPPER_RIGHT )
            UpperRightQuarterCircle( isClockWise, flowLevelA, NX_X(cellFrame), NX_Y(cellFrame) );
         if( role == PIPE_LOWER_LEFT )
            LowerLeftQuarterCircle( isClockWise, flowLevelA, NX_X(cellFrame), NX_Y(cellFrame) );
         if( role == PIPE_LOWER_RIGHT )
            LowerRightQuarterCircle( isClockWise, flowLevelA, NX_X(cellFrame), NX_Y(cellFrame) );
         break;
      case PIPE_INTERSECTION:
         isEastward = ( flowEntryDirection == WEST ? TRUE : FALSE );
         isNorthward = ( flowEntryDirection == SOUTH ? TRUE : FALSE );
         IntersectingPipe( isEastward,flowLevelA, isNorthward, flowLevelB, NX_X(cellFrame), NX_Y(cellFrame));
         break;
      case PIPE_VERTICAL_ONEWAY_UP:
         VerticalPipe( TRUE, flowLevelA, NORTH, NX_X(cellFrame), NX_Y(cellFrame) );
         break;
      case PIPE_VERTICAL_ONEWAY_DOWN:
         VerticalPipe( FALSE, flowLevelA, SOUTH, NX_X(cellFrame), NX_Y(cellFrame) );
         break;
      case PIPE_HORIZONTAL_ONEWAY_LEFT:
         HorizontalPipe( FALSE, flowLevelA, WEST, NX_X(cellFrame), NX_Y(cellFrame) );
         break;
      case PIPE_HORIZONTAL_ONEWAY_RIGHT:
         HorizontalPipe( TRUE, flowLevelA, EAST, NX_X(cellFrame), NX_Y(cellFrame) );
         break;
      default:
         break;
   }
   return self;
}

@end

