/*   Copyright 2005,2006 Paweł Niegowski
*
*    This file is part of Fenrir.
*
*    Fenrir 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.
*
*    Fenrir 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 Fenrir; if not, write to the Free Software
*    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
*/
#include "item.h"
#include "main.h"
#include "network.h"
#include "object.h"
#include "script.h"
#include "palette.h"
#include "lookup.h"
#include "skill.h"
#include <stdio.h>
#include <math.h>

list<Item> inventory_use,inventory_etc,inventory_loot;
list<EquipItem> inventory_equip;
int selected_item = 0,selected_inv = 0;

ItemDatabaseEntry item_use_db[MAX_ITEMS];
ItemDatabaseEntry item_etc_db[MAX_ITEMS];
MonsterDatabaseEntry monster_db[MAX_MONSTERS];
char tmp[DESC_LINE_LENGTH],tmp2[300];

int item_delay = 0;

DATAFILE *itemuse = 0, *itemetc = 0;

void item_parse_use(FILE *f)
{
 int i = 0;
 fscanf(f,"%d",&i);
 item_use_db[i].id = i;
 fscanf(f,"%d ",&item_use_db[i].type);
 char c = 0;
 int cnt = 0;
 do
 {
  c = fgetc(f);
  item_use_db[i].name[cnt++] = c;
 }
 while(c != '\n' && c != '\r');
 item_use_db[i].name[cnt-1] = 0;
 fscanf(f,"%d ",&item_use_db[i].datanum);
 //loading description
  fgets(tmp,DESC_LINE_LENGTH,f);
 do
 {
  for(int j = 0; j < DESC_LINE_LENGTH; j++)
   if(tmp[j] == '\n' || tmp[j] == '\r') tmp[j] = 0;
  item_use_db[i].description.push_back(_DescriptionLine(tmp));
  fgets(tmp,DESC_LINE_LENGTH,f);
 }
 while(tmp[0] != '#');
 //loading script
 item_use_db[i].script = new char[SCRIPT_MAX_LENGTH];
 char *ptr = item_use_db[i].script;
 fgets(ptr,300,f);
 while(ptr[0] != '#')
 {
  for(int i = 0; i < 300; i++)
   if(ptr[i] == '\n')
   { ptr += i+1; break; }
  fgets(ptr,300,f);
 }
 ptr[0] = 0;
 fgetc(f);
 //for debug purposes
 //allegro_message(item_use_db[i].name);
}

void item_parse_etc(FILE *f)
{
 int i = 0;
 fscanf(f,"%d",&i);
 item_etc_db[i].id = i;
 fscanf(f,"%d ",&item_etc_db[i].type);
 char c = 0;
 int cnt = 0;
 do
 {
  c = fgetc(f);
  item_etc_db[i].name[cnt++] = c;
 }
 while(c != '\n' && c != '\r');
 item_etc_db[i].name[cnt-1] = 0;
 fscanf(f,"%d ",&item_etc_db[i].datanum);
 //loading description
  fgets(tmp,DESC_LINE_LENGTH,f);
 do
 {
  for(int j = 0; j < DESC_LINE_LENGTH; j++)
   if(tmp[j] == '\n' || tmp[j] == '\r') tmp[j] = 0;
  item_etc_db[i].description.push_back(_DescriptionLine(tmp));
  fgets(tmp,DESC_LINE_LENGTH,f);
 }
 while(tmp[0] != '#');
 fgetc(f);
 //for debug purposes
 //allegro_message(item_etc_db[i].name);
}


void item_load_itemdb()
{
 FILE *f = fopen("data/items_use.txt","r");
 if(!f) allegro_message("ERROR: data/items_use.txt not found.\n");
 fgetc(f);
 while(!feof(f))
  item_parse_use(f);
 fclose(f);

 f = fopen("data/items_etc.txt","r");
 if(!f) allegro_message("ERROR: data/items_etc.txt not found.\n");
 fgetc(f);
 while(!feof(f))
  item_parse_etc(f);
 fclose(f);
}

void item_load_monsterdb()
{
 FILE *f = fopen("data/monsters.txt","r");
 if(!f) allegro_message("ERROR: data/monsters.txt not found.\n");
 int linecount = 0;
 while(!feof(f))
  if(fgetc(f) == '\n')
   linecount++;
 fseek(f,0,SEEK_SET);
 unsigned short id = 0;
 for(int i = 0; i < linecount; i++)
 {
  fscanf(f,"%hu ",&id);
  monster_db[id].id = id;
  fgets(monster_db[id].name,30,f);
  for(int j = 0; j < 30; j++)
   if(monster_db[id].name[j] == '\n' || monster_db[id].name[j] == '\n')
    monster_db[id].name[j] = 0;
 }
 fclose(f);
}

void item_init()
{
 item_load_itemdb();
 item_load_monsterdb();
 itemuse = load_datafile("gfx/itemuse.dat");
 if(!itemuse) allegro_message("gfx/itemuse.dat not found.\n");
 itemetc = load_datafile("gfx/itemetc.dat");
 if(!itemetc) allegro_message("gfx/itemetc.dat not found.\n");
// item_add(0,0,10);
 //item_add(0,1,5);
}

void item_cleanup()
{
 unload_datafile(itemuse);
 unload_datafile(itemetc);
}

void item_add(int inv, unsigned short id, unsigned short quantity)
{
 if(inv == INV_USE)
 {
  for(list<Item>::iterator it = inventory_use.begin(); it != inventory_use.end(); it++)
   if((*it).id == id)
   {
    (*it).quantity += quantity;
    return;
   }
  inventory_use.push_back(Item(id,quantity));
 }
 if(inv == INV_ETC)
 {
  for(list<Item>::iterator it = inventory_etc.begin(); it != inventory_etc.end(); it++)
   if((*it).id == id)
   {
    (*it).quantity += quantity;
    return;
   }
  inventory_etc.push_back(Item(id,quantity));
 }
 if(inv == INV_LOOT)
 {
  for(list<Item>::iterator it = inventory_loot.begin(); it != inventory_loot.end(); it++)
   if((*it).id == id)
   {
    (*it).quantity += quantity;
    return;
   }
  inventory_loot.push_back(Item(id,quantity));
 }
}

void item_remove(int inv, unsigned short id, unsigned short quantity)
{
 if(inv == INV_USE)
 {
  for(list<Item>::iterator it = inventory_use.begin(); it != inventory_use.end(); it++)
   if((*it).id == id)
   {
    if((*it).quantity > quantity)
     (*it).quantity -= quantity;
    else
     inventory_use.erase(it);
    return;
   }
 }
 if(inv == INV_ETC)
 {
  for(list<Item>::iterator it = inventory_etc.begin(); it != inventory_etc.end(); it++)
   if((*it).id == id)
   {
    if((*it).quantity > quantity)
     (*it).quantity -= quantity;
    else
     inventory_etc.erase(it);
    return;
   }
 }
 if(inv == INV_LOOT)
 {
  for(list<Item>::iterator it = inventory_loot.begin(); it != inventory_loot.end(); it++)
   if((*it).id == id)
   {
    if((*it).quantity > quantity)
     (*it).quantity -= quantity;
    else
     inventory_loot.erase(it);
    return;
   }
 }
}

void item_use(unsigned short id)
{
 unsigned char msg[3];
 msg[0] = ID_ITEMUSE;
 memcpy(msg+1,&id,2);
 network_send_packet(msg,3);
}

void item_read_inventory(Packet *packet)
{
 if(packet->length < 5) return;
 int total_length = packet->data[1]*4 + packet->data[2] + packet->data[3]*4 + packet->data[4]*4 + 5;
 if(packet->length < total_length) return;
 unsigned char *ptr = packet->data+5;
 unsigned short id, quantity;
 inventory_use.clear();
 inventory_etc.clear();
 inventory_loot.clear();
 for(int i = 0; i < packet->data[1]; i++)
 {
  memcpy(&id,ptr,2);
  memcpy(&quantity,ptr+2,2);
  item_add(INV_USE,id,quantity);
  ptr += 4;
 }
 //equip should be here
 for(int i = 0; i < packet->data[3]; i++)
 {
  memcpy(&id,ptr,2);
  memcpy(&quantity,ptr+2,2);
  item_add(INV_ETC,id,quantity);
  ptr += 4;
 }
 for(int i = 0; i < packet->data[4]; i++)
 {
  memcpy(&id,ptr,2);
  memcpy(&quantity,ptr+2,2);
  item_add(INV_LOOT,id,quantity);
  ptr += 4;
 }
 packet->length -= total_length;
 packet->data += total_length;
}

void item_render_use(Object *user, unsigned short id)
{
 if(item_use_db[id].script == 0) return;
 script_setptr("self",user);
 script_run(item_use_db[id].script);
}

char _itemname[50];
BITMAP *sprite = 0;

void item_display(int inv, unsigned short id, unsigned short quantity, int x, int y, int w, int color)
{
 if(inv == INV_USE) strcpy(_itemname,item_use_db[id].name);
 if(inv == INV_ETC) strcpy(_itemname,item_etc_db[id].name);
 if(inv == INV_LOOT) sprintf(_itemname,"%s's Loot",monster_db[id].name);
 textout_ex(buf,font,_itemname,x+18,y+2,254,-1);
 if(quantity)
  textprintf_right_ex(buf,font,x+w+2,y+2,254,-1,"x%d",quantity);
 textout_ex(buf,font,_itemname,x+16,y,color,-1);
 if(quantity)
  textprintf_right_ex(buf,font,x+w,y,color,-1,"x%d",quantity);
 if(inv == INV_LOOT) sprite = (BITMAP*)maindata[DATA_NULLITEM].dat; else
 if(inv == INV_USE) sprite = (BITMAP*)itemuse[item_use_db[id].datanum].dat; else
 if(inv == INV_ETC) sprite = (BITMAP*)itemetc[item_etc_db[id].datanum].dat;
 draw_sprite(buf,sprite,x,y);
}

LootIndicator::LootIndicator(int sx, int sy, Object *targ)
: target(targ)
{
 sort_y = 0;
 fx = x = sx; fy = y = sy;
 v = 0.1;
 for(int i = 0; i < LOOTINDICATOR_TAIL; i++)
 { prev_x[i] = sx; prev_y[i] = sy; }
 float angle = rand()%100 * 0.0628;
 vx = cos(angle) * (5.5 + rand()%100 / 100.0);
 vy = sin(angle) * (5.5 + rand()%100 / 100.0);
}

void LootIndicator::think()
{
 for(int i = LOOTINDICATOR_TAIL-1; i > 0; i--)
 {  prev_x[i] = prev_x[i - 1]; prev_y[i] = prev_y[i - 1]; }

 prev_x[0] = (int)(fx + vx/2);
 prev_y[0] = (int)(fy + vy/2);
 v += 0.003;
 float a2 = atan2(target->y-y,target->x-x+8);
  //if(ABS(angle - a2) < 0.2) v *= 0.95;
 if(ABS(vx + cos(a2) * v) < 8.0)
 vx += cos(a2) * v;
 if(ABS(vy + sin(a2) * v) < 8.0)
 vy += sin(a2) * v;
 fx += cos(a2) * v * 4;
 fy += sin(a2) * v * 4;
 fx += vx;
 fy += vy;
 x = (int)fx; y = (int)fy;
 if(kill_counter == 0) remove = true;
  if(kill_counter != -1)
 { kill_counter--; }
 if(ABS(x - target->x - 8) < 8 && ABS(y - target->y) < 8 && kill_counter == -1)
 { /*new SkillFlash(253,target);*/ kill_counter = LOOTINDICATOR_TAIL; }
}

void LootIndicator::draw_top()
{
// rect(buf,x - cam_x - 5,y - cam_y - 5,x - cam_x + 5,y - cam_y + 5,255);
 int ix, iy;
 for(int i = ((kill_counter<LOOTINDICATOR_TAIL && kill_counter > -1) ? LOOTINDICATOR_TAIL-kill_counter : 0); i < LOOTINDICATOR_TAIL; i++)
 {
  ix = prev_x[i] - cam_x;
  iy = prev_y[i] - cam_y;
  color_map = trans_map + i/2;
  if(ix < 1 || ix >= buf->w -1 || iy < 1 || iy >= buf->h - 1) continue;
  buf->line[iy][ix] = color_map->data[buf->line[iy][ix]] [253];
  buf->line[iy+1][ix] = color_map->data[buf->line[iy+1][ix]][253];
  buf->line[iy-1][ix] = color_map->data[buf->line[iy-1][ix]][253];
  buf->line[iy][ix+1] = color_map->data[buf->line[iy][ix+1]][253];
  buf->line[iy][ix-1] = color_map->data[buf->line[iy][ix-1]][253];
 }

}
