/*
 * server/SideDef.cc:
 *
 * Copyright (C) 2000 John Watson, jwatson@tempusmud.com
 * 
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 * 
 * This program 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 General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 * 
 */

#include <iostream>

#include "SideDef.h"
#include "Sector.h"
#include "SectorSpecial.h"
#include "LineDef.h"
#include "Zone.h"
#include "../util/Persist.h"

SideDef::SideDef( istream & is,
                  const class Array<class LineDef *> & ls,
                  const class Array<class Sector *> & ss,
                  const class Array<const char *> & ts,
                  const class Array<class Lightmap *> & lms )
        : clientSide( 0 )
{
        components = 0;

        lightmaps[0] = lightmaps[1] = lightmaps[2] = 0;

        short sect_i  = Persist::readShort( is );
        short line_i  = Persist::readShort( is );

        sector = ss[ sect_i ];
        line   = ls[ line_i ];

        for ( int i = 0; i < 3; ++i ) {
                short ind = Persist::readShort( is );
                if ( ind >= 0 ) {
                        textures[i] = ts[ ind ];
                }
                else {
                        textures[i] = 0;
                }
        }
        
        for ( int i = 0; i < 3; ++i ) {
                short ind = Persist::readShort( is );
                if ( ind >= 0 ) {
                        lightmaps[i] = lms[ ind ];
                }
                else {
                        lightmaps[i] = 0;
                }
        }
}

void SideDef::writeSide( class ostream & os ) {
        
        const class Array<class Sector*> & sectors  = sector->getZone()->getSectors();
        const class Array<class LineDef*> &   lines = sector->getZone()->getLines();
        const class Array<const char *>  & texnames = sector->getZone()->getTexnames();
        const class Array<class Lightmap *> & lms   = sector->getZone()->getLightmaps();

        short sect_i  = sectors.findElement( sector );
        short line_i  = lines.findElement( line );

        Persist::writeShort( os, sect_i );
        Persist::writeShort( os, line_i );

        for ( int i = 0; i < 3; ++i ) {
                short ind = texnames.findElement( textures[i] );
                Persist::writeShort( os, ind );
        }

        for ( int i = 0; i < 3; ++i ) {
                short ind = lms.findElement( lightmaps[i] );
                Persist::writeShort( os, ind );
        }
}

int SideDef::getLowerHeight( const class SideDef *otherSide ) const {
        if ( otherSide && otherSide->sector->getFloorHeight() > sector->getFloorHeight() )
                return otherSide->sector->getFloorHeight() - sector->getFloorHeight();
        return 0;
}

int SideDef::getUpperHeight( const class SideDef *otherSide ) const {
        if ( otherSide && otherSide->sector->getCeilingHeight() < sector->getCeilingHeight() )
                return  (sector->getCeilingHeight() - otherSide->sector->getCeilingHeight());
        return 0;
}

int SideDef::getMainHeight(  const class SideDef *otherSide ) const {
        
        int delta = 0;

        if ( otherSide ) {
                delta = getLowerHeight( otherSide ) + getUpperHeight( otherSide );
        }
        
        return sector->getCeilingHeight() - sector->getFloorHeight() - delta;
}

int SideDef::getWallSectionZOrigin( const class SideDef * otherSide, int index ) const {
        if ( index == 0 )
                return sector->getFloorHeight();
        else if ( index == 1 )
                return sector->getFloorHeight() + getLowerHeight( otherSide );
        else if ( index == 2 )
                return sector->getCeilingHeight() - getUpperHeight( otherSide );
        else {
                cout << " error in SideDef::getWallSectionZOrigin index=" << index << endl;
        }
        
        return false;
}
void SideDef::setSideComponents( const class SideDef * other ) {
        if ( other == 0 ) {
                components |= SideDef::MAIN_BIT;
                return;
        }
                
        if ( other->sector->spec ) {
                if ( other->sector->spec->isDoor() ) {
                        components |= SideDef::UPPER_BIT;
                }
                else if ( other->sector->spec->isLift() ) {
                        components |= SideDef::LOWER_BIT;
                }
        }

        if ( other->sector->getFloorHeight() > sector->getFloorHeight() )
                components |= SideDef::LOWER_BIT;
        
        if ( other->sector->getCeilingHeight() < sector->getCeilingHeight() )
                components |= SideDef::UPPER_BIT;
}
