/*
  CoreLinux++ 
  Copyright (C) 2000 CoreLinux Consortium
  
   The CoreLinux++ Library is free software; you can redistribute it and/or
   modify it under the terms of the GNU Library General Public License as
   published by the Free Software Foundation; either version 2 of the
   License, or (at your option) any later version.

   The CoreLinux++ Library Library is distributed in the hope that it will 
   be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   Library General Public License for more details.

   You should have received a copy of the GNU Library General Public
   License along with the GNU C Library; see the file COPYING.LIB.  If not,
   write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
   Boston, MA 02111-1307, USA.  
*/   

/** \example examp11.cpp
   This example is to show use of the Builder pattern.
   
   We reworked MazeFactory from ex9 to a more generic implementation
   for a number of reasons.
   
   1. It was heavily type bound which made substitution of allocators
   difficult at best
   
   2. MazeBuilder understands the nuances of rooms, doors, etc so
   we removed it from the MazeFactory
   
   3. We added a Allocator registration method.
   
   4. We factored down the createWall, etc. and destroyWall,etc. 
   methods. to xxxxxPart which requires the NameIdentifier.
   
   In our sample, we create the maze and allow you to walk about
   
*/                   


#include <Common.hpp>
#include <MazeBuilderFactory.hpp>
#include <MazeBuilder.hpp>
#include <Maze.hpp>
#include <Room.hpp>

using namespace corelinux;

#include <iostream>
#include <exception>

//
// In module function prototypes
//

int   main( void );

void  doWalk( MazePtr );

//
// Functions that work with Engine types
//

void  handleAssertion( AssertionCref );
void  handleException( ExceptionCref );

int main( void )
{

   //
   // Practice gracefull exception management
   //

   cout << endl;

   try
   {
      MazeBuilderFactory   aMazeFactory;
      MazeBuilder          aMazeBuilder(&aMazeFactory);
      MazePtr              aMaze( aMazeBuilder.create() );

      doWalk( aMaze );
      aMazeBuilder.destroy( aMaze );
   }

   catch( AssertionRef aAssert )
   {
      handleAssertion(aAssert);
   }
   catch( ExceptionRef aException )
   {
      handleException(aException);
   }
   catch( std::exception & e )
   {
      cerr  << e.what() << endl;
   }
   catch( ... )
   {
      cerr  << "Unknown exception." << endl;
   }

   return 0;               
}

void  displayMenu( void )
{
   cout  << endl;
   cout  << "\tGo North          1" << endl;
   cout  << "\tGo East           2" << endl;
   cout  << "\tGo West           3" << endl;
   cout  << "\tGo South          4" << endl;
   cout  << "\tQuit walking      5" << endl;
   cout  << endl;
}

Int   getCommand( void )
{
   displayMenu();

   Int   aOption;

   cout  << "Enter the option number on the right to execute : ";
   cin   >> aOption;

   return aOption;
}

void  doWalk( MazePtr aMaze )
{
   bool  keepWorking(true);

   do
   {
      cout  << "Your are currently in room : " << 
         aMaze->getCurrentLocation().getRoomNumber() << endl;

      Int   aCommand( getCommand() );

      if( aCommand > 5 || aCommand < 0 )
      {
         cerr << "You can't enter non-numeric options!" << endl;
         aCommand = 5;
      }
      else
      {
         ;  // do nothing
      }

      switch( aCommand )
      {
         //
         // Travel North
         //

         case  1:
            {
               aMaze->walkInDirection( NORTH );
               break;
            }

         //
         // Travel East
         //

         case  2:
            {
               aMaze->walkInDirection( EAST );
               break;
            }

         //
         // Travel West
         //

         case  3:
            {
               aMaze->walkInDirection( WEST );
               break;
            }

         //
         // Travel South
         //

         case  4:
            {
               aMaze->walkInDirection( SOUTH );
               break;
            }

         //
         // Exit routine
         //

         case  5:
            keepWorking=false;
            break;

         default:
            ;  //do nothing
            break;
      }
   } while( keepWorking == true );

}

//
// Peform default (just show it)
//

void  handleAssertion( AssertionCref aAssert )
{
   cerr << aAssert.getFile() << ":" << aAssert.getLine() << ":" << 
      "Assertion: ";

   if( aAssert.getType() == Assertion::NEVERGETHERE )
   {
      cerr << "NEVER_GET_HERE";
   }
   else
   {
      if( aAssert.getType() == Assertion::REQUIRE )
      {
         cerr  << "REQUIRE";
      }
      else if( aAssert.getType() == Assertion::ENSURE )
      {
         cerr  << "ENSURE";
      }
      else if( aAssert.getType() == Assertion::CHECK )
      {
         cerr  << "CHECK";
      }
      else 
      {
         cerr  << "ASSERT";
      }
      cerr << "( " << aAssert.getWhy() << " )";
   }

   cerr << endl;
}

void  handleException( ExceptionCref aExcp )
{
   cerr << aExcp.getFile() << ":" << aExcp.getLine() << ":" <<
      "Exception: " << aExcp.getWhy() << endl;
}

/*
   Common rcs information do not modify
   $Author: prudhomm $
   $Revision: 1.3 $
   $Date: 2000/08/31 22:50:42 $
   $Locker:  $
*/


