/*
   intro/intro.cc
   This file is part of the Osirion project and is distributed under
   the terms of the GNU General Public License version 2
*/

#include "intro/intro.h"
#include "core/core.h"
#include "core/entity.h"
#include "core/entityglobe.h"
#include "core/parser.h"
#include "filesystem/filesystem.h"
#include "filesystem/inifile.h"
#include "math/color.h"
#include "sys/sys.h"

namespace intro
{

core::Module *factory()
{
	return new Intro();
}

Intro::Intro() : core::Module("Project::OSiRiON", false)
{
	if (!load_world()) {
		abort();
		return;
	}

	core::Func *func = 0;

	func = core::Func::add("intro", Intro::func_intro);
	func->set_info("[int] view specified introduction");
}

bool Intro::load_world()
{
	std::string filename("ini/intro");

	filesystem::IniFile inifile;
	inifile.open(filename);

	if (!inifile.is_open()) {
		con_error << "Could not open " << inifile.name() << std::endl;
		return false;
	}

	core::Zone *zone = 0;
	Convoy *convoy = 0;

	std::string strval;
	core::EntityGlobe *globe = 0;
	core::Entity *entity = 0;
	math::Color color;
	math::Vector3f v;
	float f;

	while (inifile.getline()) {

		if (inifile.got_section()) {
			if (inifile.got_section("intro")) {

				zone = new core::Zone("intro");
				zone->set_name("Introduction");
				zone->set_sky("sky");
				core::Zone::add(zone);

			} else if (inifile.got_section("entity")) {
				if (zone) {
					entity = new core::Entity();
					entity->set_zone(zone);
					entity->set_radius(0);
				}
				
			} else if (inifile.got_section("convoy")) {
				if (zone) {
					convoy = new Convoy(zone);
				}

			} else if (inifile.got_section("globe")) {
				if (zone) {
					globe = new core::EntityGlobe();
					globe->set_zone(zone);
				}

			} else {
				inifile.unknown_section();
			}
		} else if (zone && inifile.got_key()) {

			if (inifile.in_section("intro")) {

				if (inifile.got_key_string("label", strval)) {
					zone->set_label(strval);

				} else if (inifile.got_key_string("sky", strval)) {
					zone->set_sky(strval);

				} else if (inifile.got_key_color("ambient", color)) {
					zone->set_ambient_color(color);

				} else if (inifile.got_key()) {
					inifile.unknown_key();
				}

			} else if (inifile.in_section("entity")) {
				
				if (core::Parser::got_entity_key(inifile, entity)) {
					continue;
				} else {
					inifile.unknown_key();
				}
								
			} else if (inifile.in_section("globe")) {

				if (core::Parser::got_entity_key(inifile, globe)) {
					continue;
					
				} else if (inifile.got_key()) {
					inifile.unknown_key();
				}
				
			} else if (inifile.in_section("convoy")) {

				if (inifile.got_key_string("label", strval)) {
					convoy->set_label(strval);

				} else if (inifile.got_key_color("color", color)) {
					convoy->set_color(color);

				} else if (inifile.got_key_color("colorsecond", color)) {
					convoy->set_color_second(color);

				} else if (inifile.got_key_vector3f("location", v)) {
					convoy->get_location().assign(v);

				} else if (inifile.got_key_float("direction", f)) {
					convoy->get_axis().change_direction(f);

				} else if (inifile.got_key_float("speed", f)) {
					convoy->set_speed(f);

				} else if (inifile.got_key_string("ship", strval)) {
					convoy->add(strval);

				} else if (inifile.got_key()) {
					inifile.unknown_key();
				}
			}
		}
	}

	// set entity radius where required
	for (core::Entity::Registry::iterator it = core::Entity::registry().begin(); it != core::Entity::registry().end(); it++) {
		entity = (*it).second;
		if (!entity->radius() && entity->model()) {
			entity->set_radius(entity->model()->radius());
		}
		if (!entity->radius()) {
			entity->set_radius(0.5f);
		}
	}
	
	return true;
}

void Intro::player_connect(core::Player *player)
{
	core::Zone::Registry::iterator it = core::Zone::registry().begin();
	if (it != core::Zone::registry().end()) {
		size_t m = math::randomi(core::Zone::registry().size());
		for (size_t i = 0; i < m; i++) {
			it++;
		}
		player->set_zone((*it).second);
	}
}

void Intro::player_disconnect(core::Player *player)
{

}

void Intro::frame(float seconds)
{

}

Intro::~Intro()
{
	core::Func::remove("intro");
}

void Intro::func_intro(core::Player *player, std::string const &args)
{
	std::stringstream str(args);
	size_t id;
	if (str >> id) {
		core::Zone *zone = core::Zone::find(id);
		if (zone) {
			player->set_zone(zone);
		} else {
			core::Zone::list();
		}
	} else {
		core::Zone::list();
	}
}

}