/*
 * client/ClientSide.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.
 * 
 */



#ifdef WIN32
#include <windows.h>
#endif

#include "ClientSide.h"
#include "../server/SectorSpecial.h"
#include "../server/Sector.h"

#include "../server/SideDef.h"
#include "../server/LineDef.h"
#include "../server/Lightmap.h"
#include "../util/VMath.h"
#include "../util/TextureManager.h"

//float ClientSide::lmVerts[8];

ClientSide::ClientSide( const class SideDef * side ) {
        
        float y = side->line->verts[1][1] - side->line->verts[0][1];
        float x = side->line->verts[1][0] - side->line->verts[0][0];
        float r = VMath::hypotenuse( x, y );
        
        sParms[0] = x / r;
        sParms[1] = y / r;
        sParms[2] = 0;
        sParms[3] = 0;
        
        const class SideDef * other = ( side->line->sides[0] == side ) ? side->line->sides[1] : side->line->sides[0];

        for ( int i = 0; i < 3; ++i ) {
                if ( side->textures[i] ) {
                        textures[i] = TextureManager::getTexture( side->textures[i], GL_RGB );
                }

                if ( side->hasWallSection( other, i ) ) {

                        verts[i] = new float[12];
                        
                        float zs[2] = { side->getWallSectionZOrigin( other, i ),
                                        side->getWallSectionHeight( other, i ) };
                        zs[1] += zs[0];

                        //
                        // front side
                        //
                        
                        float * endpts[2] = {
                                side->line->verts[0],
                                side->line->verts[1]
                        };
                        
                        if ( side != side->line->sides[0] ) {
                                endpts[0] = side->line->verts[1];
                                endpts[1] = side->line->verts[0];
                        }
                        
                        verts[i][0] = endpts[0][0];
                        verts[i][1] = endpts[0][1];
                        verts[i][2] = zs[0];
                        verts[i][3] = endpts[1][0];
                        verts[i][4] = endpts[1][1];
                        verts[i][5] = zs[0];
                        verts[i][6] = endpts[1][0];
                        verts[i][7] = endpts[1][1];
                        verts[i][8] = zs[1];
                        verts[i][9] = endpts[0][0];
                        verts[i][10] = endpts[0][1];
                        verts[i][11] = zs[1];
                        
                        texVerts[i] = new float[8];
                        
                        texVerts[i][0] = ( x * endpts[0][0] / r + y * endpts[0][1] / r ) / textures[i]->getSize()[0];
                        texVerts[i][1] = 0;
                        texVerts[i][2] = ( x * endpts[1][0] / r + y * endpts[1][1] / r ) / textures[i]->getSize()[0];
                        texVerts[i][3] = 0;
                        texVerts[i][4] = texVerts[i][2];
                        texVerts[i][5] = (zs[1] - zs[0]) / textures[i]->getSize()[1];
                        texVerts[i][6] = texVerts[i][0];
                        texVerts[i][7] = texVerts[i][5];

                        /*
                        using VMath::square;
                        
                        texVerts[i][0] = VMath::length2d( side->line->verts[0] ) / textures[i]->getSize()[0];
                        texVerts[i][1] = zs[0] / textures[i]->getSize()[1];
                        texVerts[i][2] = texVerts[i][0] + r / textures[i]->getSize()[0];
                        texVerts[i][3] = texVerts[i][1];
                        texVerts[i][4] = texVerts[i][2];
                        texVerts[i][5] = zs[1] / textures[i]->getSize()[1];
                        texVerts[i][6] = texVerts[i][0];
                        texVerts[i][7] = texVerts[i][5];
                        */
                        class Lightmap * lm = side->lightmaps[ i ];

                        if ( lm ) {
                                lmVerts[i][0] = 0;
                                lmVerts[i][1] = 0;
                                lmVerts[i][2] = float( lm->use_size[0] ) / lm->size[0];
                                lmVerts[i][3] = lmVerts[i][1];
                                lmVerts[i][4] = lmVerts[i][2];
                                lmVerts[i][5] = float( lm->use_size[1] ) / lm->size[1];
                                lmVerts[i][6] = 0;
                                lmVerts[i][7] = lmVerts[i][5];
                        }
                }
                else {
                        verts[i] = 0;
                        texVerts[i] = 0;
                }
        }
        
}

ClientSide::~ClientSide() {
        for ( int i = 0; i < 3; ++i ) {
                delete[] verts[i];
                delete[] texVerts[i];
        }
}

void ClientSide::adjustHeights( const class SideDef * side, const class SideDef * other ) {

        for ( int i = 0; i < 3; ++i ) {

                if ( side->hasWallSection( other, i ) ) {

                        float zs[2] = { side->getWallSectionZOrigin( other, i ),
                                        side->getWallSectionHeight( other, i ) };
                        //                       zs[1] += zs[0];

                        verts[i][2] = zs[0];
                        verts[i][5] = zs[0];
                        verts[i][8] = zs[1] + zs[0];
                        verts[i][11] = verts[i][8]; 
                        texVerts[i][5] = (zs[1]) / textures[ i ]->getSize()[1];
                        texVerts[i][7] = texVerts[ i ][5];
                        
                        if ( other && other->sector->spec ) {
                                if ( i == SideDef::UPPER &&
                                     other->sector->spec->isDoor() ) {
                                        
                                        float max_z = 
                                                zs[1] + other->sector->spec->travel - 
                                                other->sector->spec->cur_travel;
                                        // change the bottom lightmap coords for this wall
                                        lmVerts[i][1] = lmVerts[i][5] * ( max_z - zs[1] ) / max_z ;
                                        lmVerts[i][3] = lmVerts[i][1];
                                        
                                }
                                if ( i == SideDef::LOWER &&
                                     other->sector->spec->isLift() ) {
                                        class Lightmap * lm = side->lightmaps[ i ];
                                        
                                        if ( lm ) {
                                                float max_z = 
                                                        zs[1] + other->sector->spec->travel - 
                                                        other->sector->spec->cur_travel;
                                                // change the top lightmap coords for this wall
                                                lmVerts[i][5] = 
                                                        ( zs[1] ) * float( lm->use_size[1] ) / lm->size[1] / max_z;
                                                lmVerts[i][7] = lmVerts[i][5];
                                        }

                                        if ( textures[i] ) {
                                                //                                                cout << "changing tex" << endl;
                                                // change the
                                                texVerts[i][1] = -float(other->sector->spec->cur_travel) / textures[i]->getSize()[1];
                                                texVerts[i][3] = texVerts[i][1];
                                                texVerts[i][5] = zs[1] / textures[i]->getSize()[1] +  texVerts[i][1];
                                                texVerts[i][7] = texVerts[i][5];
                                        }
                                }

                        }
                        else if ( side->sector->spec ) {//&& i == SideDef::MAIN ) {
                                class Lightmap * lm = side->lightmaps[ i ];

                                float max_z = 
                                        zs[1] + 
                                        side->sector->spec->cur_travel;

                                if ( side->sector->spec->isDoor() && lm ) {
                                        // change the top lightmap coods for this wall
                                        lmVerts[i][5] = 
                                                ( zs[1] ) * float( lm->use_size[1] ) / lm->size[1] / max_z;
                                        lmVerts[i][7] = lmVerts[i][5];
                                }
                                else if ( side->sector->spec->isLift() ) {

                                        if ( lm ) {
                                                // change the bottom lightmap coords for this wall
                                                lmVerts[i][1] = lmVerts[i][5] * ( max_z - zs[1] ) / max_z ;
                                                lmVerts[i][3] = lmVerts[i][1];
                                        }

                                        if ( textures[i] ) {
                                                //                                                cout << "changing tex" << endl;
                                                // change the
                                                texVerts[i][1] = float(side->sector->spec->cur_travel) / textures[i]->getSize()[1];
                                                texVerts[i][3] = texVerts[i][1];
                                                texVerts[i][5] = zs[1] / textures[i]->getSize()[1] +  texVerts[i][1];
                                                texVerts[i][7] = texVerts[i][5];

                                        }
                                }
                        }
                }
        }
}
