#include <pl.h>
#include <stdproperties.h>
#include <macros.h>
#include <filter_funs.h>
#include <composite.h>
#include <options.h>

#include "woz.h"

inherit "/std/object";

float dlugosc_postoju = 45.0;
float dlugosc_postoju_w_lokacji = 6.0;
int pasazerowie = 0;
int max_players = 6;
int jedziemy = 0;
object woznica;
mixed sequence = ({ 0, "s", "s", "e", 2, 3, "w", "n", "n", 5, 10 });
int seq_end = sizeof(sequence);
int current = 0;
object gdzie_wrocic;

int yell(string str);
object query_podrozni();
void init_sequence();
void special(int i);
void ruszamy(int i); // ruszanie
void przemiesc_woz();
void stajemy_n(int i); // stajemy w Nuln
void stajemy_g(int i); // stajemy kolo G. Grimfang (i spadamy do VOIDa)
void wracamy_g(int i); // wracamy w okolice G. Grimfang (i czekamy)
void wsiadz(string str);
string unalias(string str);
void set_jedziemy(int i);
void do_event();

void
create_object()
{
    string str;

    ustaw_nazwe(({"woz", "wozu", "wozowi", "woz", "wozem", "wozie"}),
		({"wozy", "wozow", "wozom", "wozy", "wozami", "wozach"}),
		PL_MESKI_NZYW);

    set_long("@@opis_wozu");

    add_prop(OBJ_I_WEIGHT, 1300000);
    add_prop(OBJ_I_VOLUME, 1500000);
    add_prop(OBJ_M_NO_GET, "Podniesc woz? Czy ty aby delikatnie nie przeceniasz wlasnych " +
	     "mozliwosci?\n");

    set_alarm(3.0, 0.0, &init_sequence());

    SRODEK_WOZU->ustaw_obiekt_wozu(this_object());
}

string
short(mixed for_obj, mixed przyp)
{
    string *tab_str = ({ "", " z jednym pasazerem", " z dwojka pasazerow",
		        " z trojka pasazerow", " z czworka pasazerow",
			" z piatka pasazerow", " z szostka pasazerow",
			" z siodemka pasazerow", " z osemka pasazerow",
			" z dziewiatka pasazerow", " z dziesiatka pasazerow" });
    string str = tab_str[pasazerowie];

    if (!intp(przyp))
	przyp = atoi(przyp);

    return ({"zaprzezony w markotnego siwka woz" + str,
		 "zaprzezonego w markotnego siwka wozu" + str,
		 "zaprzezonemu w markotnego siwka wozowi" + str,
		 "zaprzezony w markotnego siwka woz" + str,
		 "zaprzezonym w markotnego siwka wozem" + str,
		 "zaprzezonym w markotnego siwka wozie" + str})[przyp];
}

string
plural_short(mixed for_obj, mixed przyp)
{
    string *tab_str = ({ "", " z jednym pasazerem", " z dwojka pasazerow",
		        " z trojka pasazerow", " z czworka pasazerow",
			" z piatka pasazerow", " z szostka pasazerow",
			" z siodemka pasazerow", " z osemka pasazerow",
			" z dziewiatka pasazerow", " z dziesiatka pasazerow" });
    string str = tab_str[pasazerowie];
    
    if (!intp(przyp))
	przyp = atoi(przyp);

    return ({"zaprzezone w markotne siwki wozy" + str,
		 "zaprzezonych w markotne siwki wozow" + str,
		 "zaprzezonym w markotne siwki wozom" + str,
		 "zaprzezone w markotne siwki wozy" + str,
		 "zaprzezonymi w markotne siwki wozami" + str,
		 "zaprzezonych w markotne siwki wozach" + str})[przyp];
}


void
init()
{
    add_action(yell, "krzyknij");
    add_action(wsiadz, "wsiadz");
    ::init();
}

int
yell(string str)
{
    if (!stringp(str))
	return 0;

    tell_room(SRODEK_WOZU, QCIMIE(this_player(), PL_MIA) + " krzyczy: " + str + "\n");
    return 0;
}

int
wsiadz(string str)
{
    if (str != "na woz" && str != "do wozu")
    {
	notify_fail("Wsiadz gdzie? Moze na woz?\n");
	return 0;
    }

    if (jedziemy)
    {
	notify_fail("Ehhh nie, woz juz jedzie. Nie bedziesz na niego wskakiwac w biegu.\n");
	return 0;
    }

    if(woznica && !this_player()->query_prop(ZAPLACILEM_ZA_WOZ))
    {
	write("Probujesz wsiasc na woz, ale " + woznica->query_imie(this_player(), PL_MIA) +
	      " zagradza ci droge.\n");
	say(QCIMIE(this_player(), PL_MIA) + " probuje wsiasc na woz, ale " +
	    QIMIE(woznica, PL_MIA) + " zagradza mu droge.\n");
	
	woznica->command("' do " + OB_NAME(this_player()) + " Hola! Hola! Za darmo by sie " +
			 "chcialo jechac?! Tak dobrze to nie ma.");
	woznica->command("' do " + OB_NAME(this_player()) + " Albo placisz, albo nie jedziesz!");
	return 1;
    }
	
    if (pasazerowie == max_players)
    {
	notify_fail("Nie wydaje ci sie, zeby na wozie znalazla sie chocby odrobina " +
		    "wolnego miejsca dla ciebie.\n");
	return 0;
    }

    write("Wskakujesz na woz.\n");
    say(QCIMIE(this_player(), PL_MIA) + " wskakuje na woz.\n");
    this_player()->move_living("M", SRODEK_WOZU, 1);
    say(QCIMIE(this_player(), PL_MIA) + " wskakuje na woz.\n");
    return 1;
}

string
opis_wozu()
{
    string
    str = "Jest to duzy otwarty woz zaprzegniety w dosc poteznego, acz niezbyt zadowolonego " +
	"z zycia siwka. Spora jego przestrzen w znacznej czesci wypelniaja przeznaczone " +
	"bez watpienia na handel paki, worki i skrzynie. ";

    if (jedziemy)
    {
	str += "Pomimo to zostalo na nim wystarczajaco duzo miejsca dla powozacego wozem " +
	    woznica->query_imie(this_player(), PL_DOP);

	dump_array(pasazerowie);

	if (pasazerowie == 1)
	    str += ".\n";

	if (pasazerowie == 2)
	    str += ", a takze dla podrozujace" + query_podrozni()[0]->koncowka("go", "j") +
		" razem z nim " + query_podrozni()[0]->query_imie(this_player(), PL_DOP) + ".\n";

	if (pasazerowie > 2)
	    str += ", a takze dla podrozujacych razem z nim " + 
		COMPOSITE_LIVE(query_podrozni(), PL_MIA);
    }
    else
    {
	if (pasazerowie == 0)
	    str += "Wydaje ci sie jednak, ze zostalo na nim dostatecznie duzo wolnego " +
		"miejsca by moglo sie tam zmiescic nawet kilku podroznych.\n";

	if (pasazerowie == 1)
	    str += "Choc siedzi juz tam takze " + 
		query_podrozni()[0]->query_imie(this_player(), PL_MIA) + 
		" to jednak wydaje ci sie, ze starczyloby miejsca dla jeszcze paru osob.\n";

	if (pasazerowie > 1 && pasazerowie < max_players)
	str += "Mimo, ze wsrod towarow rozsiedli sie takze " + 
	    COMPOSITE_LIVE(query_podrozni(), PL_MIA) +
	    " wydaje ci sie, ze jeszcze ktos by sie tam zmiescil.\n";

	if (pasazerowie == max_players)
	    str += COMPOSITE_LIVE(query_podrozni(), PL_MIA) + ", ktorzy rozsiedli sie " +
		"wsrod towarow zajeli praktycznie cala przestrzen, nie zostawiajac juz " +
		"dla nikogo miejsca.\n";
    }

    return str;
}

/*
 * Zwraca podroznych, wylaczajac woznice
 */
object*
query_podrozni()
{
    object *oblist;
    SRODEK_WOZU->wczytaj_mnie();
    oblist = all_inventory(find_object(SRODEK_WOZU));
    
    oblist = FILTER_LIVE(oblist);
    oblist -= ({ woznica });
    return oblist;
}

/*
 * Rozpoczecie sekwencji (wywoluje sie tylko raz)
 */
void
init_sequence()
{
    if (!environment())
	return;

    if (!pointerp(woznica))
    {
	woznica = clone_object(WOZNICA);
	woznica->move(environment());
	tell_room(environment(), QCIMIE(woznica, PL_MIA) + " przybywa.\n");
    }
    
    set_alarm(0.5, 0.0, &special(sequence[current]));
}

/*
 * Sekwencje specjalne, dbaja o odpowiednie zachowanie wozu i woznicy
 * w roznych momentach, niestety robie to bardzo recznie :/
 * 0) Start wozu w Nuln.
 * 1) Przejazd przez brame Nuln / to bedzie dopiero /
 * 2) Wysadzenie pasazerow kolo pustkowi i znikniecie na jakis czas
 * 3) Powrot w okolice pustkowi
 * 4) Przejazd przez brame Nuln / w druga strone /
 * 5) Wysiadamy w Nuln -> 0)
 */
void
special(int i)
{
    current++;
    switch (i)
    {
    case 0:
	woznica->init_nuln_emotes();
	set_alarm(dlugosc_postoju, 0.0, &ruszamy(0));
	break;
    case 2:
	set_alarm(2.5, 0.0, &stajemy_g(0));
	break;
    case 3:
	set_alarm(0.1, 0.0, &wracamy_g(0));
	break;
    case 5:
	set_alarm(2.5, 0.0, &stajemy_n(0));
    }
}

/*
 * ruszamy z miejsca
 * (to na szczescie standardowe cosik)
 */
void
ruszamy(int i)
{
    if (!woznica)
	return; // Woz sie robi bezuzyteczny chwilowo
    
    switch (i)
    {
    case 0:
	woznica->move(SRODEK_WOZU);
	tell_room(environment(), QCIMIE(woznica, PL_MIA) + " wskakuje na woz.\n");
	tell_room(SRODEK_WOZU, QCIMIE(woznica, PL_MIA) + " wskakuje na woz.\n");
	set_alarm(4.0, 0.0, &ruszamy(1));
	set_jedziemy(1);
	break;

    case 1:
	tell_room(SRODEK_WOZU, QCIMIE(woznica, PL_MIA) + " rozsiada sie na kozle i bierze " +
		  "lejce w dlonie.\n");
	tell_room(environment(), QCIMIE(woznica, PL_MIA) + " rozsiada sie na kozle " +
		  "i bierze lejce w dlonie.\n");
	set_alarm(3.5, 0.0, &ruszamy(2));
	break;

    case 2:
	woznica->command("krzyknij No dalej Wicher! Wioooooooo! Wioooooooooo cholero!");
	set_alarm(2.0, 0.0, &ruszamy(3));
	break;

    case 3:
	tell_room(SRODEK_WOZU, "Ospaly siwek z wyrazna niechecia rusza sie z miejsca i woz " +
		  "powoli zaczyna sie toczyc.\n");
	tell_room(environment(), "Ospaly siwek z wyrazna niechecia rusza sie z miejsca i woz " +
		  "powoli zaczyna sie toczyc.\n");
	set_alarm(2.0, 0.0, &przemiesc_woz());
    }
}

/*
 * Stajemy kolo gory Grimfang, wywalamy graczy
 * I znikamy na jakis czas do voida
 */
void
stajemy_g(int i)
{
    if (i == 0 && !sizeof(query_podrozni()))
	i = 7;
    switch (i)
    {
	object *oblist;
    case 0:
	woznica->command("krzyknij Prrrrr! No stojze! Stoj u diabla, mowie!");
	set_alarm(2.5, 0.0, &stajemy_g(1));
	break;
    case 1:
	tell_room(environment(), "Markotny siwek ciagnacy woz z nieskrywana radoscia " +
		  "zatrzymuje sie w miejscu.\n");
	tell_room(SRODEK_WOZU, "Markotny siwek ciagnacy woz z nieskrywana radoscia " +
		  "zatrzymuje sie w miejscu.\n");
	set_alarm(3.0, 0.0, &stajemy_g(2));
	break;
    case 2:
	woznica->command("'No tu niestety rozstac sie musimy. Mnie do Gory Grimfang droga...");
	set_alarm(1.5, 0.0, &stajemy_g(3));
	break;
    case 3:
	woznica->command("'Z checia bym was zabral... ale coz, zwykla droga zasypana.");
	woznica->command("'A o tej drugiej ukrytej, ehhhh, mowic mi nie daja...");
	set_alarm(3.0, 0.0, &stajemy_g(4));
	break;
    case 4:
	oblist = query_podrozni();
	if (sizeof(oblist))
	{
	    oblist->catch_msg("Zsiadasz z wozu.\n");
	    oblist->remove_prop(ZAPLACILEM_ZA_WOZ);
	    oblist->move_living("M", environment(), 0, 0);
	    if (sizeof(oblist) > 1)
		tell_room(environment(), capitalize(COMPOSITE_LIVE(oblist, PL_MIA)) +
			  " zsiadaja z wozu.\n", oblist);
	    else
		tell_room(environment(), QCIMIE(oblist[0], PL_MIA) +
			  " zsiada z wozu.\n", oblist);
	}
	set_alarm(1.5, 0.0, &stajemy_g(5));
	break;
    case 5:
	woznica->command("krzyknij Bywajcie! Jak wracac bede takze sie tu zatrzymam!");
	woznica->command("krzyknij No ruszaj Wicher! Ruszaj! Pokaz im na co cie stac!");
	set_alarm(1.5, 0.0, &stajemy_g(6));
	break;
    case 6:
	tell_room(environment(), "Markotny siwek markotnieje jeszcze bardziej i powoli " +
		  "rusza w droge.\n");
	set_alarm(0.5, 0.0, &stajemy_g(7));
	break;
    case 7:
	tell_room(environment(), "Po kilku chwilach woz znika z pola widzenie gdzies za " +
		  "jakims zalomem skalnym i juz wiecej go nie zauwazasz.\n");
	gdzie_wrocic = environment();
	this_object()->move(VOID);
	set_alarm(60.0, 0.0, &przemiesc_woz());
	break;
    }
}

/*
 * Wracamy tam skad zniklismy i czekamy
 * chwile na jakichs graczy
 */
void
wracamy_g(int i)
{
    switch(i)
    {
    case 0:
	tell_room(gdzie_wrocic, QCSHORT(this_object(), PL_MIA) + " przyjezdza.\n");
	this_object()->move(gdzie_wrocic);
	set_alarm(2.0, 0.0, &wracamy_g(1));
	break;
    case 1:
	woznica->command("krzyknij Stop! Stoooop no! Noooooooo!");
	tell_room(environment(), "Siwek tym razem wcale nie ma ochoty sie zatrzymac " +
		  "i czyni to bardzo opornie.\n");
	set_alarm(2.0, 0.0, &wracamy_g(2));
	break;
    case 2:
	tell_room(environment(), QCIMIE(woznica, PL_MIA) + " zeskakuje z kozla na ziemie.\n");
	woznica->move_living("M", environment(), 0, 0);
	set_jedziemy(0);
	set_alarm(3.0, 0.0, &wracamy_g(3));
	break;
    case 3:
	woznica->command("machnij reka");
	woznica->command("'Co za bydle! Demon nie kon!");
	set_alarm(8.0, 0.0, &wracamy_g(4));
	break;
    case 4:
	woznica->command("krzyknij Do Nuln wracam! Chyzo na woz, jak kto nie chce " +
			 "nog se ztyrac na szlaku!");
	set_alarm(25.0, 0.0, &wracamy_g(5));
	break;
    case 5:
	woznica->command("krzyknij Do Nuln, do Nuln jade! Wozem! Szybko i przyjemnie! " +
			 "Wsiadac na woz, pojedziemy razem!");
	set_alarm(15.0, 0.0, &ruszamy());
	break;
    }
}

/*
 * Zatrzymujemy sie w Nuln
 */
void
stajemy_n(int i)
{
    switch(i)
    {
    case 0:
	woznica->command("krzyknij Prrrrrrrr. Prrrr. Stoj mowie, ty wredna bestio!");
	set_alarm(2.5, 0.0, &stajemy_n(1));
	break;

    case 1:
	tell_room(environment(), "Markotny siwek ciagnacy woz z nieskrywana radoscia " +
		  "zatrzymuje sie w miejscu.\n");
	tell_room(SRODEK_WOZU, "Markotny siwek ciagnacy woz z nieskrywana radoscia " +
		  "zatrzymuje sie w miejscu.\n");
	set_alarm(2.0, 0.0, &stajemy_n(2));
	break;

    case 2:
	if (pasazerowie > 1)
	{
	    woznica->command("krzyknij No! Jestesmy w Nuln, koniec drogi! Zsiadac, zsiadac!");
	    all_inventory(find_object(SRODEK_WOZU))->remove_prop(ZAPLACILEM_ZA_WOZ);
	}
	set_alarm(2.0, 0.0, &stajemy_n(3));
	break;

    case 3:
	tell_room(SRODEK_WOZU, QCIMIE(woznica, PL_MIA) + " zeskakuje z wozu.\n");
	woznica->move(environment());
	tell_room(environment(), QCIMIE(woznica, PL_MIA) + " zeskakuje z wozu.\n");
	set_jedziemy(0);
	current = 0;
	set_alarm(2.0, 0.0, &przemiesc_woz());
	break;
    }
}

void
przemiesc_woz()
{
    int i;
    string str;

    if (intp(sequence[current]))
    {
	set_alarm(0.1, 0.0, &special(sequence[current]));
	return;
    }

    str = unalias(sequence[current]);
    i = member_array(str, environment()->query_exit());

    tell_room(environment(), QCSHORT(this_object(), PL_MIA) + " z turkotem wyjezdza na " 
	      + str + ".\n");
    this_object()->move(environment()->query_exit()[--i]);
    tell_room(environment(), QCSHORT(this_object(), PL_MIA) + " przyjezdza.\n");

    current++;
    if (intp(sequence[current]))
	set_alarm(1.0, 0.0, &special(sequence[current]));
    else
	set_alarm(dlugosc_postoju_w_lokacji, 0.0, &przemiesc_woz());
}

void
add_pasazer()
{
    pasazerowie++;
}

void
sub_pasazer()
{
    pasazerowie--;
}

int
query_jedzie()
{
    return jedziemy;
}

string
unalias(string str)
{
    mapping kier = (["w" : "zachod", "e" : "wschod", "n" : "polnoc", "s" : "poludnie",
		    "ne" : "polnocny-wschod", "nw" : "polnocny-zachod",
		    "se" : "poludniowy-wschod", "sw" : "poludniowy-zachod"]);

    return kier[str];
}

void
enter_env(object dest, object old)
{
    object *oblist;
    int tmp, i;
    string str;

    ::enter_env(dest, old);

    oblist = query_podrozni();
    tmp = sizeof(oblist);

    for (i = 0 ; i <  tmp ; i++)
    {
	if (!interactive(oblist[i]))
	    continue;

	if (oblist[i]->query_option(OPT_BRIEF))
	    oblist[i]->catch_msg(environment()->short() + ".\n" + 
				 environment()->exits_description());
	else
	    oblist[i]->catch_msg(environment()->long());
    }

    oblist = all_inventory(environment());
    
    oblist = FILTER_LIVE(oblist);
    if ( !(tmp = sizeof(oblist)) )
	return;
	
    if (tmp == 1)
    {
	tell_room(SRODEK_WOZU, "Woz mija raznie maszerujac" + 
		  this_player()->koncowka("ego", "a", "e") + " traktem " +
		  QCIMIE(oblist[0], PL_BIE) + ".\n");
	return;
    }

    for ( i = 0; i < tmp ; i++ )
    {
	if (oblist[i]->query_gender() == G_MALE)
	{
	    str = COMPOSITE_LIVE(oblist, PL_BIE);
	    tell_room(SRODEK_WOZU, "Woz mija raznie maszerujacych traktem " +
		      str + ".\n");
	    return;
	}
    }

    str = COMPOSITE_LIVE(oblist, PL_BIE);
    tell_room(SRODEK_WOZU, "Woz mija raznie maszerujace traktem " + str + ".\n");
}

void
set_jedziemy(int i)
{
    if (i)
    {
	set_alarm(itof(5 + random(10)), 0.0, &do_event());
    }

    jedziemy = i;
}

void
do_event()
{
    int il_eventow = 3;

    if (!jedziemy)
	return;

    switch (random(il_eventow))
    {
    case "0":
	tell_room(SRODEK_WOZU, "Woz nieprzyjemnie podskakuje na wybojach.\n");
	break;
    case "1":
	tell_room(SRODEK_WOZU, QCIMIE(woznica, PL_MIA) + " gwizdze sobie pod nosem " +
		  "jakas skoczna melodie.\n");
	break;
    case "2":
	tell_room(SRODEK_WOZU, "Kola turkocza wesolo na usianej kamieniami drodze.\n");
	break;
    }

    set_alarm(itof(5 + random(10)), 0.0, &do_event());
}
