/*   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 "damage.h"
#include "main.h"
#include "palette.h"
#include "player.h"
#include "map.h"
#include "lookup.h"

BITMAP *numbers[10];
BITMAP *chat = 0;

void _draw_scaled_border(BITMAP *source, BITMAP *dest, int x, int y, float scale, int color)
{
 int w = (int)(source->w * scale);
 int h = (int)(source->h * scale);
 if(x >= dest->w || y >= dest->h || x + w < 0 || y + h < 0) return;
 int stx = 0, sty = 0;
 if(x < 0) { stx = -x; }
 if(y < 0) { sty = -y; }
 if(x+w >= dest->w) { w = dest->w-x-1; }
 if(y+h >= dest->h) { h = dest->h-y-1; }
 int last_pixel = 0;
 int coord_x,coord_y;
 int up_row[w];
 memset(up_row,0,w*sizeof(int));
 for(int i=sty; i<h; i++,last_pixel=0)
  for(int j=stx; j<w; j++)
  {
   coord_y = (int)(i/scale);
   coord_x = (int)(j/scale);
   if(source->line[coord_y][coord_x] != last_pixel || source->line[coord_y][coord_x] != up_row[j])
   {
    up_row[j] = last_pixel = source->line[coord_y][coord_x];
    dest->line[i+y][j+x] = color_map->data[dest->line[i+y][j+x]][color];
   }
  }

}

Damage::Damage(unsigned int v, int c, int startx, int starty, float _vx, float _vy)
: reverse_scale(false), value(v), color(c)
{
 sort_y = 64000;
 y = starty;
 x = startx;
 fx = startx;
 fy = starty;
 scale = 0.1;
 len = 0;
 vx = _vx;
 vy = _vy;
 int mul = 1;
 for(int i=0; i<DAMAGE_MAX_LENGTH; i++)
 {
  str[i] = (value/mul)%10;
  mul *= 10;
  if(str[i] != 0) len = i+1;
 }
}

void Damage::think()
{
 if(show_delay) { show_delay--; return; }
 if(reverse_scale)
  scale -= 0.2;
 else
  scale += 0.2;

 fx += vx;
 fy += vy;
 vy += 0.2;

 if(scale > 5.0)
  reverse_scale = true;
 if(scale < 0.1)
  remove = true;
}

void Damage::draw_top()
{
 if(remove) return;
 color_map = trans_map+2;
 for(int i=0; i<len; i++)
  _draw_scaled_border(numbers[(int)str[i]],buf,
                      (int)fx - cam_x - (int)(numbers[0]->w*scale*(i+1)) + (int)(numbers[0]->w*scale*len/2),
                      (int)fy - cam_y - (int)(numbers[0]->h*scale/2),scale,
                      color);
}


DelayEnd::DelayEnd(int m)
: max(m)
{
 radius = 1;
 sort_y = 64000;
}

void DelayEnd::think()
{
 radius += (max-radius)/4 + 1;
 if(radius > max) remove = true;
}

void _delay_end_pixel(BITMAP *bmp, int x, int y, int d)
{
 if(x < 0 || y < 0 || x >= bmp->w || y >= bmp->h) return;
 if(d) { if(!(y%d)) bmp->line[y][x] = color_map->data[ bmp->line[y][x] ][ 140 ]; }
 else bmp->line[y][x] = color_map->data[ bmp->line[y][x] ][ 140 ];
}

void DelayEnd::draw_top()
{
 color_map = trans_map + 2;
 do_circle(buf,player->x - cam_x + 8, player->y - cam_y,radius,radius>(max-10)?radius-(max-11):0,_delay_end_pixel);
}

RegenWave::RegenWave()
{
 x = player->x + 8;
 y = player->y + 8;
 radius = 24;
 sort_y = 0;
}

void RegenWave::think()
{
 radius++;
 if(radius > 200) remove = true;
}

void _regen_wave_pixel(BITMAP *bmp, int x, int y, int d)
{
 if(x < 0 || y < 0 || x >= bmp->w || y/2 >= bmp->h) return;
 if(y % d) return;
 bmp->line[y/2][x] = color_map->data[ bmp->line[y/2][x] ][ 138 ];
}

void RegenWave::draw_lower()
{
 /*if(radius < 150)*/ color_map = trans_map + 6;
 //else color_map = trans_map + 6 + (radius-151)/25;
 do_circle(buf,x - cam_x, (y - cam_y)*2,radius/2,radius<50?1:(radius-49)/10 + 1,_regen_wave_pixel);
}

ChatSymbol::ChatSymbol(int _char_num)
: phase(0), h(0), char_num(_char_num)
{
 if(!objects[char_num]) return;
 x = objects[char_num]->x;
 y = objects[char_num]->y - 16;
 sort_y = 32000;
}

void ChatSymbol::think()
{
 if(!objects[char_num]) { remove = true; return; }
 x = objects[char_num]->x;
 y = objects[char_num]->y - 24;

 phase++;
 if(phase < 16) h = phase; else
 if(phase > 107) h = 120 - phase; else
 h = 16;
 if(phase > 120) remove = true;
}

void ChatSymbol::draw_top()
{
 masked_stretch_blit(chat,buf,0,0,16,16,x-cam_x,phase>16 ? y-cam_y : y-cam_y+16-h,16,h);
}

FlashText::FlashText(char *t, Object *targ)
{
 strcpy(text,t);
 l = strlen(text)+1;
 target = targ;
 x = target->x;
 y = target->y - 32;
 sort_y = 64000;
 phase = 0;
 color = 240;
}

void FlashText::think()
{
 x = target->x + 8 - (l/2*5);
 y = target->y - 32;
 phase++;
 if(phase%5 == 0) color++;
 if(color > 255) color = 240;
 if(phase > 120) remove = true;
}

void FlashText::draw_top()
{
 int coords_x[l];
 if(phase < 30)
  for(int i = 0; i < l; i++)
   coords_x[i] = 160 - (int)(phase/30.0 * 160.0) + i;
 else if(phase > 90)
  for(int i = 0; i < l; i++)
   coords_x[i] =  (int)((phase-90)/30.0 * -160.0) + i; else
  for(int i = 0; i < l; i++)
   coords_x[i] = i * 5;
 char t[2];
 t[1] = 0;

 for(int i = 0; i < l; i++)
 {
  t[0] = text[i];
  textout_ex(buf,font,t,x - cam_x + coords_x[i] + 1,y - cam_y+1, 0, -1);
  textout_ex(buf,font,t,x - cam_x + coords_x[i],y - cam_y, color, -1);
 }
}

void damage_init()
{
 for(int i=0; i<10; i++)
 {
  numbers[i] = create_bitmap(5,12);
  textprintf_ex(numbers[i],font,0,0,255,0,"%d",i);
 }
 chat = (BITMAP*)maindata[DATA_CHAT].dat;
}

void damage_cleanup()
{
 for(int i=0; i<10; i++)
  destroy_bitmap(numbers[i]);
}
