/** 
 *  _   _        _  _                           _             
 * | |_| |  ___ | || |  ___   __ _  _ __  _ __ (_)  ___  _ __ 
 * |  _  | / _ \| || | / __| / _` || '__|| '__|| | / _ \| '__|
 * | | | ||  __/| || || (__ | (_| || |   | |   | ||  __/| |   
 * |_| |_| \___||_||_| \___| \__,_||_|   |_|   |_| \___||_|   
 * 
 *  (c) 2001 Free Lunch Design, Teknisk-IT, AerotechTelub
 *			  http://www.freelunchdesign.com
 * 
 * This source code is released as is under GPL (General Public
 * License). Please refer to license.txt for more information.
 * 
 */
 

#include "stdio.h"

#include "allegro.h"
#include "main.h"
#include "mission.h"
#include "object.h"
#include "scenery.h"
#include "soldier.h"
#include "building.h"
#include "dime.h"
#include "config.h"


// constructor
// sets some silly default values
building :: building() {
	// object
	type = OBJ_BUILDING;
	sprintf(name, "building[%d]", rand());
	altitude = GL_GROUND_SCENERY;

	smoking = 0;
	x = y = w = h = 0;
	exist = TRUE;
	target = FALSE;
	detail_level = DETAIL_LOW;
	angle = 0;
	base_image = 1;
	anim_pos = 0;
	anim_frames = 0;
	anim_rate = 0;
	anim_count = 0;
	armour = 200;
	shadow_dist	= 10;
	max_armour = armour;
	got_rotor = 0;
	rot_angle = itofix(rand()%256);
	pw = 1;
	essential = FALSE;
	inside = FALSE;

	// scenery
	material = MAT_WOOD;
	size = SCEN_MED;

	// building
	for(int i=0;i<MAX_OCCUPANTS;i++)
		occupant[i] = -1;		// ids of the people in the house
	num_occupants = 0;

}

// destructor
building :: ~building() {
	for(int i=0;i<MAX_OCCUPANTS;i++) {
		if (occupant[i] != NULL)
			occupant[i]->~object();
	}
}

// try to add an object to reside inside this object
// the object should already be added to the mission
bool building::add_object(object *o) {
	// find free slot
	int i=0;
	while(occupant[i]!=-1 && i<MAX_OCCUPANTS) i++;
	if (i==MAX_OCCUPANTS) return FALSE;

	// add object and set some values
	occupant[i] = o->index;
	o->inside = TRUE;

	num_occupants ++;

	return TRUE;
}

// removes the occupants of a building and places outside
void building::empty(mission *m) {
	for(int i=0;i<MAX_OCCUPANTS;i++)
		if (occupant[i] != -1) {
			if (m->obj[occupant[i]] != NULL) {
				m->obj[occupant[i]]->inside = FALSE;
				m->obj[occupant[i]]->set_position(x+rand()%radius-radius/2, y+rand()%radius-radius/2);
			}
			occupant[i] = -1;
		}

	num_occupants = 0;
}

// removes the occupants of a building and places outside (burning possible!)
void building::destroy(mission *m) {
	for(int i=0;i<MAX_OCCUPANTS;i++)
		if (occupant[i] != -1) {
			if (m->obj[occupant[i]] != NULL) {
				m->obj[occupant[i]]->inside = FALSE;
				m->obj[occupant[i]]->set_position(x+rand()%radius-radius/2, y+rand()%radius-radius/2);
				if ((m->obj[occupant[i]]->type == OBJ_SOLDIER || m->obj[occupant[i]]->type == OBJ_FOOT_SOLDIER || m->obj[occupant[i]]->type == OBJ_BAZOOKA_SOLDIER))
					if (!m->obj[occupant[i]]->essential)
						if (rand()%100>60) {
							((soldier*)m->obj[occupant[i]])->start_fire(60);
							m->obj[occupant[i]]->armour = rand()%15+10;
						}
			}
			occupant[i] = -1;
		}

	num_occupants = 0;
}

// copies data about object to str
void building::to_string(char *str) {
	sprintf(str, "%s", name);
}

// shows a property dialog
void building::props_dialog(DATAFILE *df) {
	dialogf("Building Properties" , ALIGN_CENTER, ALIGN_CENTER, 300,
		"Name:%string[32]"
		"Radar on top:%bool[]"
		"Collision width (%%):%double[0,1]",
		name, &got_rotor, &pw);

	if (got_rotor) {
		rot_w = ((BITMAP *)df[base_image+1].dat)->w;
		rot_h = ((BITMAP *)df[base_image+1].dat)->h;
	}
}

void building::save(PACKFILE *fp) {
	pack_fwrite(name, sizeof(name), fp);
	pack_fwrite(&index, sizeof(index), fp);
	pack_fwrite(&inside, sizeof(inside), fp);
	pack_fwrite(&type, sizeof(type), fp);
	pack_fwrite(&altitude, sizeof(altitude), fp);
	pack_fwrite(&x, sizeof(x), fp);
	pack_fwrite(&y, sizeof(y), fp);
	pack_fwrite(&w, sizeof(w), fp);
	pack_fwrite(&h, sizeof(h), fp);
	pack_fwrite(&exist, sizeof(exist), fp);
	pack_fwrite(&target, sizeof(target), fp);
	pack_fwrite(&detail_level, sizeof(detail_level), fp);
	pack_fwrite(&angle, sizeof(angle), fp);
	pack_fwrite(&base_image, sizeof(base_image), fp);
	pack_fwrite(&shadow_image, sizeof(base_image), fp);
	pack_fwrite(&wreck_image, sizeof(base_image), fp);
	pack_fwrite(&anim_frames, sizeof(anim_frames), fp);
	pack_fwrite(&anim_rate, sizeof(anim_rate), fp);
	pack_fwrite(&armour, sizeof(armour), fp);
	pack_fwrite(&team, sizeof(team), fp);
	pack_fwrite(&essential, sizeof(essential), fp);

	pack_fwrite(&got_rotor, sizeof(got_rotor), fp);
	pack_fwrite(&rot_w, sizeof(rot_w), fp);
	pack_fwrite(&rot_h, sizeof(rot_h), fp);

	pack_fwrite(&material, sizeof(material), fp);
	pack_fwrite(&size, sizeof(size), fp);

	pack_fwrite(&pw, sizeof(pw), fp);
	pack_fwrite(occupant, sizeof(occupant), fp);
	pack_fwrite(&num_occupants, sizeof(num_occupants), fp);
}

void building::load(PACKFILE *fp) {
	pack_fread(name, sizeof(name), fp);
	pack_fread(&index, sizeof(index), fp);
	pack_fread(&inside, sizeof(inside), fp);
	pack_fread(&type, sizeof(type), fp);
	pack_fread(&altitude, sizeof(altitude), fp);
	pack_fread(&x, sizeof(x), fp);
	pack_fread(&y, sizeof(y), fp);
	pack_fread(&w, sizeof(w), fp);
	pack_fread(&h, sizeof(h), fp);
	pack_fread(&exist, sizeof(exist), fp);
	pack_fread(&target, sizeof(target), fp);
	pack_fread(&detail_level, sizeof(detail_level), fp);
	pack_fread(&angle, sizeof(angle), fp);
	pack_fread(&base_image, sizeof(base_image), fp);
	pack_fread(&shadow_image, sizeof(base_image), fp);
	pack_fread(&wreck_image, sizeof(base_image), fp);
	pack_fread(&anim_frames, sizeof(anim_frames), fp);
	pack_fread(&anim_rate, sizeof(anim_rate), fp);
	pack_fread(&armour, sizeof(armour), fp);
	pack_fread(&team, sizeof(team), fp);
	pack_fread(&essential, sizeof(essential), fp);

	pack_fread(&got_rotor, sizeof(got_rotor), fp);
	pack_fread(&rot_w, sizeof(rot_w), fp);
	pack_fread(&rot_h, sizeof(rot_h), fp);

	pack_fread(&material, sizeof(material), fp);
	pack_fread(&size, sizeof(size), fp);

	pack_fread(&pw, sizeof(pw), fp);
	pack_fread(occupant, sizeof(occupant), fp);
	pack_fread(&num_occupants, sizeof(num_occupants), fp);
}

void building::draw(BITMAP *bmp, DATAFILE *gfx, fixed ca, bool shadow) {
	/*
	for(int t=0;t<team;t++)
		circle(bmp, render_x, render_y, radius-t*2, 15);
		*/

	// shadow
	if (shadow) {
		BITMAP *s1 = create_bitmap(w, h);
		BITMAP *s2 = create_bitmap(radius*2, radius*2);
		clear(s1);
		clear(s2);
		draw_character(s1, (BITMAP *)gfx[base_image].dat, 0, 0, 15);
		rotate_sprite(s2, s1, radius-w/2, radius-h/2, angle - ca);
		draw_trans_sprite(bmp, s2, render_x+shax*shadow_dist-radius, render_y+shay*shadow_dist-radius);
		destroy_bitmap(s1);
		destroy_bitmap(s2);
	}
		
	rotate_sprite(bmp, (BITMAP *)gfx[base_image].dat, render_x-w/2, render_y-h/2, angle - ca);
	

	if (got_rotor) {
		rotate_sprite(bmp, (BITMAP *)gfx[base_image+1].dat, render_x-rot_w/2, render_y-rot_h/2, rot_angle - ca);
		rot_angle += ftofix(0.5);
	}

	//textprintf(bmp, font, render_x, render_y, 1, "%d", radius);
}

void building::set_from_file(char *fname) {
	config *c = new config();
	if (c->load_data(fname)) {
		c->get_data_string("name", name);
		anim_frames = c->get_data_int("anim_frames");
		anim_rate = c->get_data_int("anim_rate");
		base_image = c->get_data_int("base_image");
		shadow_image = c->get_data_int("shadow_image");
		wreck_image = c->get_data_int("wreck_image");
		armour = c->get_data_int("armour");
		got_rotor = c->get_data_int("got_rotor");
	}
	c->~config();
}

