TinyMighty.Converse = {

	options: { 
		username: 'guest'
	},
	
	conversations: {},
	
	status:-1,

	init: function init(options){
		console.log(this);
		this.setOptions(options);
		console.log('Init converse');
		this.ape = new APE.Client();

		this.user = {};
		this.cam = {id:null,enabled:false,permissions:{}};
		
		this.ape.addEvent('load', TinyMighty.Util.bindEventScope(this.eventHandlers.ape.load,this) );
		this.ape.addEvent('ready',  TinyMighty.Util.bindEventScope(this.eventHandlers.ape.ready,this) );
		this.ape.addEvent('userJoin', TinyMighty.Util.bindEventScope(this.eventHandlers.ape.userJoin,this) );
		this.ape.addEvent('restoreStart', TinyMighty.Util.bindEventScope(this.eventHandlers.ape.restoreStart,this) );
		this.ape.addEvent('restoreEnd', TinyMighty.Util.bindEventScope(this.eventHandlers.ape.restoreEnd,this) );
		this.ape.addEvent('multiPipeCreate', TinyMighty.Util.bindEventScope(this.eventHandlers.ape.multiPipeCreate,this) );
		
		this.ape.onRaw('IDENT', TinyMighty.Util.bindEventScope(this.eventHandlers.raw.ident,this) );
		//this.ape.onRaw('CHANNEL',this.events.raw.channel.bindWithEvent(this) );
		//this.ape.onRaw('CONFIRM_CONVERSATION',TinyMighty.Util.bindEventScope(this.eventHandlers.raw.confirmConversation,this) );
		//this.ape.onRaw('CONVERSATION_LIST',TinyMighty.Util.bindEventScope(this.eventHandlers.raw.conversationList,this) );
		this.ape.onRaw('CHANNEL_USERS',TinyMighty.Util.bindEventScope(this.eventHandlers.raw.channelUsers,this) );
		
		this.ape.addEvent('raw',TinyMighty.Util.bindEventScope(function(raw){ this.sendEvent('raw',raw) },this) );
		
		this.ape.onError('004', TinyMighty.Util.bindEventScope(this.eventHandlers.ape.sessionError,this));
		this.ape.onError('007', TinyMighty.Util.bindEventScope(this.eventHandlers.ape.nickError,this));
		
		//this.ape.onRaw();
		//init groups/views???
		
		this.ape.load({'identifier':'converse'});
		
		//console.log('Init end');
		
		return this;
	},

	eventHandlers:{
		ape:{
			load: function(){
				console.log('Ape loaded');
				
				if (!this.ape.core.options.restore) {
					console.log('options.restore is false, connecting');

					//this.ape.core.options.name = this.options.username;
					this.ape.core.start({'name':this.options.username});
				}else{
					console.log('options.restore is true, restoring');
					this.ape.core.start();
				}
			},
			ready: function(){
				console.log('Ape ready');
				this.status = 0;
			},
			
			restoreStart: function(){
				
			},
			restoreEnd: function(){

			},
				
			userJoin: function(user, pipe){
			},
	
			multiPipeCreate: function(pipe,options){
				
				switch(pipe.properties.type){
					case 'notifications':
						//notification events - eg: new user, user X is on cam
						//do we handle this in another object??
						this.global = {};
						this.global.pipe = pipe;
						
						pipe.addEvent('userJoin',function(raw){
							console.log('user joined global');
							console.log(raw);
						});
						pipe.addEvent('userLeft',function(raw){
							console.log('user left global');
							console.log(raw);
						});
						
						pipe.request.send('GET_CHANNEL_USERS',{channel:pipe.pipe.pubid});
						this.initNotifications(pipe);
					break;
					case 'conversation':
						//this.initConversation(pipe.pipe.pubid,{'id':pipe.pipe.pubid,'pipe':pipe,'name':pipe.properties.name,'users':pipe.users});
					break;
					default:
					break;
				}
				//this.addConversation(pipe,options);*/
			},
	
	
			sessionError: function(){
				console.log('Ape session error, reloading');
				this.ape.core.clearSession();
				this.ape.core.initialize(this.ape.core.options);
			},
			nickError: function(){
				console.log('Nickname already in use.  This could be a session error');
			}
		},
		
		raw:{
			ident: function(raw){
				this.user.ape = raw.data.user;
				this.user.id = raw.data.user.pubid;
				this.user.name = raw.data.user.properties.name;
				this.user.pipe = this.ape.core.getPipe(this.user.id);

				this.status = 1;
				this.sendEvent('ready');
			},
			
			channel: function(raw){
			},
			
			channelUsers: function(raw){
				if(raw.data.channel == this.global.pipe.pipe.pubid){
					this.global.users = raw.data.users;
					this.sendEvent('allUsers',this.global.users);
				}
			}
		},
		
		camera:{
			publish: function(status){
				console.log('Received cam status: '+status+'  ...sending to server.');
				var cam = {id:this.user.name};
				if(status){
					cam.enabled = true;
				}else{
					cam.enabled = false;
				}
				this.user.pipe.request.sendRaw('SET_CAM',cam);
				this.cam = cam;
			}
		}
	},
	
	
	//total hack - camera should be part of a view...
	setCamera: function(cam){
		//console.log(cam);
		this.camswf = cam;
		setTimeout(TinyMighty.Util.bindEventScope(function(){
		this.camswf.addEvent('publish', TinyMighty.Util.bindEventScope(this.eventHandlers.camera.publish,this) );
		},this),300);
	},
	
	setCameraPermission: function(user,permission){
		this.cam.permissions[user] = permission;
		this.user.pipe.request.sendRaw('SET_CAM',this.cam);
		delete this.cam.permissions[user];
	},
	
	initNotifications: function(pipe){
		pipe.addEvent('userJoin',function(user,pipe){
			
		});
		pipe.onRaw('PUBLIC_CAM',function(raw){
			
		});
		pipe.onRaw('ADD_NOTIFICATION',function(raw){
			
		});
		
	}
		
};

TinyMighty.Util.mixin(
	TinyMighty.Converse,
	TinyMighty.Mixin.Options,
	TinyMighty.Mixin.Events
);

TinyMighty.Converse.Views = {};
TinyMighty.Converse.Models = {};
TinyMighty.Converse.Controllers = {};



TinyMighty.Converse.Controllers.Conversations = function ConversationsController(converse,options){
	this.converse = converse;
	this.user = this.converse.user;
	this.setOptions(options);
	this.conversations = {};
	
	this.converse.addEvent('ready',TinyMighty.Util.bindEventScope(this.init,this));
	this.converse.addEvent('raw',TinyMighty.Util.bindEventScope(this.raw,this));
	
}
TinyMighty.Converse.Controllers.Conversations.prototype = {
	
	init: function(event){
		
	},
	
	raw: function(event){
		//console.log('GOT RAW?');
		//console.log(event);
		var raw = event.data.raw;
		var data = event.data.data;
		switch(raw){
			case 'CONFIRM_CONVERSATION':
				console.log("RAW: CONFIRM_CONVERSATION");
				this.confirmConversation(data);
			break;
			case 'CONVERSATION_LIST':
				console.log("RAW: CONVERSATION_LIST");
				this.conversationList(data);
			break;
			
		}
	},
	
	conversationList: function(data){
		console.log('Received conversation list');
		console.log(data);
		var conversations = data;
		console.log(conversations);
		if(this.user.ape.pipes){
			for(var i in conversations){
				var conversation = conversations[i];
				//check we're dealing with data we want, not namespace pollution from MooTools/Prototype etc...
				if(typeof conversation == 'object' && conversation.id != undefined){
					console.log('Attempting to restore conversation '+conversation.id);
					if(this.user.ape.pipes[conversation.id] && this.user.ape.pipes[conversation.id].properties.type == 'conversation'){
						this.restoreConversation(conversation.id,conversation);
					}
				}						
			}
		}
	},
	
	startConversation: function(users){
		//console.log('Creating conversation with:');
		//console.log(users);
		if(!(users instanceof Array) && typeof users != 'string')
			throw 'InvalidUser';
		if(!(users instanceof Array))
			users = [users];
		var options = {};

		//this needs to be changed for serious multiuser
		options.title = (users.length < 2) ? users[0] : users.join(', ');
		var conversation = new TinyMighty.Converse.Controllers.Conversation(this.converse,null,this.options);
		conversation.invite(users);

		conversation.addEvent('ready', TinyMighty.Util.bindEventScope(function(event){
			console.log('Storing conversation...');
			console.log(conversation);
			if(conversation.id != undefined){
				this.conversations[conversation.id] = conversation; 
			}else{
				console.error("Conversation does not have a valid id");
				throw "InvalidConversationId";
			}
		},this));
		return conversation;
	},

	joinConversation: function(id){
		//console.log("Joining conversation: "+id);
		if(id == undefined || typeof id != 'string'){
			throw 'InvalidConversationId';
		}
		var conversation = new TinyMighty.Converse.Controllers.Conversation(this.converse,{'id':id},this.options);
		this.conversations[conversation.id] = conversation;
		return conversation;
	},
	
	confirmConversation: function(data){
		var event = this.sendEvent('conversationRequest',data);
		if(!event.isDefaultPrevented())
			this.joinConversation(data.id);
		//var conversation = new TinyMighty.Converse.Controllers.Conversation(this.converse,{id:data.id});
	//	this.conversations[data.id] = conversation;
	},

	declineConversation: function(id){
		this.user.pipe.request.send('DECLINE_CONVERSATION',{conversation:id});
	},
	
	restoreConversation: function(id,data){
		console.log('Restoring conversation '+id);
		console.log(data);
		if(id == undefined || typeof id != 'string'){
			console.error('Invalid or undefined conversation id: '+id);
			throw 'InvalidConversationId';
		}
		if( this.conversations[id] == undefined ){			
			var conversation = new TinyMighty.Converse.Controllers.Conversation(this.converse,data,this.options);
			this.conversations[id] = conversation;
		}else{
			console.log('Attempt was made to restore existing conversation. Action ignored.');
			//var conversation = this.conversations.get(id);
			//umm... we shouldn't need to really do anything here actually, 
		}		
	}
}
TinyMighty.Util.mixin(
	TinyMighty.Converse.Controllers.Conversations,
	TinyMighty.Mixin.Options,
	TinyMighty.Mixin.Events
);



TinyMighty.Converse.Controllers.Conversation = function ConversationController(converse,data,options){
		
		console.log('new Conversation instance');
		console.log(data);
		console.log(options);
		this.setOptions(options);
		this.converse = converse;
		
		this.model = new TinyMighty.Converse.Models.Conversation(converse,data,options);
		if(this.options.useView == true)
			this.view = new TinyMighty.Converse.Views.Conversation(converse,options);
		
		/*this.model.addEvents({
			'ready':this.modelEvents.ready.bindWithEvent(this),
			'userJoin':this.modelEvents.userJoin.bindWithEvent(this),
			'userLeave':this.modelEvents.userLeave.bindWithEvent(this),
			'messageSent':this.modelEvents.messageSent.bindWithEvent(this),
			'messageReceived':this.modelEvents.messageReceived.bindWithEvent(this)
		});*/
		for(var name in this.eventHandlers.model){
			var handler = this.eventHandlers.model[name];
			this.model.addEvent(name,TinyMighty.Util.bindEventScope(handler,this));
		}
		if(this.view){
			for(var name in this.eventHandlers.view){
				var handler = this.eventHandlers.view[name];
				this.view.addEvent(name,TinyMighty.Util.bindEventScope(handler,this));
			}
		}
};

TinyMighty.Converse.Controllers.Conversation.prototype = {
	settings: {
		useView: true,
		events: {
			chain: TinyMighty.Converse
		}
	},
	eventHandlers:{
		model:{
			ready: function(){
				this.id = this.model.id;
				if(this.view){
					var users = [];
					var tmpusers = this.model.getUsers();
					for(var i in tmpusers){
						var user = tmpusers[i];
						users.push(user);
					}
				
					this.view.setTitle(this.model.title);
					this.view.setUsers(users);
					this.view.setMessages(this.model.getMessages());
					console.group('Model is ready, setting up view...');
					console.log(this.view.status);
					console.groupEnd();
					this.view.redraw();
				}
				this.sendEvent('ready');
			},
			userJoin: function(ev){
				console.log('Controller received userJoin event from model');
				if(this.view)
					this.view.addUser(ev.data);
			},
			userLeave: function(ev){
				if(this.view){ //if user closed the view might be gone already!
					this.view.removeUser(ev.data.id);
				}
			},
			messageSent: function(ev){
				if(this.view)
					this.view.addMessage(ev.data);
			},
			messageReceived: function(ev){
				if(this.view)
					this.view.addMessage(ev.data);
			},
			addMessage: function(ev){
				//console.log('Caught addMessage event from model');
				if(this.view)
					this.view.addMessage(ev.data);
			}
		},
	
	
		view:{
			sendMessage: function(event){
				this.model.sendMessage(event.data.message);
			},
			close: function(){
				this.model.removeUser(this.converse.user.ape);
			}
		}
	},
	
	/*sanitiseModelUser: function(modelUser){
		console.log("!!!!!!!");
		console.log(modelUser);
		if(!modelUser.pubid || !modelUser.properties)
			throw 'InvalidModelUser';
		return {id: modelUser.pubid, name: modelUser.properties.name, cam:modelUser.properties.cam}
	},*/

	sendMessage: function(msg){
		this.model.sendMessage(msg);
	},
	
	invite: function(users){
		if( users == undefined || !(users instanceof Array) || users.length<1 )
			throw 'InvalidUsers';
		this.model.invite(users);
	}


};
TinyMighty.Util.mixin(
	TinyMighty.Converse.Controllers.Conversation,
	TinyMighty.Mixin.Options,
	TinyMighty.Mixin.Events
);

TinyMighty.Converse.Models.Conversation = function ConversationModel(converse,data,options){
	console.log('new Conversation model');
	console.log(data);
	console.log(options);
	this.setOptions(options);
	this.converse = converse;
	
	this.users = {};
	this.status = -1;
	this.messages = [];
	this.notifications = [];
	this.queue = [];
	this.users = {};
	
	if(this.converse.status > 0){
		this.setup(data);
	}else{
		this.converse.addEvent('ready',TinyMighty.Util.bindEventScope(this.setup,this,data));
	}
};
TinyMighty.Converse.Models.Conversation.prototype = {	
	setup: function(data){
		this.ape = this.converse.ape;
		this.user = this.converse.user;
		
		this.ape.addEvent('multiPipeCreate', TinyMighty.Util.bindEventScope(this.eventHandlers.multiPipeCreate,this));
		this.ape.onRaw('INIT_CONVERSATION', TinyMighty.Util.bindEventScope(this.eventHandlers.initConversation,this));
		
		
		if(data && data.id){
			this.id = data.id;
			if(data.name)
				this.name = data.name;
			if(data.title)
				this.title = data.title;
			var pipe = data.pipe ? data.pipe : this.user.ape.pipes[this.id];
			
			//HACK TO GET AROUND CHANNEL LEFT BUG
			if( data.users )
				this.setUsers(data.users);
			if(pipe){
				this.setPipe(pipe);
				this.user.pipe.request.send('RESTORE_CONVERSATION',{id:this.id});
			}else{
				this.user.pipe.request.send('JOIN_CONVERSATION',{id:this.id});
			}
			
			if(data.messages)
				this.setMessages(data.messages);
	
			
		}else{
			console.log('Creating new conversation');
			var opts = {};
			var name = (data && data.name) ? data.name : this.user.name+Math.floor(Date.now()/10)+Math.floor(Math.random()*1000);//;Math.floor(+Math.floor(Math.random()*1000)*0.015);
			this.name = name;
			opts.name = name;
			if(this.options.title)
				opts.title = this.options.title;

			this.user.pipe.request.send('CREATE_CONVERSATION',opts);
		}
		
		//this.ape.core.join(name);
		this.addEvent('connected',TinyMighty.Util.bindEventScope(this.eventHandlers.connected,this));
		this.addEvent('ready',TinyMighty.Util.bindEventScope(this.eventHandlers.ready,this));

	},

	eventHandlers:{
		multiPipeCreate: function(pipe,options){
			
			if(pipe.properties.type == 'conversation'){
				if(this.id != undefined && this.id == pipe.pipe.pubid){
					this.setPipe(pipe);
				}else if(this.id == undefined && pipe.properties.name == this.name){
					this.setPipe(pipe);
				}
			}
		
		},
	
		connected: function(){
			this.sendQueue();
		},
		
		ready: function(){
			console.log('Conversation model is ready');
		},

		initConversation: function(raw){
			if(this.status<0){
				console.log('Init conversation received for ID '+raw.data.id+' - this is '+this.id);
				if(this.id != undefined && raw.data.id == this.id){
					if(raw.data.messages)
						this.setMessages(raw.data.messages);
					if(raw.data.title)
						this.name = raw.data.title;
					if(raw.data.users)
						this.setUsers(raw.data.users);
					this.status = 1;
					this.sendEvent('ready');
				}
			}
		},
		
		addMessage: function(raw){
			if(raw.data.user == undefined || raw.data.message == undefined)
				throw 'Invalid Message';
			var message = {
				user:  raw.data.user,
				message:decodeURIComponent(raw.data.message),
				time:raw.time
			};
			this.addMessage(message);
		},
		
		addNotification: function(raw){
			if(raw.data.message == undefined)
				throw 'Invalid Notification';
			var notification = {
				type: raw.data.type || 'notice',
				message:decodeURIComponent(raw.data.message),
				time:raw.time
			};
			if(raw.data.data)
				notification.data = raw.data.data;
			this.addNotification(notification);			
		},
		
		userJoin: function(raw){
			var user = raw.data.user;
			console.group('User '+user.properties.name+' joined '+this.name);
			console.log(user);
			console.groupEnd();
			this.addUser(user);
			//this.sendEvent('userJoin',{user:user});
		},
		
		userLeft: function(raw){
			console.log('caught USER_LEFT raw...');
			var user = this.users[raw.data.user];
			if(user){
				delete this.users[user.id];
				console.group('User '+user.name+' left '+this.name);
				console.log(user);
				console.groupEnd();
				this.sendEvent('userLeave',user);
			}
		}
	},
	
	setPipe: function(pipe){
		if(pipe){
			
			//if we're joining a pipe, we know it's pubid but not it's name
			if(this.id && !this.name && pipe.pipe.pubid == this.id){
				this.name = pipe.pipe.properties.name;
				this.pipe = pipe;
			//if it's a new pipe, we know it's name but not it's pubid
			}else if(!this.id && this.name && pipe.pipe.properties.name == this.name){
				this.id = pipe.pipe.pubid;
				this.pipe = pipe;
			//if we're restoring a pipe, we know it's pubid, and may know it's name
			}else if(this.id && pipe.pipe.pubid == this.id){
				this.pipe = pipe;
			}else{
				throw 'Incorrect Pipe';
			}
			
			
			//We're bypassing this
			/*if(this.pipe.users){
				if($defined(this.userIds)){
					var users = {};
					for(i in this.pipe.users){
						if(this.userIds.indexOf(this.pipe.users[i].pubid) > -1)
							users.set(this.pipe.users[i].pubid,this.pipe.users[i]);
					}
					this.setUsers(users);
				}else{
					this.setUsers(this.pipe.users);
				}
				
			}*/
			
			//console.log('Adding events to pipe:');
			//console.log(this.pipe);
			
			this.pipe.onRaw('JOIN', TinyMighty.Util.bindEventScope(this.eventHandlers.userJoin,this));
			//this.pipe.addEvent('userLeft', this.events.userLeft.bindWithEvent(this));
			
			//workaround for ape userleft bug
			this.pipe.onRaw('USER_LEFT', TinyMighty.Util.bindEventScope(this.eventHandlers.userLeft,this));
			this.pipe.onRaw('ADD_MESSAGE',TinyMighty.Util.bindEventScope(this.eventHandlers.addMessage,this));
			this.pipe.onRaw('ADD_NOTIFICATION', TinyMighty.Util.bindEventScope(this.eventHandlers.addNotification,this));
			
			this.sendEvent('connected');
		}
	},

	
	invite: function(users){
		console.log('attempting to invite');
		console.log(users);
		
		if( !(users instanceof Array))
			throw 'InvalidUsers';

		
		if(users != undefined && (users instanceof Array)){

			if(users.length>0){
				if(this.status>0){
					console.log("Inviting users to conversation "+this.name);
					console.log(users);
					for(var i=0; i<users.length; i++){
						var user = users[i];
						this.user.pipe.request.send('INVITE_TO_CONVERSATION',{'user':user,'conversation':this.id});
					}

				}else{
					console.log('not ready to invite, adding to ready event');
					this.addEvent('ready', TinyMighty.Util.bindScope(this.invite,this,[users]));
				}
			}
		}else{
			throw 'Invalid User Array';
		}
	},

	addUser: function(user){
		if(user == undefined || user.id == undefined)
			throw 'Invalid User';
		if(this.users[user.id] == undefined){
			this.users[user.id] = user;
		}
		this.sendEvent('userJoin',user);
	},	
	
	addUsers: function(users){
		for(var i in users){
			var user = users[i];
			this.addUser(user);
		}
	},
	
	setUsers: function(users){
		for(var i in users){
			var user = users[i];
			if(this.users[user.id] == undefined){
				this.users[user.id] = user;
			}
		}
	},
	
	removeUser: function(user){
		/*console.group('Removing user');
		console.log(user);
		console.log(this.users);
		console.groupEnd();*/
		if(this.users[user.pubid] != undefined)
			delete this.users[user.pubid];
		this.pipe.request.send('LEAVE_CONVERSATION',{'conversation':this.id});
		this.sendEvent('userLeave',user);
	},
		
	addMessage: function(msg){
		this.messages.push(msg);
		this.sendEvent('addMessage',msg);
	},
	
	sendMessage: function(msg){	
		if(this.status>0){
			this.pipe.request.send('SEND_MESSAGE',{'conversation':this.id,'message':msg});
		}else{
			this.queue.push(msg);
		}
	},
	
	addNotification: function(notification){
		this.notifications.push(notification);
		this.sendEvent('addNotification', notification);
	},
	
	sendQueue: function(){
		if(this.status == 1 && this.queue.length > 0){
			for(var i in this.queue){
				var msg = this.queue[i];
				this.sendMessage(msg);
			}

		}
	},
	
	getUsers: function(){
		return this.users;
	},
	getMessages: function(){
		return this.messages;
	},
	setMessages: function(messages){
		for(var i=0;i<messages.length;i++){
			var msg = messages[i];
			this.messages.push({
				user: msg.user,
				message: decodeURIComponent(msg.message),
				time: msg.time
			});
		}
	
	}
	
};
TinyMighty.Util.mixin(
	TinyMighty.Converse.Models.Conversation,
	TinyMighty.Mixin.Options,
	TinyMighty.Mixin.Events
);




TinyMighty.Converse.Views.Conversation = function ConversationView(converse, options){

	this.setOptions(options);
	this.converse = converse;
	var theclass = 'conversation';
	/*if(this.users.getLength() == 2 && !data.title){ 
		///if 2 users, set the title to their username
		//get their username for the title
		$H(this.data.users).each(function(v,k){ if(k!==this.data.me){ them=v; } },this);
		this.title = them;
	}
	if(this.users.getLength() > 2){
		theclass = theclass + ' multiuser';
	}
	theclass = theclass + ' section';*/
	
	/*
	-1 Initializing
	0 Disabled
	1 Enabled
	*/
	this.status = -1; 

	this.title = this.options.title;
	
	this.els = {};
	this.els.container = jQuery('<div></div>').attr({'data-chatid':this.id,'class':theclass});
	
	this.users = {};
	this.messages = [];
	
	jQuery('#converse-container').append(this.els.container);
	//this.redraw();
};

TinyMighty.Converse.Views.Conversation.prototype = {
	setUsers: function(users){
		if(typeof users == 'array'){
			for(var i in users){
				var user = users[i];
				if(!user.id || !user.name || !user.cam)
					throw 'Invalid Users Array';
				this.users[user.id] = user;
			}

		}else if(typeof users == 'object'){
			for(var i in users){
				var user = users[i];
				if(!user.id || !user.name || !user.cam)
					throw 'Invalid Users Object';
			}

			this.users = users;
		}
		var usersLength = 0;
		for(var i in this.users) usersLength++;
		if(usersLength > 1){
			this.enable();
		}else{
			this.disable();
		}
		
	},
	setMessages: function(messages){
		if(messages.length> 0){
			for(var i in messages){
				var msg = messages[i];
				this.addMessage(msg);
			}

		}
		this.redraw();
	},
	setTitle: function(title){
		this.title = title;
		this.redraw();
	},
	addUser: function(user){
		//expects simplified user object: {id:XXX, name:XXX}
		console.log('Adding user to view: ');
		console.log(user);
		var oldlength = 0;
		for(var i in this.users) oldlength++;
	
		this.users[user.id] = user;
		var usersLength = 0;
		for(var i in this.users) usersLength++;
		//if we're adding a third user, redraw (to multiuser)
		if(usersLength > 2 && oldlength == 2){
			this.redraw();
		
		//if we're adding a second user, enable the chat
		}else if(usersLength> 1 && oldlength == 1 && this.status < 1){
			this.enable();
		}
	},
	removeUser: function(userid){
		console.group('Attempting to remove '+userid+' from...');
		console.log(this.users);
		delete this.users[userid];
		console.log(this.users);
		console.groupEnd();
		var usersLength = 0;
		for(var i in this.users) usersLength++;
		//if we're removing the second to last user, disable the chat
		if(usersLength < 2){
			this.disable();
		}else{
			this.redraw();
		}
	},
	addMessage: function(msg){
		this.messages.push(msg);
		//msg.user = this.users.get(msg.user);
		this.drawMessage(msg);
	},
	getContainerElement: function(){
		return this.container;
	},
	dataUpdateEvent: function(ev){
		this.update(ev.data);
	},
	update: function(){
		

	},
	
	redraw: function(){
		console.log('Drawing conversation');

		this.els.container.empty();
		
		if(this.status<1){
			this.els.container.addClass('disabled');
		}else{
			this.els.container.removeClass('disabled');
		}
		
		this.els.conversationText = jQuery('<div></div>').attr({'class':'conversation-text'});
		this.els.cam = jQuery('<div></div>').attr({'class':'conversation-cam'});
		this.els.camSwf = jQuery('<div></div>').attr({'class':'conversation-cam-swf','id':'conversation-cam-'+this.converse.user.id+Date.now()+Math.floor(Math.random()*100)});

		this.els.content = jQuery('<div></div>').attr({'class':'conversation-content'});
		var username = '';
		for(var i in this.users){
			var user = this.users[i];
			if(user.id !== this.converse.user.id) username = user.name;
		}


		//this needs changing for multiuser chat...
		this.els.header = jQuery('<h2></h2>').text(username || this.title || "Conversation");
		
		this.els.closeButton = jQuery('<div></div>').attr({'class':'close'})
			.css('cursor','pointer')
			.text('x')
			.click(TinyMighty.Util.bindEventScope(this.closeButtonClickEvent,this));
		
	 	this.els.composer = jQuery('<div></div>').attr({'class':'message-composer'});
		this.els.composerField = jQuery('<input></input>').attr({'type':'text','class':'entryfield'});
		this.els.composerButton = jQuery('<div></div>').attr({'class':'send button'})
			.text('Send');

		if(this.status>0){
			this.els.composerButton
				.click(TinyMighty.Util.bindEventScope(this.sendButtonClickEvent,this))
				.keydown(function(event){
					console.log(event);
			   		console.log(event.keyCode);
				});
		}else{
			this.els.composerField.attr('disabled','disabled');
			this.els.composerButton.css('cursor','default');
		}
		
		this.els.cam.append( this.els.camSwf );
			
		this.els.composer.append( this.els.composerField );
		this.els.composer.append( this.els.composerButton );
		
		this.els.header.append( this.els.closeButton );
		
		this.els.container.append( this.els.header );
		//this.els.conversationText.append( this.els.camLink );
		this.els.conversationText.append( this.els.content );
		this.els.conversationText.append( this.els.composer );
		
		this.els.container.append(this.els.conversationText);
		this.els.container.append(this.els.cam);
		
		this.els.conversationText.click( TinyMighty.Util.bindEventScope(function(){ this.els.composerField.focus(); },this) );
		
		//for now there should only be two users, but this needs to be changed for multiuser chat
		for(var i in this.users){
			var user = this.users[i];
			if(user.id!==this.converse.user.id){
				//if(user.cam.permissions && user.cam.permissions[this.converse.user.id]==true){
					swfobject.embedSWF('./library/cam/subscriber.swf', this.els.camSwf.attr('id'), 320, 265, '9.0.98', 'swf/expressInstall.swf', {'user':user.name,'server':'rtmp://94.236.101.123/videochat'}, {}, {}, function(ev){ console.log(ev); });
				/*}else{
					if(user.cam.enabled){
						this.els.cam.appendText(user.name+" is not sharing their camera with you.  Click here to request access.");
					}else{
						this.els.cam.appendText(user.name+"'s cam is not enabled.");
					}
				}*/
			}
		}
		
		for(var i=0;i<this.messages.length;i++){
			var msg = this.messages[i];
			this.drawMessage(msg);
		}

		this.sendEvent('redraw');
	},



	drawMessage: function(msg){
		var entry = null;
		var usersLength = 0;
		for(var i in this.users) usersLength++;
		//expensive to do this check every time - should be moved elsewhere
		if(usersLength > 2){
			entry = jQuery('<p></p>').attr({'class':'message','data-user':msg.user.id,'data-time':msg.time});
			console.log(msg.user);
			console.log(this.users);
			entry.append( jQuery('<span></span>').attr({'class':'user'}).text(msg.user.name) );
		}else{
			//console.log('comparing user for view');
			//console.log(this.converse.user.id + ' - ' + msg.user);
			//console.log(msg);
			theclass = (this.converse.user.id == msg.user.id) ? 'me' : 'them';
			entry = jQuery('<p></p>').attr({'class':theclass,'data-user':msg.user.id,'data-time':msg.time});
		}
		entry.text(msg.message);
		this.els.content.append(entry);
		this.els.content.scrollTo('max');
	},
	
	drawNotification: function(message,type,clickhandler){
		var theclass="notice";
		if(type != undefined){
			switch(type){
				case 'user':
					theclass = 'user';
				break;
				case 'error':
					theclass = 'error';
				break;
			}
		}
		var notification = jQuery('<div></div>').attr({'class':'notification '+theclass}).text(message);
		if(clickhandler != undefined && typeof clickhandler == 'function'){
			notification.addEvent('click',clickhandler);
		}
		this.els.content.appent(notification);
		this.els.content.scrollTo('max');
	},
	
	highlight: function(){
		
	},
	dim: function(){
		
	},
	alert: function(){
		
	},
	
	disable: function(){
		this.status = 0;
		this.redraw();
	},
	enable: function(){
		this.status = 1;
		this.redraw();
	},
	
	close: function(){
		this.sendEvent('close');
		this.els.container.empty();
		this.els.container = this.els.container.detach();
	},
	
	sendButtonClickEvent: function(){
		var msg = this.els.composerField.val();
		if(msg.length > 0){
			this.sendEvent('sendMessage',{message:msg});
			this.els.composerField.val('');
		}
		this.els.composerField.focus();
	},
	
	closeButtonClickEvent: function(ev){
		//ev.stop();
		this.close();
	}
};

TinyMighty.Util.mixin(
	TinyMighty.Converse.Views.Conversation,
	TinyMighty.Mixin.Options,
	TinyMighty.Mixin.Events
);


/*
CONTINUE LATER!

TinyMighty.Converse.Controllers.Camera = new Class({
	Implements: [Options, Events],
	
	options:{
		container:'my-bar',
		id:'my-cam'
	},
	
	initialize: function(converse,options){
		this.converse = converse;
		this.setOptions(options);
	},
	
	draw: function(){
		
	}
	
});

TinyMighty.Converse.Controllers.CameraPlayer = new Class({});*/







/*TinyMighty.Converse.Views.ConversationGroup = new Class({
	Implements: [Options,Events],
	options:{
		id:null,
		title:'Conversations',
		containerSelector: '#converse-container'
	},
	//chatdata is an object of chats keyed by a unique identifier
	initialize: function(data, options){
		this.setOptions(options);
		
		this.container = new Element('div',{'class':'converse-group',id:this.options.id});
		$$(this.options.containerSelector).grab( container );
		
		if(container.length < 1 || container.length > 1)
			throw 'Invalid container';
		this.container = container[0];
		
		this.data = data;
		this.title = data.title ? data.title : this.options.title;
		this.conversations = [];
		
		this.data.each(function(data,i){
			var conversation = new TinyMighty.Converse.Views.Conversation(data);
			this.conversations.push( conversation );
			//this.container.grab(conversation.getContainerElement());
		},this);
		
		this.redraw();
	},
	
	update: function(data){
		
	},
	
	addConversation: function(data){
		
	},
	
	redraw: function(){
		this.container.empty();
		
		var header = new Element('h1').appendText(this.title);
		this.container.grab(header);
		this.conversations.each(function(c,i){
			this.drawConversation(c);
		},this);
	},
	
	drawConversation: function(conversation){
		//check if conversation is already in DOM
		//if( !this.container.getChildren('div[data-chatid='+conversation.id+']') )
			this.container.grab(conversation.getContainerElement());
	},
	
	
	closeClickEvent: function(event){
		event.preventDefault();
		this.triggerEvent();
		return false;
	},
	titlebarClickEvent: function(event){
		event.preventDefault();
		
		
		return false;
	}
});
*/
