#ifndef _CHANNEL_H
#define _CHANNEL_H
#include <iostream>
#include <list>
#include <mysql/mysql.h>
#include "merc.h"

class Topic;
class Post;
class Channel;
extern MYSQL *db;
extern std::list<Channel *> chanList;
typedef void (Channel::*CmdFun)(ACCOUNT *, char *);
struct Command
{	char *name;
	CmdFun cmdfun;
	bool onReq;
};
extern struct Command chanCmdTable[];

class Channel
{   public:
	char *name;
	std::list<Topic *> topics;
	int bit;
	int lastTID;
	Channel(char *name);
	~Channel();
	void Send(ACCOUNT *pAcnt, std::string &txt);
	Topic *getTopic(int id);
	void interpret(ACCOUNT *pAcnt, char *name);
	void LoadTopics();
	void TopicHist(ACCOUNT *pAcnt, char *argument);
	void HandleBanned(ACCOUNT *pAcnt, char *argument);
	void New(ACCOUNT *, char *);
	void Ignore(ACCOUNT *, char *);
	void Acknowledge(ACCOUNT *, char *);
	void On(ACCOUNT *, char *);
	void Off(ACCOUNT *, char *);
	void History(ACCOUNT *, char *);
	void Lock(ACCOUNT *, char *);
	bool CheckChanFunc(ACCOUNT *pAcnt, char *argument )
	{	char cmd[MSL];
		argument = one_argument(argument,cmd);
		if(cmd[0] == '\0')
			return false;
		for( int i = 0; chanCmdTable[i].name != NULL ; ++i )
		{	if(!str_prefix(cmd, chanCmdTable[i].name) )
			{	if(!IS_SET(pAcnt->channel, bit) && chanCmdTable[i].onReq)
					ptc(pAcnt, "You have to have the channel on to use this function.\n\r");
				else
					(this->*(chanCmdTable[i].cmdfun))(pAcnt, argument);
				return true;
			}
		}
		return false;
	}
	static void loadChannels()
	{	MYSQL_ROW row;
		MYSQL_RES *res;
		int maxChans;
		char query[MSL];
		sprintf(query, "SELECT * FROM Channels");
		if( mysql_real_query(db, query, strlen(query)) )
		{	logfp(LOG_BUG, "loadChannels: %s", mysql_error(db) );
			return;
		}
		if( !(res = mysql_store_result(db) ) )
		{	logfp(LOG_BUG, "loadChannels: Result null!");
			return;
		}
		if( (maxChans = mysql_num_rows(res) ) <= 0 )
		{	logfp(LOG_BUG, "loadChannels: rows <= 0" );
			mysql_free_result(res);
			return;
		}
	
		for(int i = 0; i < maxChans; i++ )
		{	row = mysql_fetch_row(res);
			Channel *chan = new Channel(row[0]);
			chan->bit = atoi(row[1]);
			chan->lastTID = atoi(row[2]);
			chanList.push_back(chan);
			chan->LoadTopics();
		}
		mysql_free_result(res);

	}
	static Channel *find(const char *name)
	{	std::list<Channel *>::iterator i;
		for( i = chanList.begin() ; i != chanList.end() ; ++i )
		{	if(LOWER(name[0]) == LOWER((*i)->name[0]) &&
			   !str_prefix(name, (*i)->name) )
				return (*i);
		}
		return NULL;
	}
    private:
	Channel( const Channel & );

};

class Topic
{   public:
	char *name;
	char *subject;
	int id;
	Channel *on;
	int lastPID;
	bool locked;
	std::list<Post *> posts;
	
	Topic(Channel *parent);
	~Topic();
	void Send();
	Post *getPost(int id);
	void Lock(){ locked = true; }
	void Unlock() { locked = false; }
	void Log();
	void LoadPosts();
	void PostHist(ACCOUNT *, char *);
    private:	
	Topic( const Topic & );
};

class Post
{   public:
	char *poster;
	std::list<Post *> replies;
	int parentID;
	int id;
	Topic *on;
	char *msg;
	time_t timeStamp;

	Post(Topic *);
	Post(Post *);
	~Post();
	void Send();
	void Log();
     private:
	Post( const Post & );
};


		
#endif