/*  EQEMu:  Everquest Server Emulator
Copyright (C) 2001-2002  EQEMu Development Team (http://eqemu.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 except by those people which sell it, which
	are required to give you total support for your newly bought product;
	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 "../common/debug.h"
#include <iostream>
#include <stdlib.h>
using namespace std;

#include "doors.h"
#include "entity.h"
#include "groups.h"
#include "PlayerCorpse.h"
#include "object.h"
#include "client.h"
#include "../common/database.h"
#include "../common/packet_functions.h"
#include "../common/packet_dump.h"

#include <string.h>

extern Database database;
extern EntityList entity_list;

Doors::Doors(const Door* door)
{
    db_id = door->db_id;
    door_id = door->door_id;
    strncpy(zone_name,door->zone_name,16);
    strncpy(door_name,door->door_name,16);
    pos_x = door->pos_x;
    pos_y = door->pos_y;
    pos_z = door->pos_z;
    heading = door->heading;
    opentype = door->opentype;
    guildid = door->guildid;
    lockpick = door->lockpick;
    keyitem = door->keyitem;
    trigger_door = door->trigger_door;
    trigger_type = door->trigger_type;
	triggered=false;
    liftheight = door->liftheight;
    isopen = false;

    close_timer = new Timer(5000);
    close_timer->Disable();
    
    strncpy(dest_zone,door->dest_zone,16);
    dest_x = door->dest_x;
    dest_y = door->dest_y;
    dest_z = door->dest_z;
    dest_heading = door->dest_heading;

}

Doors::~Doors()
{
    safe_delete(close_timer);
}

bool Doors::Process()
{
    if(close_timer && close_timer->Check() && isopen)
    {
		triggered=false;
        close_timer->Disable();
        isopen=false;
    }
	return true;
}

void Doors::HandleClick(Client* sender)
{
 #if EQDEBUG>=5  
        LogFile->write(EQEMuLog::Debug, "Doors:HandleClick(%s)", sender->GetName());
        DumpDoor();
#endif
	if(GetTriggerType() == 255) { // this object isnt triggered
		return;
	}
#if 1
    APPLAYER* outapp = new APPLAYER(OP_MoveDoor, sizeof(MoveDoor_Struct));
	MoveDoor_Struct* md=(MoveDoor_Struct*)outapp->pBuffer;
	//DumpPacket(app);
	md->doorid = door_id;
	/////////////////////////////////////////////////////////////////
	//used_pawn: Locked doors! Rogue friendly too =) 
	//TODO: add check for other lockpick items 
	//////////////////////////////////////////////////////////////////
	if((GetKeyItem()==0&&GetLockpick()==0) 
	   || (GetKeyItem()==sender->GetItemIDAt(0))
	   || (IsDoorOpen() && opentype == 58)) { 
		//door not locked, or door is locked & client is using key 
		if( !IsDoorOpen() || opentype == 58 ) { 
			//currentdoor->HandleClick(this); 
			md->action = 0x02; 
		} 
		else { 
			//currentdoor->HandleClick(this); 
			md->action = 0x03; 
		} 
	} 
	else { 
		//door is locked, client is NOT using key 
		if(sender->GetSkill(35)>0&&GetLockpick()!=0) {
			bool has_lockpicks=false; 
			float modskill=0.0f; 
			const ItemInst* inst = sender->GetInv().GetItem(SLOT_CURSOR);
			if (inst && inst->IsType(ItemTypeCommon)) {
				if (inst->GetItem()->Common.Skill == 12) {
					modskill=sender->GetSkill(35);
					has_lockpicks=true; 
				}
			}
			if(has_lockpicks) {
#if EQDEBUG>=5
					LogFile->write(EQEMuLog::Debug,"Client has lockpicks: skill=%f", modskill);
#endif
				if(GetLockpick() <= modskill) { // lockpick is the minimum skill needed to open the lock
					if(rand()%100<2)
						sender->IncreaseSkill(35);
					if(!IsDoorOpen()) { 
						//currentdoor->HandleClick(this); 
						md->action = 0x02; 
					} 
					else { 
						//currentdoor->HandleClick(this); 
						md->action = 0x03; 
					}
					sender->Message(4,"You picked the lock!");
				} 
				else { 
					sender->Message(4,"Your skill is not high enough for this door.");
					return;
				} 
			} 
			else { 
				sender->Message(4,"It's locked and you don't have the key!");
				return;
			} 
		}
		else if (sender->GetSkill(35)>0){
			sender->Message(4,"This lock can not be picked.");
			return;
		}
	} 
	int8 action = md->action;
	entity_list.QueueClients(sender,outapp,false);
	safe_delete(outapp);
	if(GetTriggerDoorID() != 0){
		Doors* triggerdoor = entity_list.FindDoor(GetTriggerDoorID());
		if(triggerdoor && !triggerdoor->triggered) {
			triggered=true;
            if(!triggerdoor->IsDoorOpen()) {
				triggerdoor->HandleClick(sender);
				action = 0x02;
			}
			else {
				triggerdoor->HandleClick(sender);
				action = 0x03;
			}
/*
			//printf("%i %i\n",door->trigger_door,action);
			//printf("Triggering: %i\n",door->trigger_door);
			outapp = new APPLAYER(OP_MoveDoor, sizeof(MoveDoor_Struct));
			MoveDoor_Struct* md=(MoveDoor_Struct*)outapp->pBuffer;
			md->doorid = triggerdoor->GetDoorID();
			md->action = action;
			entity_list.QueueClients(sender,outapp,false);
			delete outapp;
*/
		}
		else
			triggered=false;
	}
						//#endif

    if(!isopen || opentype == 58) {
        close_timer->Start();
        isopen=true;
    }
    else {
        close_timer->Disable();
        isopen=false;
    }
	#endif
    if (opentype == 58 && strncmp(dest_zone,"NONE",sizeof("NONE")) != 0 ){ // Teleport door!
        if ( strncmp(dest_zone,zone_name,sizeof(zone_name)) == 0){
            sender->GMMove(dest_x,dest_y,dest_z);
        }
        else {
           	sender->MovePC(dest_zone, dest_x, dest_y, dest_z);
        }
    }
}
void Doors::DumpDoor(){
    LogFile->write(EQEMuLog::Debug,
        "db_id:%i door_id:%i zone_name:%s door_name:%s pos_x:%f pos_y:%f pos_z:%f heading:%f",
        db_id, door_id, zone_name, door_name, pos_x, pos_y, pos_z, heading);
    LogFile->write(EQEMuLog::Debug,
        "opentype:%i guildid:%i lockpick:%i keyitem:%i trigger_door:%i trigger_type:%i liftheight:%i open:%s",
        opentype, guildid, lockpick, keyitem, trigger_door, trigger_type, liftheight, (isopen) ? "open":"closed");
    LogFile->write(EQEMuLog::Debug,
        "dest_zone:%s dest_x:%f dest_y:%f dest_z:%f dest_heading:%f",
        dest_zone, dest_x, dest_y, dest_z, dest_heading);
}

