class CreateRoomHandler(tornado.web.RequestHandler):
    def find_dealer(self):
        collection = DealerInfo.get_collection()
        dealer = collection.find(sort=[("rooms", 1)], limit=1)[0]
        return dealer

    @tornado.web.asynchronous
    @authenticate
    def post(self):
        roomType = self.get_argument("roomType", None)
        blind = int(self.get_argument("blind"))
        max_stake = blind * 200
        min_stake = blind * 10
        max_player = self.get_argument("max_player")
        room = ConfigReader.getObj("room")[roomType]

        if blind < room[0] or blind > room[1]:
            self.finish()
            return
        if (blind - room[0]) % room[2] != 0:
            self.finish()
            return

        dealer = self.find_dealer()
        self.channel = Channel(self.application.channel,
                               str(dealer['exchange']))

        arguments = self.session["user_id"]
        self.channel.add_ready_action(self.connected_call_back, arguments)
        self.channel.add_message_action(self.message_call_back, None)
        self.channel.connect()

    def message_call_back(self, argument):
        message = self.channel.get_messages()[0]
        self.write(json.dumps(message))
        self.finish()

    def connected_call_back(self, userid):
        blind = int(self.get_argument("blind"))
        roomType = int(self.get_argument("roomType", None))
        max_stake = blind * 200
        min_stake = blind * 10
        max_player = self.get_argument("max_player")

        msg = {
            "method": "create_room",
            "blind": blind,
            "max_stake": max_stake,
            "min_stake": min_stake,
            "max_player": max_player,
            "user_id": str(userid),
            "roomType": roomType,
            "source": self.channel.routing_key
        }

        self.channel.publish_message("dealer", json.dumps(msg))
class CreateRoomHandler(tornado.web.RequestHandler):
	def find_dealer(self):
		collection = DealerInfo.get_collection()
		dealer = collection.find(sort=[("rooms",1)],limit=1)[0]
		return dealer

	@tornado.web.asynchronous
	@authenticate
	def post(self):
		roomType	= self.get_argument("roomType",None)
		blind		= int(self.get_argument("blind"))
		max_stake	= blind * 200
		min_stake	= blind * 10
		max_player	= self.get_argument("max_player")
		room = ConfigReader.getObj("room")[roomType]

		if blind < room[0] or blind > room[1]:
			self.finish()
			return
		if (blind - room[0]) % room[2] != 0:
			self.finish()
			return

		dealer = self.find_dealer()
		self.channel	= Channel(
				self.application.channel,
				str(dealer['exchange']))

		arguments = self.session["user_id"]
		self.channel.add_ready_action(self.connected_call_back, arguments);
		self.channel.add_message_action(self.message_call_back, None)
		self.channel.connect()

	def message_call_back(self,argument):
		message = self.channel.get_messages()[0]
		self.write(json.dumps(message))
		self.finish()

	def connected_call_back(self,userid):
		blind		= int(self.get_argument("blind"))
		roomType	= int(self.get_argument("roomType",None))
		max_stake	= blind * 200
		min_stake	= blind * 10
		max_player	= self.get_argument("max_player")

		msg = {"method":"create_room","blind":blind,"max_stake":max_stake,"min_stake":min_stake,
				"max_player":max_player,"user_id":str(userid),"roomType":roomType,
				"source":self.channel.routing_key}

		self.channel.publish_message("dealer",json.dumps(msg))
class SitDownBoardHandler(tornado.web.RequestHandler):
	@tornado.web.asynchronous
	@authenticate
	def post(self):
		self.mongodb = self.application.settings['_db']
		user		= self.user
		seat		= self.get_argument('seat')
		stake		= self.get_argument('stake')

		if False and 'is_sit_down' in self.session and \
			self.session['is_sit_down'] == True and \
			self.session['seat'] == seat:
			self.write(json.dumps({'status':'success'}))
			self.finish()
		else:
			messages		= self.mongodb.board.find_one({"id":self.session.session_id})
			room			= Room.find(_id=messages["room_id"])
			if room is None:
				self.finish(json.dumps({'status':'failed'}))
				return

			queue_name		= str(user.username) + '_sit'
			exchange_name   = self.session['exchange']

			user.room_id	= room.id
			#exchange_name	= str(user.room.exchange)
			#source_key		= "%s_%s" % (exchange_name, queue_name)

			message			=	{
									'method':'sit',
									'user_id':user.id,
									'seat':seat,
									#'source':source_key,
									'room_id':str(user.room_id),
									'private_key':self.session['private_key'] ,
									'stake':stake
								}

			arguments		= {'routing_key': 'dealer', 'message':message}
			self.channel	= Channel(self.application.channel, exchange_name)
			self.channel.add_ready_action(self.sit_call_back, arguments)
			self.channel.connect()

	def sit_call_back(self, argument):
		if self.request.connection.stream.closed():
			self.channel.close()
			return

		self.channel.add_message_action(self.message_call_back, None)
		argument['message']['source'] = self.channel.routing_key
		self.channel.publish_message(argument['routing_key'], json.dumps(argument['message']))

	def message_call_back(self, argument):
		messages= self.channel.get_messages()[0]
		if self.request.connection.stream.closed():
			self.channel.close()
			return
		if messages['status'] == 'success':
			self.mongodb.board.update({"id":self.session.session_id},\
					{"$set" :{'is_sit_down':True}});

		self.write(json.dumps(messages))
		self.channel.close();
		self.finish()

	def on_connection_close(self):
		self.channel.close()
class EnterRoomHandler(tornado.web.RequestHandler):
	@tornado.web.asynchronous
	@authenticate
	def post(self):
		message			= None
		user			= self.user
		room_id			= self.get_argument('room_id')
		room			= Room.find(_id = room_id)
		if not room:
			print Room.find_all()
			print "not a valid room",room_id
			self.finish()
			return

		self.mongodb	= self.application.settings['_db']
		msg = {"id":self.session.session_id, "room_id":room.id}

		BoardMessage.get_collection().remove({
						"id":self.session.session_id,
						},safe=True)

		# guarantee only one exist
		self.mongodb.board.update({"id":self.session.session_id},msg,upsert=True)

		exchange			= str(room.exchange)

		self.session['exchange'] = exchange

		public_key			= ('broadcast_%s_%s.testing')% (exchange, room._id)
		private_key			= ('direct.%s.%s.%s') % (exchange, room._id, user._id)
		binding_keys		= [public_key, private_key]
		if user.isBot:
			bot_key			= ('direct.%s.%s.bot') % (exchange, room._id)
			binding_keys.append(bot_key)
			self.session['bot_key'] = bot_key


		message				= {	'method'		: 'enter',
								'user_id'		: user.id,
								'room_id'		: room.id,
								'private_key'	: private_key}

		arguments			= {'routing_key': 'dealer', 'message': message}
		self.broadcast_channel = broadcast_channel	= PersistentChannel(
									self.application.channel,
									"%s%s" % (str(self.session.session_id),room.id[-10:]),
									exchange,
									binding_keys,
									declare_queue_only=True,
									arguments = {"x-expires":int(600000)}
									)

		self.callBackCount = 0
		broadcast_channel.add_ready_action(self.initial_call_back,
				arguments)
		broadcast_channel.connect()

		self.channel = Channel(self.application.channel,exchange)

		self.channel.add_ready_action(self.initial_call_back, arguments);
		self.channel.connect()
		self.session['public_key']	= public_key
		self.session['private_key']	= private_key
		#self.session['messages']	= list()
		print "ENTER!"


	def purge_call_back(self,data):
		argument = self.argument
		self.channel.add_message_action(self.message_call_back, None)
		self.mongodb.board.update(
			{"id":self.session.session_id},
			{"$set": {'queue':self.broadcast_channel.queue_name}}
		)
		argument['message']['source'] = self.channel.routing_key
		self.channel.publish_message(	argument['routing_key'],
										json.dumps(argument['message']))

	def initial_call_back(self, argument):
		print "ENTER CALL BACK",argument
		self.callBackCount += 1
		if self.callBackCount < 2:
			#We have to wait broadcast_channel created
			return

		if self.request.connection.stream.closed():
			self.channel.close();
			return
		self.argument = argument
		self.application.channel.queue_purge(
			callback= self.purge_call_back,
			queue	= self.broadcast_channel.queue_name
		)



	def message_call_back(self, argument):
		messages= self.channel.get_messages()[0]
		if self.request.connection.stream.closed():
			self.channel.close();
			return
		self.write(json.dumps(messages))
		self.channel.close();
		self.finish()

	def on_connection_close(self):
		self.channel.close()
class SitDownBoardHandler(tornado.web.RequestHandler):
    @tornado.web.asynchronous
    @authenticate
    def post(self):
        self.mongodb = self.application.settings['_db']
        user = self.user
        seat = self.get_argument('seat')
        stake = self.get_argument('stake')

        if False and 'is_sit_down' in self.session and \
         self.session['is_sit_down'] == True and \
         self.session['seat'] == seat:
            self.write(json.dumps({'status': 'success'}))
            self.finish()
        else:
            messages = self.mongodb.board.find_one(
                {"id": self.session.session_id})
            room = Room.find(_id=messages["room_id"])
            if room is None:
                self.finish(json.dumps({'status': 'failed'}))
                return

            queue_name = str(user.username) + '_sit'
            exchange_name = self.session['exchange']

            user.room_id = room.id
            #exchange_name	= str(user.room.exchange)
            #source_key		= "%s_%s" % (exchange_name, queue_name)

            message = {
                'method': 'sit',
                'user_id': user.id,
                'seat': seat,
                #'source':source_key,
                'room_id': str(user.room_id),
                'private_key': self.session['private_key'],
                'stake': stake
            }

            arguments = {'routing_key': 'dealer', 'message': message}
            self.channel = Channel(self.application.channel, exchange_name)
            self.channel.add_ready_action(self.sit_call_back, arguments)
            self.channel.connect()

    def sit_call_back(self, argument):
        if self.request.connection.stream.closed():
            self.channel.close()
            return

        self.channel.add_message_action(self.message_call_back, None)
        argument['message']['source'] = self.channel.routing_key
        self.channel.publish_message(argument['routing_key'],
                                     json.dumps(argument['message']))

    def message_call_back(self, argument):
        messages = self.channel.get_messages()[0]
        if self.request.connection.stream.closed():
            self.channel.close()
            return
        if messages['status'] == 'success':
            self.mongodb.board.update({"id":self.session.session_id},\
              {"$set" :{'is_sit_down':True}})

        self.write(json.dumps(messages))
        self.channel.close()
        self.finish()

    def on_connection_close(self):
        self.channel.close()
class EnterRoomHandler(tornado.web.RequestHandler):
    @tornado.web.asynchronous
    @authenticate
    def post(self):
        message = None
        user = self.user
        room_id = self.get_argument('room_id')
        room = Room.find(_id=room_id)
        if not room:
            print Room.find_all()
            print "not a valid room", room_id
            self.finish()
            return

        self.mongodb = self.application.settings['_db']
        msg = {"id": self.session.session_id, "room_id": room.id}

        BoardMessage.get_collection().remove({
            "id": self.session.session_id,
        },
                                             safe=True)

        # guarantee only one exist
        self.mongodb.board.update({"id": self.session.session_id},
                                  msg,
                                  upsert=True)

        exchange = str(room.exchange)

        self.session['exchange'] = exchange

        public_key = ('broadcast_%s_%s.testing') % (exchange, room._id)
        private_key = ('direct.%s.%s.%s') % (exchange, room._id, user._id)
        binding_keys = [public_key, private_key]
        if user.isBot:
            bot_key = ('direct.%s.%s.bot') % (exchange, room._id)
            binding_keys.append(bot_key)
            self.session['bot_key'] = bot_key

        message = {
            'method': 'enter',
            'user_id': user.id,
            'room_id': room.id,
            'private_key': private_key
        }

        arguments = {'routing_key': 'dealer', 'message': message}
        self.broadcast_channel = broadcast_channel = PersistentChannel(
            self.application.channel,
            "%s%s" % (str(self.session.session_id), room.id[-10:]),
            exchange,
            binding_keys,
            declare_queue_only=True,
            arguments={"x-expires": int(600000)})

        self.callBackCount = 0
        broadcast_channel.add_ready_action(self.initial_call_back, arguments)
        broadcast_channel.connect()

        self.channel = Channel(self.application.channel, exchange)

        self.channel.add_ready_action(self.initial_call_back, arguments)
        self.channel.connect()
        self.session['public_key'] = public_key
        self.session['private_key'] = private_key
        #self.session['messages']	= list()
        print "ENTER!"

    def purge_call_back(self, data):
        argument = self.argument
        self.channel.add_message_action(self.message_call_back, None)
        self.mongodb.board.update(
            {"id": self.session.session_id},
            {"$set": {
                'queue': self.broadcast_channel.queue_name
            }})
        argument['message']['source'] = self.channel.routing_key
        self.channel.publish_message(argument['routing_key'],
                                     json.dumps(argument['message']))

    def initial_call_back(self, argument):
        print "ENTER CALL BACK", argument
        self.callBackCount += 1
        if self.callBackCount < 2:
            #We have to wait broadcast_channel created
            return

        if self.request.connection.stream.closed():
            self.channel.close()
            return
        self.argument = argument
        self.application.channel.queue_purge(
            callback=self.purge_call_back,
            queue=self.broadcast_channel.queue_name)

    def message_call_back(self, argument):
        messages = self.channel.get_messages()[0]
        if self.request.connection.stream.closed():
            self.channel.close()
            return
        self.write(json.dumps(messages))
        self.channel.close()
        self.finish()

    def on_connection_close(self):
        self.channel.close()