!#/usr/bin/python

from twisted.internet import reactor, protocol
import random
from conf import *


# a client protocol

class UnoBot(protocol.Protocol):


   def connectionMade(self):
       print "Connected"
       self.rawsend("NICK %s \n" % (nick))
       self.rawsend("USER %s * * :%s\n" % (ident, realname))
       self.logf = open("raw.txt", "a")
       self.game = {}
       self.game["going"] = False
       self.game["playing"] = False
       self.game["starter"] = ""

   def on_GAME_STOP(self, info) :
       self.game = {}
       self.game["going"] = False
       self.game["playing"] = False
       self.game["starter"] = ""
       self.ircsend(channel, "The game has ended")

   def dataReceived(self, data):
       print data
       self.logf.write(data)
       error = 0
       lines = data.replace("\r", "").split("\n")
       if data.split(" ")[0] == "PING" : self.rawsend("PONG %s\n" % (data.split(" ")[1]))
       for line in lines :
           if line != "" :
               try :
                   info = {}
                   info["raw"] = line
                   info["words"] = line[1:].split(" ")
                   if info["words"][1] == "001" :
                       if bpass != ""    :
                           self.ircsend("NickServ", "IDENTIFY %s %s" % (nick, bpass))
                       self.rawsend("JOIN %s \n" % (channel))
                   info["whois"] = info["words"][0]
                   info["sender"] = info["whois"].split("!")[0]
               except : print "Ok"
               try : info["hostname"] = info["whois"].split("@")[1]
               except : info["hostname"] = "Unknown"
               try : info["mode"] = info["words"][1]
               except : info["mode"] = "Unknown"
               try :
                   if info["words"][2] == nick :
                       info["channel"] = info["sender"]
                   else : info["channel"] = info["words"][2].replace(":", "")
               except : info["channel"] = "Unknown"
               try :
                   if info["mode"] == "PRIVMSG" or info["mode"] == "TOPIC" :
                       if ":" in info["words"][3] : info["message"] = " ".join(info["words"][3:])[1:]
                       else : info["message"] = " ".join(info["words"][3:])
                   else : info["message"] = "Unknown"
               except : error = 1
               #if error != 1 : self.prettify(info)
               self.command_parser(info)

   def on_GAME_START(self, info) :
       if not self.game["going"] :
           self.shuffle_deck()
           self.ircsend(info["channel"], "Who is going to play?  Up to four players may join.")
           self.game["players"] = {}
           self.game["order"] = []
           self.game["going"] = True
           self.game["starter"] = info["sender"]
       else : self.ircsend(info["channel"], "%s: We are already playing a game!" % (info["sender"]))

   def on_PLAYER_JOIN(self, info) :
       if len(self.game["order"]) <= 3 and self.game["going"] and not self.game["playing"] and info["sender"] not in self.game["order"]:
           self.game["order"].append(info["sender"])
           self.game["players"][info["sender"]] = {}
           self.game["players"][info["sender"]]["cards"] = []
           self.ircsend(channel, "%s has just joined the game!" % (info["sender"]))
       elif not self.game["going"] :
           self.ircsend(info["channel"], "We are not playing yet!")
       elif len(self.game["order"]) == 4 :
           self.ircsend(info["channel"], "Sorry, but there are already 4 players")
       elif self.game["playing"] :
           self.ircsend(info["channel"], "We are already playing a game!")
       elif info["sender"] in self.game["order"] :
           self.ircsend(info["channel"], "%s: You have already joined!" % (info["sender"]))
   def shuffle_deck(self) :
       self.game["deck"] = []
       for color in ["r", "y", "b", "g"] :
           for action in ["skip", "+2", "rev"] :
               self.game["deck"].append("%s_%s" % (color, action))
           for num in range(1, 10) :
               self.game["deck"].append("%s_%s" % (color, num))
       self.game["deck"] = self.game["deck"] + self.game["deck"]
       for card in range(4) :
           self.game["deck"].append("w_*")
           self.game["deck"].append("w_+4")
       for color in ["r", "y", "b", "g"] :
           self.game["deck"].append("%s_0" % (color))
       random.shuffle(self.game["deck"])

   def connectionLost(self, reason):
       print "connection lost"
       self.logf.close()

   def on_GO(self, info) :
       if self.game["going"] :
           for player in self.game["order"] :
               self.game["players"][player]["r"] = []
               self.game["players"][player]["g"] = []
               self.game["players"][player]["b"] = []
               self.game["players"][player]["y"] = []
               self.game["players"][player]["w"] = []
               for count in range(10) :
                   self.game["players"][player][str(count)] = []
               self.game["players"][player]["skip"] = []
               self.game["players"][player]["+2"] = []
               self.game["players"][player]["rev"] = []
               self.game["players"][player]["*"] = []
               self.game["players"][player]["+4"] = []
               for card in range(7) :
                   self.game["players"][player]["cards"].append(self.game["deck"][0])
                   self.game["players"][player][self.game["deck"][0][0]].append(self.game["deck"][0].split("_")[1])
                   self.game["players"][player][self.game["deck"][0].split("_")[1]].append(self.game["deck"][0][0])
                   self.game["deck"].pop(0)
               msg = ""
               for card in self.game["players"][player]["cards"] :
                   msg = msg + "[%s] " % (card)
               self.ircsend(player, "Your hand: %s" % (msg))
           self.ircsend(channel, "Let the game begin!  %s goes first.  Also, the current card is [%s]" % (self.game["order"][0], self.game["deck"][0]))
           self.game["nextup"] = 1
           self.game["up"] = 0
           self.game["currentcard"] = self.game["deck"][0]
           self.game["deck"].pop(0)
           self.game["reversed"] = False
           if self.game["currentcard"][0] == "w" :
               self.game["chooser"] = self.game["order"][0]
               self.ircsend(channel, "%s needs to choose a color with the choose command" % (self.game["chooser"]))
           else : self.game["chooser"] = ""
           self.game["safe"] = []
       else : self.ircsend(channel, "We are not playing a game right now!")
       self.game["playing"] = True
   def on_TURN_DONE(self, info) :
       if self.game["reversed"] :
           if self.game["up"] == 0 :
               self.game["up"] = len(self.game["order"]) - 1
               self.game["nextup"] = len(self.game["order"]) - 2
           else :
               self.game["up"] -= 1
               if self.game["nextup"] == 0 :
                   self.game["nextup"] == len(self.game["order"]) - 1
               else :
                   self.game["nextup"] -= 1
       else :
           if self.game["up"] == len(self.game["order"]) - 1 :
               self.game["up"] = 0
               self.game["nextup"] = 1
           else :
               self.game["up"] += 1
               if self.game["nextup"] == len(self.game["order"]) - 1 :
                   self.game["nextup"] = 0
               else :
                   self.game["nextup"] += 1
       msg = ""
       for card in self.game["players"][info["sender"]]["cards"] :
           msg = msg + "[%s] " % (card)
       self.ircsend(info["sender"], "Your hand: %s" % (msg))


       self.ircsend(channel, "%s now has %s card(s) left in his/her hand" % (info["sender"], len(self.game["players"][info["sender"]]["cards"])))
       self.ircsend(channel, "It is now %s's turn" % (self.game["order"][self.game["up"]]))
       self.ircsend(channel, "The current card is now [%s]" % (self.game["currentcard"]))
   def eval_card(self, info) :
       if self.game["currentcard"].split("_")[1] not in ["0", "1", "2", "3", "4", "5", "6", "7", "8", "9"] :
           if self.game["currentcard"].split("_")[1] == "rev" :
               if not self.game["reversed"] :
                   self.game["reversed"] = True
               else :
                   self.game["reversed"] = False
               self.ircsend(channel, "The turn order has been reversed!")
               self.on_TURN_DONE(info)
           elif self.game["currentcard"].split("_")[1] == "skip" :
               self.on_SKIP(info)
               self.on_TURN_DONE(info)
           elif self.game["currentcard"].split("_")[1] == "+2" :
               for card in range(2) :
                   self.game["players"][self.game["order"][self.game["nextup"]]]["cards"].append(self.game["deck"][0])
                   self.game["players"][self.game["order"][self.game["nextup"]]][self.game["deck"][0][0]].append(self.game["deck"][0].split("_")[1])
                   self.game["players"][self.game["order"][self.game["nextup"]]][self.game["deck"][0].split("_")[1]].append(self.game["deck"][0][0])
                   self.game["deck"].pop(0)
               msg = ""
               for card in self.game["players"][self.game["order"][self.game["nextup"]]]["cards"] :
                   msg = msg + "[%s] " % (card)
               self.ircsend(self.game["order"][self.game["nextup"]], "Your hand: %s" % (msg))
               self.ircsend(channel, "%s has %s card(s) left in his/her hand" % (self.game["order"][self.game["nextup"]], len(self.game["players"][self.game["order"][self.game["nextup"]]]["cards"])))
               self.on_TURN_DONE(info)
           elif self.game["currentcard"] == "w_*" :
               self.game["chooser"] = info["sender"]
               self.ircsend(channel, "%s needs to choose a color with the choose command" % (self.game["order"][self.game["up"]]))
           elif self.game["currentcard"] == "w_+4" :
               self.game["chooser"] = info["sender"]
               for card in range(4) :
                   self.game["players"][self.game["order"][self.game["nextup"]]]["cards"].append(self.game["deck"][0])
                   self.game["players"][self.game["order"][self.game["nextup"]]][self.game["deck"][0][0]].append(self.game["deck"][0].split("_")[1])
                   self.game["players"][self.game["order"][self.game["nextup"]]][self.game["deck"][0].split("_")[1]].append(self.game["deck"][0][0])
                   self.game["deck"].pop(0)
               msg = ""
               for card in self.game["players"][self.game["order"][self.game["nextup"]]]["cards"] :
                   msg = msg + "[%s] " % (card)
               self.ircsend(self.game["order"][self.game["nextup"]], "Your hand: %s" % (msg))
               self.ircsend(channel, "%s now has %s card(s) left in his/her hand" % (self.game["order"][self.game["nextup"]], len(self.game["players"][self.game["order"][self.game["nextup"]]]["cards"])))
               self.ircsend(channel, "%s needs to choose a color with the choose command" % (self.game["order"][self.game["up"]]))
       else : self.on_TURN_DONE(info)
   def on_SKIP(self, info) :
       if self.game["reversed"] :
           if self.game["up"] == 0 :
               self.game["up"] = len(self.game["order"]) - 1
               self.game["nextup"] = len(self.game["order"]) - 2
           else :
               self.game["up"] -= 1
               if self.game["nextup"] == 0 :
                   self.game["nextup"] == len(self.game["order"]) - 1
               else :
                   self.game["nextup"] -= 1
       else :
           if self.game["up"] == len(self.game["order"]) - 1 :
               self.game["up"] = 0
               self.game["nextup"] = 1
           else :
               self.game["up"] += 1
               if self.game["nextup"] == len(self.game["order"]) - 1 :
                   self.game["nextup"] = 0
               else :
                   self.game["nextup"] += 1

   def on_PLAY(self, info, args) :
       if info["sender"] == self.game["order"][self.game["up"]] :
           if len(args) == 2 :
               if args[1] in self.game["players"][info["sender"]]["cards"] :
                   if args[1].split("_")[0] == self.game["currentcard"].split("_")[0] or args[1].split("_")[1] == self.game["currentcard"].split("_")[1] or args[1][0] == "w" :
                       if len(self.game["players"][info["sender"]]["cards"]) > 1 and info["sender"] in self.game["safe"] :
                           self.game["safe"].remove(info["sender"])
                       self.game["currentcard"] = args[1]
                       self.game["players"][info["sender"]]["cards"].remove(args[1])
                       self.game["players"][info["sender"]][args[1].split("_")[0]].remove(args[1].split("_")[1])
                       self.game["players"][info["sender"]][args[1].split("_")[1]].remove(args[1].split("_")[0])
                       self.eval_card(info)
                       if len(self.game["players"][info["sender"]]["cards"]) == 0 :
                           self.ircsend(channel, "%s wins the game!" % (info["sender"]))
                           self.on_GAME_STOP(info)
                   else : self.ircsend(channel, "%s: You cannot play that card right now!" % (info["sender"]))
               else : self.ircsend(channel, "%s: You do not have that card!" % (info["sender"]))
       else : self.ircsend(channel, "%s: It is not your turn!" % (info["sender"]))


   def on_CHOOSE(self, info, args) :
       if self.game["playing"] :
           if info["sender"] == self.game["chooser"] and args[1] in ["red", "yellow", "blue", "green"] :
               self.game["currentcard"] = "%s_*" % (args[1][0])
               self.game["chooser"] = ""
               self.ircsend(channel, "%s is now the current color" % (args[1]))
               self.on_TURN_DONE(info)
           else : self.ircsend(channel, "%s: You either did not play a wild card or that color is invalid" % (info["sender"]))
       else : self.ircsend(channel, "We are not playing a game right now!")
   def on_DRAW(self, info) :
       if self.game["playing"] :
           if self.game["players"][info["sender"]][self.game["currentcard"].split("_")[0]] == [] and self.game["players"][info["sender"]][self.game["currentcard"].split("_")[1]] == [] and "w_*" not in self.game["players"][info["sender"]]["cards"] and "w_+4" not in self.game["players"][info["sender"]]["cards"] :
               self.game["players"][info["sender"]]["cards"].append(self.game["deck"][0])
               self.game["players"][info["sender"]][self.game["deck"][0][0]].append(self.game["deck"][0].split("_")[1])
               self.game["players"][info["sender"]][self.game["deck"][0].split("_")[1]].append(self.game["deck"][0][0])
               self.game["deck"].pop(0)
               msg = ""
               for card in self.game["players"][info["sender"]]["cards"] :
                   msg = msg + "[%s] " % (card)
               self.on_TURN_DONE(info)
           else : self.ircsend(channel, "%s: You have a card that you can play!" % (info["sender"]))
       else : self.ircsend(channel, "We are not playing a game right now!")

   def on_UNO(self, info) :
       if self.game["playing"] :
           if len(self.game["players"][info["sender"]]["cards"]) == 1 :
               self.game["safe"].append(info["sender"])
               self.ircsend(channel, "Uno! Approved")
           else :
               self.ircsend(channel, "%s: You have more than one card.  Try counting next time!" % (info["sender"]))
               for card in range(2) :
                   self.game["players"][info["sender"]]["cards"].append(self.game["deck"][0])
                   self.game["players"][info["sender"]][self.game["deck"][0][0]].append(self.game["deck"][0].split("_")[1])
                   self.game["players"][info["sender"]][self.game["deck"][0].split("_")[1]].append(self.game["deck"][0][0])
                   self.game["deck"].pop(0)
               msg = ""
               for card in self.game["players"][info["sender"]]["cards"] :
                   msg += "[%s] " % (card)
               self.ircsend(info["sender"], "Your hand: %s" % (msg))
               self.ircsend(channel, "%s now has %s card(s) left in his/her hand" % (info["sender"], len(self.game["players"][info["sender"]]["cards"])))
       else : self.ircsend(channel, "We are not playing a game right now!")
   def on_CATCH(self, info, args) :
       if self.game["playing"] :
           if args[1] in self.game["order"] :
               if args[1] not in self.game["safe"] and len(self.game["players"][args[1]]["cards"]) == 1 :
                   for card in range(2) :
                       self.game["players"][args[1]]["cards"].append(self.game["deck"][0])
                       self.game["players"][args[1]][self.game["deck"][0][0]].append(self.game["deck"][0].split("_")[1])
                       self.game["players"][args[1]][self.game["deck"][0].split("_")[1]].append(self.game["deck"][0][0])
                       self.game["deck"].pop(0)
                   msg = ""
                   for card in self.game["players"][args[1]]["cards"] :
                       msg = msg + "[%s] " % (card)
                   self.ircsend(args[1], "Your hand: %s" % (msg))
                   self.ircsend(channel, "%s now has %s card(s) left in his/her hand" % (args[1], len(self.game["players"][args[1]]["cards"])))
               elif args[1] in self.game["safe"] :
                   self.ircsend(channel, "Wrong! That person already said Uno!")
                   for card in range(2) :
                       self.game["players"][info["sender"]]["cards"].append(self.game["deck"][0])
                       self.game["players"][info["sender"]][self.game["deck"][0][0]].append(self.game["deck"][0].split("_")[1])
                       self.game["players"][info["sender"]][self.game["deck"][0].split("_")[1]].append(self.game["deck"][0][0])
                       self.game["deck"].pop(0)
                   msg = ""
                   for card in self.game["players"][info["sender"]]["cards"] :
                       msg = msg + "[%s] " % (card)
                   self.ircsend(info["sender"], "Your hand: %s" % (msg))
                   self.ircsend(channel, "%s now has %s card(s) left in his/her hand" % (info["sender"], len(self.game["players"][info["sender"]]["cards"])))
               elif len(self.game["players"][args[1]]["cards"]) != 1 :
                   self.ircsend(channel, "Wrong! That player does not have only one card in his/her hand!")
                   for card in range(2) :
                       self.game["players"][info["sender"]]["cards"].append(self.game["deck"][0])
                       self.game["players"][info["sender"]][self.game["deck"][0][0]].append(self.game["deck"][0].split("_")[1])
                       self.game["players"][info["sender"]][self.game["deck"][0].split("_")[1]].append(self.game["deck"][0][0])
                       self.game["deck"].pop(0)
                   msg = ""
                   for card in self.game["players"][info["sender"]]["cards"] :
                       msg = msg + "[%s] " % (card)
                   self.ircsend(info["sender"], "Your hand: %s" % (msg))
                   self.ircsend(channel, "%s now has %s card(s) left in his/her hand" % (info["sender"], len(self.game["players"][info["sender"]]["cards"])))
           else : self.ircsend(info["channel"], "No such player!")
       else : self.ircsend(channel, "We are not playing a game right now!")
   def command_parser(self, info) :
       args = info["message"][1:].split(" ")
       if info["message"][0] == prefix and info["sender"] in admin :
           args = info["message"][1:].split(" ")
           if args[0] == "join" :
               self.rawsend("JOIN %s \n" % (args[1]))

           if args[0] == "part" :
               self.rawsend("PART %s \n" % (args[1]))

           if args[0] == "quit" :
               self.transport.loseConnection()
           if args[0] == "eval" :
               try : self.ircsend(info["channel"], str(eval(args[1])))
               except : print "Error"
       if info["message"][0] == prefix :
           if args[0] == "start":
               self.on_GAME_START(info)
           elif args[0] == "me" :
               self.on_PLAYER_JOIN(info)
           elif args[0] == "go" and info["sender"] == self.game["starter"] and self.game["going"] :
               self.on_GO(info)
           elif args[0] == "play" :
               self.on_PLAY(info, args)
           elif args[0] == "choose" :
               self.on_CHOOSE(info, args)
           elif args[0] == "draw" :
               self.on_DRAW(info)
           elif args[0] == "uno":
               self.on_UNO(info)
           elif args[0] == "stop" and self.game["starter"] == info["sender"] :
               self.on_GAME_STOP(info)
   def ircsend(self, targ_channel, msg_out) :
       self.rawsend("PRIVMSG %s :%s\n" % (targ_channel, msg_out))

   def rawsend(self, msg_out) :
       self.transport.write(msg_out)
       print ">>>%s" % (msg_out)


class UnoFactory(protocol.ClientFactory):
   protocol = UnoBot

   def clientConnectionFailed(self, connector, reason):
       print "Connection failed - goodbye!"
       reactor.stop()

   def clientConnectionLost(self, connector, reason):
       print "Connection lost - goodbye!"
       reactor.stop()



def main():
   f = UnoFactory()
   reactor.connectTCP(host, port, f)
   reactor.run()


if __name__ == '__main__':
   main()