/*  inn.c: (c) 2002 sibn

    This file is part of GWiz.

    GWiz 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.

    GWiz 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 GWiz; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
*/

#include <SDL/SDL.h>
#include <SDL/SDL_ttf.h>
#include <stdlib.h>
#include "gwiz.h"
#include "text.h"
#include "inn.h"
#include "uiloop.h"
#include "levelup.h"

extern GwizApp gwiz;
GwizInn inn;

 void BeginStay (int whichpawn)
 {
     inn.pawn = &gwiz.pawn[whichpawn];
     inn.window = DrawInnOptions();
     inn.crect.x = BORDERWIDTH;
     inn.crect.y = BORDERHEIGHT + gwiz.font.height*2 + gwiz.font.height/2 -
		   gwiz.cursor->h/2;
     inn.crect.h = gwiz.cursor->h;
     inn.crect.w = gwiz.cursor->w;
     inn.drect.x = gwiz.canvas->w/2 - inn.window->w/2;
     inn.drect.y = gwiz.canvas->h/2 - inn.window->h/2;
     inn.drect.h = inn.window->h;
     inn.drect.w = inn.window->w;
     inn.displace = NewGwizSurface (inn.drect.w, inn.drect.h);
     SDL_BlitSurface (gwiz.canvas, &inn.drect, inn.displace, NULL);
     SDL_BlitSurface (gwiz.cursor, NULL, inn.window, &inn.crect);
     SDL_BlitSurface (inn.window, NULL, gwiz.canvas, &inn.drect);
     SDL_Flip (gwiz.canvas);
     inn.statusdisplace = NewTextBox (gwiz.canvas->w - BORDERWIDTH*2,
				      gwiz.font.height);
     SDL_BlitSurface (gwiz.canvas, NULL, inn.statusdisplace, NULL);

     ChooseBed();

     SDL_BlitSurface (inn.statusdisplace, NULL, gwiz.canvas, NULL);
     SDL_BlitSurface (inn.displace, NULL, gwiz.canvas, &inn.drect);
     SDL_FreeSurface (inn.displace);
     SDL_FreeSurface (inn.statusdisplace);
     SDL_FreeSurface (inn.window);
     SDL_Flip (gwiz.canvas);
 }

 void ChooseBed (void)
 {
     SDL_Event event;
     SDL_Event *e = &event;
     inn.position = 0;

     while (SDL_WaitEvent (e) != 0)
	 {
	     if (EventIsUp (e))
		 MoveInnCursor (TRUE);
	     if (EventIsDown (e))
		 MoveInnCursor (FALSE);
	     if (EventIsOk (e))
		 Rest(e);
	     if (EventIsCancel (e))
		 break;
	 }
 }

void Rest (SDL_Event *e)
{
    int tent = 10;
    int basic = 50;
    int luxury = 200;
    int regal = 500;
    char prompt[] = "     /      (Esc to Exit)";

    /* This loop shares the same event structure as the one in ChooseBed,
       because that makes it extremely easy to send data between the two, and
       automate otherwise tedious tasks. */
    do
	{
	    SDL_BlitSurface (inn.statusdisplace, NULL, gwiz.canvas, NULL);
	    if ((e->type == SDL_KEYDOWN) || (e->type == SDL_JOYBUTTONDOWN) ||
		(e->type == SDL_JOYAXISMOTION))
		{
		    if (EventIsCancel (e))
			break;
		    
		    if ((inn.position == 1) && (inn.pawn->counter.gp < tent))
			{
			    MsgBox ("You cannot afford this room");
			    break;
			}
		    if ((inn.position == 2) && (inn.pawn->counter.gp < basic))
			{
			    MsgBox ("You cannot afford this room");
			    break;
			}
		    if ((inn.position == 3) && (inn.pawn->counter.gp < luxury))
			{
			    MsgBox ("You cannot afford this room");
			    break;
			}
		    if ((inn.position == 4) && (inn.pawn->counter.gp < regal))
			{
			    MsgBox ("You cannot afford this room");
			    break;
			}
		    
		    SubtractCostOfInn();
		    IncrementHps();
		    RefillMagic();
		    CheckForLevelUp();
		    CheckForBirthday();

		    snprintf (prompt, sizeof(char)*26, "%4d/%4d (Esc to Exit)",
			      inn.pawn->counter.hp, inn.pawn->counter.hp_max);
		    PrintInnStatus();
		}
	} while (SDL_WaitEvent (e) != 0);
}

void MoveInnCursor (int goingup)
{
    SDL_FillRect (inn.window, &inn.crect, 0);
    if (goingup)
	{
	    inn.position--;
	    if (inn.position < 0)
		inn.position = 4;
	} else {
	    inn.position++;
	    if (inn.position > 4)
		inn.position = 0;
	}
    inn.crect.y = BORDERHEIGHT + gwiz.font.height*2 + gwiz.font.height/2 -
	          gwiz.cursor->h/2 + gwiz.font.height*inn.position;
    SDL_BlitSurface (gwiz.cursor, NULL, inn.window, &inn.crect);
    SDL_BlitSurface (inn.window, NULL, gwiz.canvas, &inn.drect);
    SDL_Flip (gwiz.canvas);
}

void CheckForLevelUp (void)
{
    long unsigned int nextlevel = 0;
    int i;

    if (inn.pawn->class == FIGHTER)
	nextlevel = FIGHTER_LEVEL;
    if (inn.pawn->class == MAGE)
	nextlevel = MAGE_LEVEL;
    if (inn.pawn->class == CLERIC)
	nextlevel = CLERIC_LEVEL;
    if (inn.pawn->class == THIEF)
	nextlevel = THIEF_LEVEL;
    if (inn.pawn->class == WIZARD)
	nextlevel = WIZARD_LEVEL;
    if (inn.pawn->class == SAMURAI)
	nextlevel = SAMURAI_LEVEL;
    if (inn.pawn->class == LORD_LEVEL)
	nextlevel = LORD_LEVEL;
    if (inn.pawn->class == NINJA)
	nextlevel = NINJA_LEVEL;

    for (i = 1; i < inn.pawn->level; i++)
	{
	    if (nextlevel < 524288)
		nextlevel += nextlevel/9;
	    else
		nextlevel += 524288;
	}
    if (inn.pawn->counter.ep > nextlevel)
	{
	    HandleLevelUp();
	}
    inn.levelup = FALSE; /* by default, do not process the levelup event */
}

void RefillMagic (void)
{
    int i;
    for (i = 0; i < 7; i++)
	{
	    inn.pawn->mm.spellpoints[i] = inn.pawn->mm.maxpoints[i];
	    inn.pawn->cm.spellpoints[i] = inn.pawn->cm.maxpoints[i];
	}
}

void CheckForBirthday (void)
{
    int birthday;
    birthday = rand() % (52 - 1) + 1;
    if (birthday == 1) /* good a number as any */
	{
	    inn.pawn->counter.age++;
	    inn.hadbirthday = TRUE;
	}
}

SDL_Surface *DrawInnOptions (void)
{
    SDL_Surface *labels[] = {
	GwizRenderText ("Hog\'s Wallow "),
	GwizRenderText ("Tent "),
	GwizRenderText ("Basic Room "),
	GwizRenderText ("Luxury Suite "),
	GwizRenderText ("Regal Chambers ")
    };
    SDL_Surface *costs[] = {
	GwizRenderText ("10 "),
	GwizRenderText ("50 "),
	GwizRenderText ("200 "),
	GwizRenderText ("500 ")
    };
    SDL_Surface *perweek[] = {
	GwizRenderText ("(Free)"),
	GwizRenderText ("G.P. / Week")
    };
    SDL_Surface *prompt = GwizRenderText ("Greetings, ");
    SDL_Surface *name = GwizRenderText (inn.pawn->name);
    SDL_Surface *area;
    SDL_Surface *column1;
    SDL_Surface *column2;
    SDL_Surface *column3;
    SDL_Rect trect;
    SDL_Rect dest;
    int widest = 0;
    int areawidth;
    int areaheight;
    int i;

    trect.x = 0;
    trect.y = 0;
    trect.h = gwiz.font.height;

    for (i = 0; i < 5; i++)
	if (labels[i]->w > widest)
	    widest = labels[i]->w;
    column1 = NewGwizSurface (widest, gwiz.font.height*5);
    widest = 0;
    for (i = 0; i < 4; i++)
	if (costs[i]->w > widest)
	    widest = costs[i]->w;
    column2 = NewGwizSurface (widest, gwiz.font.height*4);
    widest = (perweek[0]->w > perweek[1]->w) ? perweek[0]->w : perweek[1]->w;
    column3 = NewGwizSurface (widest, gwiz.font.height*5);
    for (i = 0; i < 5; i++)
	{
	    trect.w = labels[i]->w;
	    SDL_BlitSurface (labels[i], NULL, column1, &trect);
	    if (i < 4) /* prices have one fewer rows; only do four of them */
		{
		    trect.w = costs[i]->w;
		    SDL_BlitSurface (costs[i], NULL, column2, &trect);
		}
	    if (i == 0) /* first row is different, the rest are the same */
		{
		    trect.w = perweek[i]->w;
		    SDL_BlitSurface (perweek[i], NULL, column3, &trect);
		} else {
		    trect.w = perweek[1]->w;
		    SDL_BlitSurface (perweek[1], NULL, column3, &trect);
		}
	    trect.y += gwiz.font.height;
	}
    areawidth = column1->w + column2->w + column3->w + gwiz.font.width*2 +
	        gwiz.cursor->w;
    areaheight = gwiz.font.height*7;
    area = NewTextBox (areawidth, areaheight);

    dest.x = BORDERWIDTH + gwiz.cursor->w;
    dest.y = BORDERHEIGHT;
    dest.h = gwiz.font.height;
    dest.w = prompt->w;
    SDL_BlitSurface (prompt, NULL, area, &dest);
    dest.x = BORDERWIDTH + gwiz.cursor->w + prompt->w;
    dest.w = name->w;
    SDL_BlitSurface (name, NULL, area, &dest);
    dest.x = BORDERWIDTH + gwiz.cursor->w;;
    dest.y = BORDERWIDTH + gwiz.font.height*2;
    dest.h = column1->h;
    dest.w = column1->w;
    SDL_BlitSurface (column1, NULL, area, &dest);
    dest.x = area->w - BORDERWIDTH - column3->w;
    dest.w = column3->w;
    SDL_BlitSurface (column3, NULL, area, &dest);
    dest.x = dest.x - column2->w;
    dest.y += gwiz.font.height;
    dest.h = column2->h;
    dest.w = column2->w;
    SDL_BlitSurface (column2, NULL, area, &dest);

    for (i = 0; i < 5; i++)
	{
	    SDL_FreeSurface (labels[i]);
	    if (i < 4)
		SDL_FreeSurface (costs[i]);
	}
    SDL_FreeSurface (perweek[0]);
    SDL_FreeSurface (perweek[1]);
    SDL_FreeSurface (prompt);
    SDL_FreeSurface (name);
    SDL_FreeSurface (column1);
    SDL_FreeSurface (column2);
    SDL_FreeSurface (column3);

    return (area);
}

void IncrementHps (void)
{
    switch (inn.position)
	{
	case 0:
	    return;
	case 1:
	    inn.pawn->counter.hp += 1;
	    break;
	case 2:
	    inn.pawn->counter.hp += 2;
	    break;
	case 3:
	    inn.pawn->counter.hp += 5;
	    break;
	case 4:
	    inn.pawn->counter.hp += 10;
	    break;
	}
    if (inn.pawn->counter.hp > inn.pawn->counter.hp_max)
	inn.pawn->counter.hp = inn.pawn->counter.hp_max;
}

void PrintInnStatus (void)
{
    SDL_Surface *box;
    SDL_Surface *text;
    SDL_Rect trect;
    char status[30];

    snprintf (status, sizeof(char)*30, "HP: %4d/%4d (Esc to Quit)", 
	      inn.pawn->counter.hp, inn.pawn->counter.hp_max);

    text = GwizRenderText (status);
    box = NewTextBox (text->w, text->h);

    trect.x = BORDERWIDTH;
    trect.y = BORDERHEIGHT;
    trect.h = text->h;
    trect.w = text->w;

    SDL_BlitSurface (text, NULL, box, &trect);
    SDL_BlitSurface (box, NULL, gwiz.canvas, NULL);
    SDL_Flip (gwiz.canvas);
    SDL_FreeSurface (text);
    SDL_FreeSurface (box);
}

void SubtractCostOfInn (void)
{
    switch (inn.position)
	{
	case 0:
	    break;
	case 1:
	    inn.pawn->counter.gp -= 10;
	    break;
	case 2:
	    inn.pawn->counter.gp -= 50;
	    break;
	case 3:
	    inn.pawn->counter.gp -= 200;
	    break;
	case 4:
	    inn.pawn->counter.gp -= 500;
	    break;
	}
}
