/*
 *
 * Copyright (C) 2003 Atomic Blue (info@planeshift.it, http://www.atomicblue.org) 
 *
 *
 * 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 (version 2 of the License)
 * 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 <psconfig.h>

#include <iengine/mesh.h>
#include <iengine/movable.h>

#include <propclass/linmove.h>

#include "gem.h"
#include "npc.h"
#include "globals.h"
#include "networkmgr.h"
#include "util/consoleout.h"


//-------------------------------------------------------------------------------
psNPCClient *gemNPCObject::cel = NULL;

gemNPCObject::gemNPCObject( psNPCClient* cel, PS_ID id )
    :visible(true)
{
    if (!this->cel)
        this->cel = cel;

    entity = cel->GetPlLayer()->CreateEntity(id);
}    

gemNPCObject::~gemNPCObject()
{
    NPC *npc = cel->FindAttachedNPC(entity);
    if (npc)
    {
        if(entity != npc->GetEntity())
        {
            const char* debug1 = npc->GetName();
            const char* debug2 = name.GetData();
            unsigned int debug3 = entity->GetID();
            CPrintf(CON_DEBUG, "Deactivating NPC %s - %s, %u.\n", debug1, debug2, debug3 );
            CS_ASSERT_MSG("Failed to deactivate NPC!", entity == npc->GetEntity());
        }
        npc->SetEntity(NULL);
        npc->ClearState();
    }

    cel->GetPlLayer()->RemoveEntity( entity );    
}

void gemNPCObject::Move(const csVector3& pos,float rotangle,  const char* room)
{
    csRef<iEngine> engine = CS_QUERY_REGISTRY(cel->GetObjectReg(), iEngine);

    // Position and sector
    iSector* sector = engine->FindSector(room);
    if ( sector == NULL )
        CPrintf(CON_DEBUG, "No Sector Found!\n");
    pcmesh->MoveMesh( sector , pos );

    // Rotation
    csMatrix3 matrix = (csMatrix3) csYRotMatrix3 (rotangle);
    pcmesh->GetMesh()->GetMovable()->GetTransform().SetO2T (matrix);
   
}    

bool gemNPCObject::InitMesh(  
                                const char *factname,
                                const char *filename,
                                const csVector3& pos,
                                const float rotangle,
                                const char* room
                             )
{
    csRef<iCelPropertyClass> pc;
    
    pc = cel->GetPlLayer()->CreatePropertyClass(entity, "pcmesh");
    if ( !pc )
    {
        Error1("Could not create Item because pcmesh class couldn't be created.");
        return false;
    }

    pcmesh = SCF_QUERY_INTERFACE ( pc, iPcMesh );
    if ( !pcmesh )
    {
        Error1("Could not create Item because pcmesh class doesn't implement iPcMesh.");
        return false;
    }

    if (!pcmesh->SetMesh(factname, filename))
    {
        Error3("Could not set mesh with factname=%s and filename=%s. Trying dummy model",factname,filename);                
        factname = "stonebm";
        filename = "/planeshift/models/stonebm/stonebm.cal3d";
        if ( !pcmesh->SetMesh(factname, filename) )
        {
            Error3("Could not use dummy CVS mesh with factname=%s and filename=%s",factname,filename);        
            return false;
        }
    }

    iMeshWrapper* mesh = pcmesh->GetMesh();
    if ( !mesh )
    {
        Error1("Could not create Item because pcmesh didn't have iMeshWrapper.");
        return false;
    }

    Move(pos,rotangle,room);

    return true;
}



 

gemNPCActor::gemNPCActor( psNPCClient* cel, psPersistActor& mesg) 
               : gemNPCObject( cel, mesg.entityid )
{
    name = mesg.name;
    entity->SetName( mesg.name );
    id = mesg.entityid;
    type = mesg.type;
    playerID = mesg.playerID;
    ownerID = mesg.ownerID;
    race = mesg.race;
    SetVisible( ! mesg.flags & psPersistActor::INVISIBLE );

    CPrintf( CON_DEBUG, "Actor %s(%u) Received", mesg.name.GetData(), mesg.entityid );
    InitMesh(  mesg.factname, mesg.filename, mesg.pos, mesg.yrot, mesg.sectorName );
    InitLinMove( mesg.pos, mesg.yrot, mesg.sectorName, mesg.top, mesg.bottom, mesg.offset );
    InitCharData( mesg.texParts, mesg.equipment );  
}

gemNPCActor::~gemNPCActor()
{
    
}

bool gemNPCActor::InitCharData( const char* textParts, const char* equipment )
{                   
    return true;    
}    

bool gemNPCActor::InitLinMove(const csVector3& pos, float angle, const char* sector,
                                csVector3 top, csVector3 bottom, csVector3 offset )
{
    csRef<iCelPropertyClass> pc;
    pc = cel->GetPlLayer()->CreatePropertyClass(entity, "pclinearmovement");
    if ( !pc )
    {
        Error1("Could not create property class pclinearmovement.  Actor not created.");
        return false;
    }
    pcmove = SCF_QUERY_INTERFACE(pc, iPcLinearMovement);

    csRef<iEngine> engine = CS_QUERY_REGISTRY(cel->GetObjectReg(), iEngine);

    top.x *= .7f;
    top.z *= .7f;
    bottom.x *= .7f;
    bottom.z *= .7f;
    pcmove->InitCD(top, bottom,offset, NULL); 
    pcmove->SetPosition(pos,angle,engine->FindSector(sector));
    
    return true;  // right now this func never fail, but might later.
}


gemNPCItem::gemNPCItem( psNPCClient* cel, psPersistItem& mesg) 
    : gemNPCObject( cel, mesg.id ), flags(NONE)
{        
    name = mesg.name;
    Debug3( LOG_CELPERSIST, 0,"Item %s(%d) Received", mesg.name.GetData(), mesg.id );
    entity->SetName( mesg.name );
    id = mesg.id;
    type = mesg.type;
    InitMesh(  mesg.factname, mesg.filename, mesg.pos, mesg.yRot, mesg.sector );
    if (mesg.flags & psPersistItem::NOPICKUP) flags |= NOPICKUP;
}

//Here we check the flag to see if we can pick up this item
bool gemNPCItem::IsPickable() { return !(flags & NOPICKUP); }

