//-----------------------------------------------------------------------------
// NastCellField2d.cpp
//-----------------------------------------------------------------------------
//
//  Copyright (C) 1998 Technische Universitaet Muenchen, Germany
//  written by Bernhard Brueck
//
//  This file is part of Nast++
//
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
//  Changes:
//

#include "NastCellField2d.h"
#include "NastDebug.h"

//-----------------------------------------------------------------------------
//                    Konstruktor + Destruktor
//-----------------------------------------------------------------------------

//  Feld der Groesse 0..nSizeI-1, 0..nSizeJ-1 erzeugen
CNastCellField2d::CNastCellField2d( const CNastBox2d &box, int nSizeI, int nSizeJ )
    :m_arrCells( nSizeI, nSizeJ ),
     m_box(box)
{
    // Zellen bekommen im Defaultkonstruktor den Typ EMPTY
    m_arrCells.setSize( nSizeI, nSizeJ );
}

CNastCellField2d::~CNastCellField2d()
{
    NAST_ASSERT_VALID( this );
    // vorerst nichts zu tun
}


// ----------------------------------------------------------------------------
//                                Memberfunktionen
// ----------------------------------------------------------------------------



//  legt fuer eine bestimmte Zelle den Typ fest und aendert bei Bedarf
//  die Nachbarzellen
void CNastCellField2d::setCellType( int i, int j, CNastCell2d::Type type)
{
    NAST_ASSERT_INDEX( i >= 0);
    NAST_ASSERT_INDEX( j >= 0);
    NAST_ASSERT_INDEX( i < sizeI() );
    NAST_ASSERT_INDEX( j < sizeJ() );

    CNastCell2d *pWest  = 0;
    CNastCell2d *pEast  = 0;
    CNastCell2d *pNorth = 0;
    CNastCell2d *pSouth = 0;

    // Zahler mit den Zellen anpassen
    if( !cell(i,j).isFluid() &&( type == CNastCell2d::FLUID ))
    {
        ++m_nCountFluid;
    }
    else if( cell(i,j).isFluid() && (type != CNastCell2d::FLUID ))
    {
        --m_nCountFluid;
    }

    // die passenden Zeiger setzen, falls Nachbarzellen existieren 
    if( i   > 0       )  pWest  = &( m_arrCells( i-1, j   ));
    if( i+1 < sizeI() )  pEast  = &( m_arrCells( i+1, j   ));
    if( j   > 0       )  pSouth = &( m_arrCells( i  , j-1 ));
    if( j+1 < sizeJ() )  pNorth = &( m_arrCells( i  , j+1 ));

    // und die Eigenschaften der Zelle und ihrer Nachbarn setzen
    m_arrCells(i,j).type( type, pWest, pEast, pSouth, pNorth );
}

// ----------------------------------------------------------------------------
//                                    Debug
// ----------------------------------------------------------------------------


// Hilfsfunktion um die Beziehungen zwischen den Zellen anzuzeigen
static void printFluid( const CNastCellField2d &field, CNastDumpContext &dumpContext )
{
    int i,j;
    // horizontale Unterteilungen
    dumpContext << "\t  ";
    for( i = 0; i < field.sizeI()-9; i += 10)
        dumpContext << "                                       |";   
    dumpContext << "\n";
    
    dumpContext << "\t  ";
    for( i = 0; i < field.sizeI()-4; i += 5)
        dumpContext << "                    |";   
    dumpContext << "\n";
    
    //  die Daten ausgeben
    for( j = field.sizeJ()-1; j >= 0; j--)
    {
        dumpContext << "\t  ";
        for( i = 0; i < field.sizeI(); i++)
            if( field.cell(i,j).isFluid(CNastCell2d::NORTH))
        	dumpContext << " #  "; 
            else
        	dumpContext << " 0  ";
        dumpContext << "\n";

        // vertikale Unterteilungen
        if( (j+1) % 10 == 0 )
            dumpContext << "\t--";
        else if( (j+1) % 5 == 0 )
            dumpContext << "\t -";
        else
            dumpContext << "\t  ";
        
        for( i = 0; i < field.sizeI(); i++)
        {
            if( field.cell(i,j).isFluid( CNastCell2d::WEST ))
        	dumpContext << "#";
            else
        	dumpContext << "0";

            if( field.cell(i,j).isFluid( CNastCell2d::THIS ))
        	dumpContext << "#";
            else
        	dumpContext << "0";

            if( field.cell(i,j).isFluid( CNastCell2d::EAST ))
        	dumpContext << "#";
            else
 		dumpContext << "0";
            dumpContext << " ";
        }
        dumpContext << "\n";
        
        dumpContext << "\t  ";
        for( i = 0; i < field.sizeI(); i++)
            if( field.cell(i,j).isFluid(CNastCell2d::SOUTH))
        	dumpContext << " #  "; 
            else
        	dumpContext << " 0  ";

        dumpContext << "\n\n";
    }
}

void 
CNastCellField2d::debugDump( CNastDumpContext &dumpContext ) const
{
    int i,j;
    CNastObject::debugDump( dumpContext );

    dumpContext << "CNastCellField2d" << "\n";
    dumpContext << "\tAnzahl der Zellen:  ";
    dumpContext << m_arrCells.sizeI() << "  ";
    dumpContext	<< m_arrCells.sizeJ() << "\n";
    dumpContext << "\tAnzahl der Fluidzellen:" << m_nCountFluid << "\n";

    // Falls nicht zu viele Zellen vorhanden sind, dann werden sie ausgegeben
    // # Hinderniszelle
    // . Fluidzelle

    if( sizeI() < 130 && sizeJ() < 60 )
    {
        // horizontale Unterteilungen
        dumpContext << "\t  ";
        for( i = 0; i < sizeI()-9; i += 10)
            dumpContext << "         |";   
        dumpContext << "\n";

        dumpContext << "\t  ";
        for( i = 0; i < sizeI()-4; i += 5)
            dumpContext << "    |";   
        dumpContext << "\n";
            
        //  die Daten ausgeben
        for( j = sizeJ()-1; j >= 0; j--)
        {
            // vertikale Unterteilungen
            if( (j+1) % 10 == 0 )
        	dumpContext << "\t--";
            else if( (j+1) % 5 == 0 )
        	dumpContext << "\t -";
            else
        	dumpContext << "\t  ";
            
            for( i = 0; i < sizeI(); i++)
        	switch( cell(i,j).type() )
        	{
        	case CNastCell2d::FLUID:
        	    dumpContext << "."; 
        	    break;
        	case CNastCell2d::BARRIER:
        	    dumpContext << "#"; 
        	    break;
        	case CNastCell2d::EMPTY:
        	    dumpContext << " ";
        	    break;
        	default:
        	    NAST_ASSERT( false ); // unbekannter Typ
        	}
            dumpContext << "\n";
        }
    }

    dumpContext << "Box : " << m_box;
//    printFluid( *this, dumpContext );
}

void 
CNastCellField2d::assertValid() const
{
    // zuerst einmal AssertValid der Basisklasse aufrufen
    CNastObject::assertValid(); 
}


