#ifndef INCLUDE_NASTCELL2D_H
#define INCLUDE_NASTCELL2D_H
//-----------------------------------------------------------------------------
// NastCell2d.h
//-----------------------------------------------------------------------------
//
//  Copyright (C) 1998 Technische Universitaet Muenchen, Germany
//                   written by Bernhard Brueck
//
//  This file is part of Nast++
//
//-----------------------------------------------------------------------------
// CNastCell2d beschreibt den Typ der Zelle. Es laesst sich der Typ der Zelle
// und die Eigenschaft isFluid der Nachbarzellen erfragen. Eine Zelle kann
// folgende Eigenschaften haben:
//    isEmpty()       kein Fluid und keine Hinderniszelle ?
//    isFluid()       Fluidzelle ?
//    isBarrier()     Hindernisszelle ?
//    isInsideFluid() Fluidzelle umgeben mit Fluidzellen ?
//-----------------------------------------------------------------------------
//  Aenderungen:
//     

#include "NastConfig.h"
#include "NastObject.h"
#include "NastDebug.h"

class CNastCell2d : public CNastObject
{
public:
    //-------------------------------------------------------------------------
    //                         Typen
    //-------------------------------------------------------------------------
    //  bitcodierte Richtungen,
    //  sie lassen sich ueber logische Verkuepfungen verbinden
    //  z.B. (CNastCell2d::THIS | CNastCell2d::NORTH)

    typedef int Direction;
    enum
    {
        THIS  = 1 << 0,  // 00001  die aktuelle Zelle  (i  ,j  )
        NORTH = 1 << 1,  // 00010  die Zelle noerdlich (i  ,j+1)
        SOUTH = 1 << 2,  // 00100  die Zelle suedlich  (i  ,j-1)
        WEST  = 1 << 3,  // 01000  die Zelle westlich  (i-1,j  )
        EAST  = 1 << 4   // 10000  die Zelle oestlich  (i+1,j  )
    };

    enum Type
    {
        EMPTY,			// Zelle ist leer
        FLUID,			// Zelle ist im Fluid
        BARRIER                 // Hinderniszelle
    };

    //-------------------------------------------------------------------------
    //                         Konstruktor + Destruktor
    //-------------------------------------------------------------------------
    //  im Defaultkonstr. wird der Zelltyp auf empty festgelegt
    //  
    CNastCell2d();
    CNastCell2d( Direction fluid, Type type );
    CNastCell2d( const CNastCell2d &other);	            
    const CNastCell2d& operator=( const CNastCell2d &other );

    //-------------------------------------------------------------------------
    //    Zelltyp
    //-------------------------------------------------------------------------
    // type()            liefert den Typ der Zelle 
    // filterFluid(...)  liefert zurueck welche Zellen Fluidzellen sind
    //                   Die zu betrachtenden Richtung lasesen sich angeben.
    // isInsideFluid()   sind die Zelle und alle Nachbarzellen Fluidzellen ?

    Type type() const;
    void type( Type newType,
               CNastCell2d *pWest,
               CNastCell2d *pEast,
               CNastCell2d *pSouth,
               CNastCell2d *pNorth );

    Direction filterFluid( int filter ) const;
    bool isFluid  ( int filter = THIS ) const;
    bool isBarrier() const;
    bool isEmpty  () const;
    bool isInsideFluid() const;
   
    //-------------------------------------------------------------------------
    //                                  Debug
    //-------------------------------------------------------------------------
    //  debugInfo    gibt Information ueber den Zustand des Objekts aus
    //  assertValid  testet das Objekt auf Integritaet
    //

    virtual void debugDump( CNastDumpContext &dumpContext ) const;
    virtual void assertValid() const;

private:
    //-------------------------------------------------------------------------
    //                            Membervariablen
    //-------------------------------------------------------------------------
    
    Direction m_fluid; // Fluideigenschaft der Zelle und der Nachbarn
    Type      m_type;  // Typ der Zelle selbst
};

//-------------------------------------------------------------------------
//                            inline
//-------------------------------------------------------------------------

// sind alle Zellen in den angegebenen Richtungen Fluidzellen ?
inline bool 
CNastCell2d::isFluid( Direction dir /* = CNastCell2d::THIS */ ) const
{
    return (m_fluid & dir) == dir;
}

// ist die Zelle eine Hinderniszelle ?
inline bool 
CNastCell2d::isBarrier() const
{
    return m_type == BARRIER;
}

// ist die Zelle leer ?
inline bool 
CNastCell2d::isEmpty  () const
{
    return m_type == EMPTY;
}

// alle Richtungen in denen Fluidzellen liegen
inline CNastCell2d::Direction 
CNastCell2d::filterFluid( int filter ) const
{
    return m_fluid & filter;
}

// Typ der Zelle
inline CNastCell2d::Type 
CNastCell2d::type() const
{
    return m_type;
}

// ist die Zelle von Fluidzellen umgeben ?
inline bool 
CNastCell2d::isInsideFluid() const 
{
    return m_fluid == (THIS | NORTH | SOUTH | WEST | EAST);
}

//  Copyconstr.
inline 
CNastCell2d::CNastCell2d( const CNastCell2d &other )
    :CNastObject( other ),
     m_fluid(other.m_fluid),
     m_type(other.m_type)
{}

inline
CNastCell2d::CNastCell2d( CNastCell2d::Direction fluid,
        		  CNastCell2d::Type type )
    :m_fluid(fluid),
     m_type(type)
{
    // Wenn Fluidzelle, dann muss THIS auch gesetzt sein
    NAST_ASSERT( type == FLUID && (fluid & THIS) ||
        	 type != FLUID);
}

#endif // INCLUDE_NASTCELL2D_H

