//  This is -*- c++ -*- code

#include <player.h>
#include <ps5/url_ops.h>
#include <ps5/error_response.h>

player::player(string name, long total_time) {
    check(total_time > 0, "Invalid total_time passed to player constructor");
    player_name = name;
    player_time = total_time;
    g = NULL;
    clock_is_running = false;
}

void player::associate( game *gm) {
    g = gm;
}    

bool player::is_associated() const {
    return (g != NULL);
}

bool player::get_position (string &p) const {
    if (player_position == "")
	return false;
    p = player_position;
    return true;
}

void player::set_position (string p) {
    player_position = p;
}

void player::set_time(long t) {
    check(t >= 0,"player::set_time passed negative time");
    player_time = t;
}


// Note, this is just a quick hack to have something here.  We need to
// decide the protocol that this will be based upon.
http_response *player::get(string request, extensions *ext)
{
string first;
if (!unescape_uri(first_component(request), first))
    return new error_response(http_response::BAD_REQUEST,
			      "Unable to unescape request; go away.");

if (first == "set_name") {
map <string,string> *q = parse_query(extract_query(request));
string name;
if (q->find("name",name)) {
if (name.length() == 0)
    return new error_response(http_response::BAD_REQUEST, "No, you need to specify a name when you're setting it!");
set_name(name);
return get_game()->display(ext,get_game()->player_index(this));
}
else if (first == "set_time") {
    map <string,string> *q = parse_query(extract_query(request));
    string value;
    if (q->find("msecs", value)) {
	long tval = atoi(value.get_chars());
	if (tval >= 0 )
	    set_time(tval);
	else get_game()->message("You cannot set time to a negative number.");
    }
    else if (q->find("time", value)) {
	long tval = 1000*atoi(value.get_chars());
	if (tval >= 0 )
	    set_time(tval);
	else get_game()->message("You cannot set time to a negative number.");
    }
    else return new error_response(http_response::BAD_REQUEST,
				   "Sorry, but you need to tell me either time or msecs to do that.");
}

else     return new error_response(http_response::BAD_REQUEST, "No, you need to specify a name when you're setting it!");

}
 return new error_response(http_response::NOT_FOUND,"I don't know how to do that, boss.");
}




void player::you_moved (move &) {
  stop_clock();
}

// Ok, this needs some more added to it.
void player::opponent_moved (move &,int ) {
  stop_clock();
}


void player::state_changed(void) {
  stop_clock();
  // This is probably reasonable
  consider_forfeiting();
}

void player::consider_forfeiting(void) {
    if ((player_time <= 0) &&
	is_associated()&&
	((get_game()->winner() < 0 )||
	(get_game()->get_player(get_game()->winner()) != this)))
	g->forfeit(g->player_index(this));
}

void player::start_clock() {
    check(clock_is_running == false,
	   "Clock was already running upon call to start_clock()");
    clock_is_running = true;
    gettimeofday(&clock_started_when, NULL); 
}

void player::stop_clock(){
    struct timeval current_time;
    if (clock_is_running) {
      clock_is_running = false;
      gettimeofday(&current_time, NULL);
      long msecs_past = 1000*(current_time.tv_sec-clock_started_when.tv_sec);
      msecs_past += (current_time.tv_usec-clock_started_when.tv_usec)/1000;
      
if (msecs_past < 0) 
  cerr << "Your OS is confused: I'm about to subtract " <<msecs_past<<" from the time left, but don't think I will.\n";
else player_time -= msecs_past;
      consider_forfeiting();
    }
  }



void player::set_name(string newname) {
check(newname.length() > 0 , "name never specified");
player_name = newname;
}
