/*
 *  Abuse - dark 2D side-scrolling platform game
 *  Copyright (c) 1995 Crack dot Com
 *  Copyright (c) 2005-2011 Sam Hocevar <sam@hocevar.net>
 *
 *  This software was released into the Public Domain. As with most public
 *  domain software, no warranty is made or implied by Crack dot Com, by
 *  Jonathan Clark, or by Sam Hocevar.
 */

#if defined HAVE_CONFIG_H
#   include "config.h"
#endif

#include "common.h"

#include "sbar.h"
#include "view.h"
#include "lisp.h"
#include "cache.h"
#include "demo.h"
#include "chars.h"
#include "objects.h"
#include "game.h"
#include "clisp.h"

status_bar sbar;

status_bar::status_bar()
{
  v=NULL;
  need_rf=1;
  changed_cursor=0;
  icon_in_selection=-1;  // the weapon the mouse cursor is on top of, -1 if none
  currently_selected_weapon=-1;
}

// defined in dev.c
void scale_put_trans(image *im, image *screen, int x, int y, short new_width, short new_height);
void scale_put(image *im, image *screen, int x, int y, short new_width, short new_height);
extern image *small_render;


void status_bar::load()
{
  char sbname[100];
  char iname[20];
  void *l_name = LSymbol::FindOrCreate("sbar_file");
  if (symbol_value(l_name)!=l_undefined)
    strcpy(sbname,lstring_value(symbol_value(l_name)));
  else strcpy(sbname,"art/statbar.spe");

  int i;
  for (i=0; i<TOTAL_WEAPONS; i++)
  {
    sprintf(iname,"bweap%04d.pcx",i+1);
    bweap[i]=cache.reg(sbname,iname,SPEC_IMAGE);

    sprintf(iname,"dweap%04d.pcx",i+1);
    dweap[i]=cache.reg(sbname,iname,SPEC_IMAGE);
  }

  for (i=0; i<30; i++)
  {
    sprintf(iname,"bnum%02d",i);
    bnum[i]=cache.reg(sbname,iname,SPEC_IMAGE);
  }


  sbar=cache.reg(sbname,"sbar",SPEC_IMAGE);
  sbar_select=cache.reg(sbname,"sbar_select",SPEC_IMAGE);
  sbar_numpad=cache.reg(sbname,"sbar_numpad",SPEC_IMAGE);
}

void status_bar::draw_num(image *screen, int x, int y, int num, int *offset)
{
  if (num<0 || num>999)
  {
    printf("bad number for statbar\n");
    return ;
  }

  image *im=cache.img(*offset);
  int dw=small_render ? im->Size().x*2 : im->Size().x;
  int dh=small_render ? im->Size().y*2 : im->Size().y;

  int n=num/100;
  scale_put(cache.img(offset[n]),screen,x,y,dw,dh);
  num-=n*100;

  x+=dw; n=num/10;
  scale_put(cache.img(offset[n]),screen,x,y,dw,dh);
  num-=n*10;

  x+=dw;
  scale_put(cache.img(offset[num]),screen,x,y,dw,dh);
}

void status_bar::redraw(image *screen)
{
  need_rf=0;
  if (!v) return ;

  if (total_weapons)
  {
    if (!playing_state(the_game->state)) return ;

    image *sb=cache.img(sbar);

    // status bar width & height
    int sb_w=(small_render ? sb->Size().x*2 : sb->Size().x),
    sb_h=(small_render ? sb->Size().y*2 : sb->Size().y);

    // status bar x & y position
    int sx=xres/2-sb_w/2,sy=yres-sb_h;

    // weapon x offset, and x add increment
    int wx=small_render ? 80 : 40,wa=small_render ? 34*2 : 34;

    // weapon icon width & height
    int ww=small_render ? cache.img(bweap[0])->Size().x*2 : cache.img(bweap[0])->Size().x;
    int wh=small_render ? cache.img(bweap[0])->Size().y*2 : cache.img(bweap[0])->Size().y;


    // numpad y offset
    int np_yo=small_render ? 42 : 21;
    int np_w=small_render ? cache.img(sbar_numpad)->Size().x*2 : cache.img(sbar_numpad)->Size().x;
    int np_h=small_render ? cache.img(sbar_numpad)->Size().y*2 : cache.img(sbar_numpad)->Size().y;

    // selection bar width * height
    int sel_w=small_render ? cache.img(sbar_select)->Size().x*2 : cache.img(sbar_select)->Size().x;
    int sel_h=small_render ? cache.img(sbar_select)->Size().y*2 : cache.img(sbar_select)->Size().y;

    int sel_off=small_render ?  8 : 4;
    scale_put(sb,screen,sx,sy,sb_w,sb_h);

    if (v->focus)
      draw_num(screen,sx+(small_render ? 17*2 : 17),sy+(small_render ? 11*2 : 11),v->focus->hp(),bnum);

    int ammo_x,ammo_y;
    if (small_render)
    {
      ammo_x=sx+52*2;
      ammo_y=sy+25*2;
    } else { ammo_x=sx+52; ammo_y=sy+25; }

    int i,x_on=sx+wx,t=TOTAL_WEAPONS;
    if (t>=total_weapons) t=total_weapons;
    for (i=0; i<t; i++,x_on+=wa,ammo_x+=wa)
    {
      if (v->has_weapon(i))
      {
    if (v->current_weapon==i)
        scale_put_trans(cache.img(bweap[i]),screen,x_on,sy,ww,wh);
    else
        scale_put_trans(cache.img(dweap[i]),screen,x_on,sy,ww,wh);

    scale_put_trans(cache.img(sbar_numpad),screen,x_on-2,sy+np_yo,np_w,np_h);

    if (v->current_weapon==i)
          draw_num(screen,ammo_x,ammo_y,v->weapon_total(i),bnum+20);
    else
          draw_num(screen,ammo_x,ammo_y,v->weapon_total(i),bnum+10);

    if (i==icon_in_selection)
        scale_put_trans(cache.img(sbar_select),screen,x_on+sel_off,sy,sel_w,sel_h);
      }
    }
  }
}

void status_bar::area(int &x1, int &y1, int &x2, int &y2)
{
  if (sbar<=0 || !total_weapons)
  {
    x2=xres;
    y2=yres;
    x1=x2;
    y1=y2;
    return ;
  }

  image *sb=cache.img(sbar);

  // status bar width & height
  int sb_w=sb->Size().x,
      sb_h=sb->Size().y;

  if (small_render) { sb_w*=2; sb_h*=2; }

  x1=xres/2-sb_w/2;
  x2=xres/2+sb_w/2;
  y1=yres-sb_h;
  y2=yres;
}


void status_bar::draw_health(image *screen,int amount)
{
  if (total_weapons)
  {
    int x1,y1,x2,y2;
    area(x1,y1,x2,y2);
    draw_num(screen,x1+(small_render ? 17*2 : 17),y1+(small_render ? 11*2 : 11),amount,bnum);
  }
}


void status_bar::draw_ammo(image *screen, int weapon_num, int amount, int light)
{
  if (total_weapons)
  {
    int x1,y1,x2,y2;
    area(x1,y1,x2,y2);
    draw_num(screen,
        x1+(small_render ? 52*2+weapon_num*34*2 : 52+weapon_num*34),
        y1+(small_render ? 25*2 : 25),amount,bnum+(light ? 20 : 10));
  }
}


int status_bar::mouse_in_area()
{
  if (!v) return 0;
  int x1,y1,x2,y2;
  area(x1,y1,x2,y2);

  int mx,my;
  if (small_render)
  {
    mx=(v->pointer_x-v->cx1)*2+v->cx1;
    my=(v->pointer_y-v->cy1)*2+v->cy1;
  } else
  {
    mx=v->pointer_x;
    my=v->pointer_y;
  }

  if (mx>=x1 && my>=y1 && mx<=x2 && my<=y2)
    return 1;
  else return 0;
}


void status_bar::draw_update()
{
  if (total_weapons && v)
  {
    if (DEFINEDP(symbol_value(l_mouse_can_switch)) && symbol_value(l_mouse_can_switch) &&
    mouse_in_area())
    {
      if ((current_level->tick_counter()&4)==0)
        wm->set_mouse_shape(cache.img(c_mouse1)->copy(),4,4);
      else wm->set_mouse_shape(cache.img(c_mouse2)->copy(),4,4);
      changed_cursor=1;
    } else if (changed_cursor)
    {
      if (!(dev&EDIT_MODE))
        wm->set_mouse_shape(cache.img(c_target)->copy(),8,8);
      else
        wm->set_mouse_shape(cache.img(c_normal)->copy(),1,1);
      changed_cursor=0;
    }

    if (need_rf)
      redraw(screen);
  }
}


void status_bar::step()
{
  if (!v) return ;
  if (!DEFINEDP(symbol_value(l_mouse_can_switch)) || !symbol_value(l_mouse_can_switch)) return ;

  int sb_w,sb_h;
  if (sbar>0 && total_weapons)
  {
    image *sb=cache.img(sbar);

    // status bar width & height
    sb_w=sb->Size().x;
    sb_h=sb->Size().y;
  }

  // see if the mouse is in the sbar region (demo_x already corrected for small_render)
  int sx1,sy1,sx2,sy2;
  area(sx1,sy1,sx2,sy2);

  int view_y2=small_render ? (v->cy2-v->cy1+1)*2+v->cy1 : v->cy2;
  if (sy1<view_y2)     // tell view to shrink if it is overlapping the status bar
  {
    v->suggest.send_view=1;
    v->suggest.cx1=v->cx1;
    v->suggest.cy1=v->cy1;
    v->suggest.cx2=v->cx2;
    v->suggest.cy2=small_render ? (sy1-v->cy1-2)/2+v->cy1 : sy1-2;
  }

  if (sbar<=0 || !total_weapons) return ;


  int mx=small_render ? (last_demo_mx-v->cx1)*2+v->cx1 : last_demo_mx;
  int my=small_render ? (last_demo_my-v->cy1)*2+v->cy1 : last_demo_my;


  if (mx>sx1 && my>sy1 && mx<sx2 && my<sy2)
  {

    int new_target;

    mx-=sx1;
    if (small_render) mx/=2;


    mx-=47;
    if (mx<0) new_target=0;
    else
    {
      new_target=mx/33;
      if (new_target>=TOTAL_WEAPONS)
        new_target=TOTAL_WEAPONS-1;
      if (new_target>=total_weapons)
        new_target=total_weapons-1;
    }

    if (v->has_weapon(new_target) && new_target!=icon_in_selection)
    {
      icon_in_selection=new_target;
      need_refresh();
    }

    if (last_demo_mbut==2 && icon_in_selection!=v->current_weapon &&
    icon_in_selection!=-1) // the user requested a weapon change
    {
      v->suggest.send_weapon_change=1;
      v->suggest.new_weapon=icon_in_selection;
    }

  } else
  {
    if (icon_in_selection!=-1)
    {
      icon_in_selection=-1;
      need_refresh();
    }
  }

  // see if a new weapon has been selected other than the one
  // we think is selected, if so redraw the status bar
  if (currently_selected_weapon!=v->current_weapon)
  {
    currently_selected_weapon=v->current_weapon;
    need_refresh();
  }


}