typedef enum { MISSION_ASSIGNED =1, MISSION_FAILED, MISSION_COMPLETED } mission_types;

class mission_data;

class mission_data {
	public:
		mission_data() { mission_vnum = 0; current_stage = 0; type = 0; name = NULL; at_time_fail = 0; }
		~mission_data() { extern void free_string(const char *); free_string(name); } 
	private:
		const  char *name;
		vnum_t mission_vnum;

		short current_stage;
		short type;
		short  at_time_fail;
	public:
		// retrieval functors!
		vnum_t get_vnum() { return mission_vnum; }
		short get_stage() { return current_stage; }
		short get_type() { return type; }
		const char *get_name() { return name; }
		short get_fail_time() { return at_fime_fail; }

		// setting functors!
		void set_vnum(vnum_t v) { mission_vnum = v; }
		void set_name(const char *n) { ReplaceString(name, n); }
		void set_state(int s) { state = s; }
		void set_type(short t) { type = t; }
		void set_fail_time(short t) { at_time_fail = t; }

};

IN PCDATA.
Lexi::List<mission_data *>mission_list;

short CHAR_DATA::mission_type(vnum_t v) {
	FOREACH(Lexi::List<mission_data *>, mission_list, mission_iter) {
		mission_data *q = (*mission_iter);
		if(v == q->get_vnum()) {
			return q->get_type();
		}
	}
	return -1;
}

bool CHAR_DATA::has_mission(vnum_t v, short t) {
	FOREACH(Lexi::List<mission_data *>, mission_list, mission_iter) {
		mission_data *q = (*mission_iter);
		if(v == q->get_vnum() && q->get_type() == t) {
			return true;
		}
	}
	return false;
}


mission_data *CHAR_DATA::get_mission(vnum_t v) {
	FOREACH(Lexi::List<mission_data *>, mission_list, mission_iter) {
		mission_data *q = (*mission_iter);
		if(q->get_vnum() == v)
			return q;
	}
	return NULL;
}

void CHAR_DATA::assign_mission(vnum_t v) {
	if(get_mission(v) != NULL) return;

	mission_data *q = new mission_data();
	q->set_vnum(v);
//	q->set_name(mission_name(v));			// for the mission-editor! (brief description of mission && some minor properties)
	q->set_state(0);
	q->set_type(MISSION_ASSIGNED);
	mission_list.push_back(q);
	return;
}

void CHAR_DATA::fail_mission(vnum_t v) {
	mission_data *q = get_mission(v);
	if(!q) return;					// don't have the mission, hard to fail it!
	if(q->get_type() == MISSION_COMPLETED) return;	// already completed the mission, cannot fail it!
	
	q->set_type(MISSION_FAILED);			// failed the mission!
	return;
}


void CHAR_DATA::complete_mission(vnum_t v) {
	mission_data *q = get_mission(v);
	if(!q) return;					// don't have the mission, hard to complete it.
	if(q->get_type() == MISSION_FAILED) return;	// already failed the mission, cannot fail it!
	
	q->set_type(MISSION_COMPLETED);			// failed the mission!
	return;
}

// change the mission-stage
void CHAR_DATA::mission_stage(vnum_t v, short s) {
	mission_data *q = get_mission(v);
	if(!q) return;					// don't have the mission, hard to complete it.
	if(q->get_type() == MISSION_FAILED) return;	// cannot change stage once failed
	if(q->get_type() == MISSION_COMPLETED) return;	// cannot change stage once completed.
	q->set_stage(s);				// change our stage!
	return;
}

// are we the stage selected ?
bool CHAR_DATA::mission_isstage(vnum_t v, short x) {
	mission_data *q = get_mission(v);
	if(!q) return false;
	if(q->get_stage() == s)
		return true;
	return false;	
}

void CHAR_DATA::mission_settime(vnum_t v, short t) {
	mission_data *q = get_mission(v);
	if(!q) return false;
	if(q->get_type() == MISSION_FAILED) return;	// cannot change stage once failed
	if(q->get_type() == MISSION_COMPLETED) return;	// cannot change stage once completed.
	q->set_time_fail(t);				// Sets how long before the mission expires
							// not all missions are timed.
							// doing it this way allows us to save the
							// time-left so we can pick up where we
							// left off! (hopefully)
	return false;	
}

/////////////////////////////////////////////////////////////////////////////////////////////////////////////
// mission fails
// mission slowly ticks down till failure!
void CHAR_DATA::check_fail() {
	FOREACH(Lexi::List<mission_data *>, mission_list, mission_iter) {
		mission_data *q = (*mission_iter);
		if(q->get_fail_time() != 0 && q->get_fail_time() < 2 && q->get_type() != MISSION_FAIL && q->get_type() != MISSION_COMPLETED) {
			ch->Sendf("You have failed the mission %s, ran out of time!", mission_name(q->get_vnum()));
			q->set_type(MISSION_FAILED);
			continue;
		}
		// lower us by 1, until we reach our end!
		if(q->get_fail_time() != 0) {
			q->set_fail_time(q->get_fail_time()-1);
		}
	}
	return;
}

COMMAND(cmd_mission) {
	BUFFER *output;
	if(NullString(argument)) {
		ch->Sendf("Syntax: mission <failed|completed|current>\n\r");
		return;
	}

	if(!str_cmp(argument, "current")) {
		int count = 0;
		output = new_buf();
		//	  vnum   name stage Time Left
		BufPrintf("[%6s] %20s %5s %10s\n\r", "SysNum", "Name", "Stage", "Time Left");
		Lexi::List<mission_data *>, ch->pcdata->mission_list, mission_iter) {
			mission_data *q = (*mission_iter);
			if(q->get_type () == MISSION_FAILED) continue;
			if(q->get_type () == MISSION_COMPLETED) continue;
			BufPrintf(output, "[%6d] %20s %5d %10d\n\r", q->get_vnum(), q->get_name(), q->get_stage(), q->get_fail_time());
			count++;
		}
		BufPrintf(output, "You have %d missions currently active!\n\r");
		page_to_char(buf_string(output), ch);
		free_buf(output);
		return;
	}

	if(!str_cmp(argument, "failed")) {
		int count = 0;
		output = new_buf();
		//	  vnum   name stage Time Left
		BufPrintf("[%6s] %20s %5s %10s\n\r", "SysNum", "Name", "Stage", "Time Left");
		Lexi::List<mission_data *>, ch->pcdata->mission_list, mission_iter) {
			mission_data *q = (*mission_iter);
			if(q->get_type () != MISSION_FAILED) continue;
			BufPrintf(output, "[%6d] %20s %5d %10d\n\r", q->get_vnum(), q->get_name(), q->get_stage(), q->get_fail_time());
			count++;
		}
		BufPrintf(output, "You have failed %d missions!\n\r");
		page_to_char(buf_string(output), ch);
		free_buf(output);
		return;
	}

	if(!str_cmp(argument, "completed")) {
		int count = 0;
		output = new_buf();
		//	  vnum   name stage Time Left
		BufPrintf("[%6s] %20s %5s %10s\n\r", "SysNum", "Name", "Stage", "Time Left");
		Lexi::List<mission_data *>, ch->pcdata->mission_list, mission_iter) {
			mission_data *q = (*mission_iter);
			if(q->get_type () != MISSION_FAILED) continue;
			BufPrintf(output, "[%6d] %20s %5d %10d\n\r", q->get_vnum(), q->get_name(), q->get_stage(), q->get_fail_time());
			count++;
		}
		BufPrintf(output, "You have completed %d missions!\n\r");
		page_to_char(buf_string(output), ch);
		free_buf(output);
		return;
	}

	ch->Sendf("What are you talking about?  Try your syntax again!\n\r");
	return;

}