import lxml.etree       # Used by imageFunc
import datetime         # Used by helloFunc
import json             # Used by spellFunc
import random           # Used by imageFunc
import urllib           # Used by imageFunc
import time             # Used for logging
import logging          # Used for... you know... logging
import wikia            # Used by findWikiPage
import os               # Used by makeFiles

logging.basicConfig(filename="gwendolyn.log", level=logging.INFO)

# Capitalizes all words except some of them
no_caps_list = ["of","the"]
def cap(s):
    word_number = 0
    lst = s.split()
    res = ''
    for word in lst:
        word_number += 1
        if word not in no_caps_list or word_number == 1:
            word = word.capitalize()
        res += word+" "
    res = res[:-1]
    return res

def time_in_range(start, end, x):
    """Return true if x is in the range [start, end]"""
    if start <= end:
        return start <= x <= end
    else:
        return start <= x or x <= end

# Responds with a greeting of a time-aprpriate maner
def helloFunc(author):
    now = datetime.datetime.now()
    if time_in_range(now.replace(hour=5, minute=0, second=0, microsecond=0),now.replace(hour=10, minute=0, second=0, microsecond=0), now):
        return("Good morning, "+str(author))
    elif time_in_range(now.replace(hour=10, minute=0, second=0, microsecond=0),now.replace(hour=13, minute=0, second=0, microsecond=0), now):
        return("Good day, "+str(author))
    elif time_in_range(now.replace(hour=13, minute=0, second=0, microsecond=0),now.replace(hour=18, minute=0, second=0, microsecond=0), now):
        return("Good afternoon, "+str(author))
    elif time_in_range(now.replace(hour=18, minute=0, second=0, microsecond=0),now.replace(hour=22, minute=0, second=0, microsecond=0), now):
        return("Good evening, "+str(author))
    elif time_in_range(now.replace(hour=22, minute=0, second=0, microsecond=0),now.replace(hour=23, minute=59, second=59, microsecond=0), now):
        return("Good night, "+str(author))
    else:
        return("Why hello, "+str(author))

# Finds a random picture online
def imageFunc():
    # Picks a type of camera, which decides the naming scheme
    try:
        cams = ("one","two","three","four")
        cam = random.choice(cams)
        logThis("Chose cam type "+cam)
        if cam == "one":
            a = str(random.randint(0 ,9))
            b = str(random.randint(0,9))
            c = str(random.randint(0,9))
            d = str(random.randint(0,9))
            search = ("img_"+a+b+c+d)
        elif cam == "two":
            a = str(random.randint(2012,2016))
            b = str(random.randint(1,12)).zfill(2)
            c = str(random.randint(1,29)).zfill(2)
            search = ("IMG_"+a+b+c)
        elif cam == "three":
            a = str(random.randint(1,500)).zfill(4)
            search = ("IMAG_"+a)
        elif cam == "four":
            a = str(random.randint(0,9))
            b = str(random.randint(0,9))
            c = str(random.randint(0,9))
            d = str(random.randint(0,9))
            search = ("DSC_"+a+b+c+d)
    except:
        logThis("error picking camera type (error code 702)")

    logThis("Searching for "+search)

    # Searches for the image and reads the resulting web page
    try:
        page = urllib.request.urlopen("https://www.bing.com/images/search?q="+search+"&safesearch=off")
        read = page.read()
        tree = lxml.etree.HTML(read)
        images = tree.xpath('//a[@class = "thumb"]/@href')

        # Picks an image
        number = random.randint(1,len(images))-1
        image = images[number]

        logThis("Picked image number "+str(number))

        # Returns the image
        logThis("Successfully returned an image")
    except:
        image = "Couldn't connect to bing (error code 701)"
        logThis("Couldn't connect to bing (error code 701)")
    return(image)

def logThis(message : str, channel = ""):
    localtime = time.asctime(time.localtime(time.time()))
    channel = channel.replace("Direct Message with ","")
    if channel == "":
        print(localtime+" - "+message)
        logging.info(localtime+" - "+message)
    else:
        print(localtime+" ("+channel+") - "+message)
        logging.info(localtime+" ("+channel+") - "+message)

# Finds a page from the Senkulpa Wikia
def findWikiPage(search : str):
    logThis("Trying to find wiki page for "+search)
    wikia.set_lang("da")
    searchResults = wikia.search("senkulpa",search)
    if len(searchResults) > 0:
        try:
            searchResult = searchResults[0].replace(",","%2C")
            logThis("Found page \""+searchResult+"\"")
            page = wikia.page("senkulpa",searchResult)
            content = page.content.replace(u'\xa0', u' ').split("\n")[0]

            images = page.images
            if len(images) > 0:
                image = images[len(images)-1]+"/revision/latest?path-prefix=da"
                return page.title, content, image
            else:
                return page.title, content, ""
        except:
            logThis("Fucked up (error code 1001)")
            return "", "Sorry. Fucked that one up (error code 1001)", ""
    else:
        logThis("Couldn't find the page (error code 1002)")
        return "", "Couldn't find page (error code 1002)", ""

def makeFiles():
    # Creates swcharacters.json if it doesn't exist
    try:
        f = open("resources/starWars/swcharacters.json","r")
    except:
        logThis("swcharacters.json didn't exist. Making it now.")
        emptyDict = {}
        with open("resources/starWars/swcharacters.json","w") as f:
            json.dump(emptyDict,f,indent = 4)
    finally:
        f.close()

    # Creates games.json if it doesn't exist
    try:
        f = open("resources/games/games.json","r")
    except:
        logThis("games.json didn't exist. Making it now.")
        data = {"trivia questions":{},"blackjack games":{},"4 in a row games": {},"users":{}}
        with open("resources/games/games.json","w") as f:
            json.dump(data,f,indent = 4)
    finally:
        f.close()
    
    # Creates hexGames.json if it doesn't exist
    try:
        f = open("resources/games/hexGames.json","r")
    except:
        logThis("hexGames.json didn't exist. Making it now.")
        data = {}
        with open("resources/games/hexGames.json","w") as f:
            json.dump(data,f,indent = 4)
    finally:
        f.close()

    # Creates monsters.json if it doesn't exist
    try:
        f = open("resources/lookup/monsters.json","r")
    except:
        logThis("monsters.json didn't exist. Making it now.")
        with open("resources/lookup/lookupExamples.json") as f:
            data = json.load(f)["monster"]
        with open("resources/lookup/monsters.json","w") as f:
            json.dump(data,f,indent = 4)
    finally:
        f.close()

    # Creates spells.json if it doesn't exist
    try:
        f = open("resources/lookup/spells.json","r")
    except:
        logThis("spells.json didn't exist. Making it now.")
        with open("resources/lookup/lookupExamples.json") as f:
            data = json.load(f)["spell"]
        with open("resources/lookup/spells.json","w") as f:
            json.dump(data,f,indent = 4)
    finally:
        f.close()
    
    # Creates users.json if it doesn't exist
    try:
        f = open("resources/users.json","r")
    except:
        logThis("users.json didn't exist. Making it now.")
        data = {}
        with open("resources/users.json","w") as f:
            json.dump(data,f,indent = 4)
    finally:
        f.close()

    # Creates destinyPoints.txt if it doesn't exist
    try:
        f = open("resources/starWars/destinyPoints.txt","r")
    except:
        logThis("destinyPoints.txt didn't exist. Making it now.")
        with open("resources/starWars/destinyPoints.txt","w") as f:
            f.write("")
    finally:
        f.close()
    
    # Creates movies.txt if it doesn't exist
    try:
        f = open("resources/movies.txt","r")
    except:
        logThis("movies.txt didn't exist. Making it now.")
        with open("resources/movies.txt","w") as f:
            f.write("The Room")
    finally:
        f.close()

    # Creates names.txt if it doesn't exist
    try:
        f = open("resources/names.txt","r")
    except:
        logThis("names.txt didn't exist. Making it now.")
        with open("resources/names.txt","w") as f:
            f.write("Gandalf")
    finally:
        f.close()
        
    # Creates token.txt if it doesn't exist
    try:
        f = open("token.txt","r")
    except:
        logThis("token.txt didn't exist. Write your bot token below, or in token.txt later.")
        token = input()
        with open("token.txt","w") as f:
            f.write(token)
            
    finally:
        f.close()

    # Creates the blackjacktables foulder if it doesn't exist
    if os.path.isdir("resources/games/blackjackTables") == False:
        os.makedirs("resources/games/blackjackTables")
        logThis("The tables directory didn't exist")
    
    # Creates the 4InARowBoards foulder if it doesn't exist
    if os.path.isdir("resources/games/4InARowBoards") == False:
        os.makedirs("resources/games/4InARowBoards")
        logThis("The 4 in a row boards directory didn't exist")
    
    # Creates the hexBoards foulder if it doesn't exist
    if os.path.isdir("resources/games/hexBoards") == False:
        os.makedirs("resources/games/hexBoards")
        logThis("The Hex boards directory didn't exist")
    
    # Creates the oldImages foulder if it doesn't exist
    if os.path.isdir("resources/games/oldImages") == False:
        os.makedirs("resources/games/oldImages")
        logThis("The old images directory didn't exist")

    # Creates the blackjackCards foulder if it doesn't exist
    if os.path.isdir("resources/games/blackjackCards") == False:
        os.makedirs("resources/games/blackjackCards")
        logThis("The blackjack cards directory didn't exist")

    # Creates the hilo foulder if it doesn't exist
    if os.path.isdir("resources/games/hilo") == False:
        os.makedirs("resources/games/hilo")
        logThis("The hi-lo directory didn't exist")

# Replaces multiple things with the same thing
def replaceMultiple(mainString, toBeReplaces, newString):
    # Iterate over the strings to be replaced
    for elem in toBeReplaces :
        # Check if string is in the main string
        if elem in mainString :
            # Replace the string
            mainString = mainString.replace(elem, newString)
    
    return  mainString

def emojiToNumber(emoji):
    if emoji == "1️⃣":
        return 1
    elif emoji == "2️⃣":
        return 2
    elif emoji == "3️⃣":
        return 3
    elif emoji == "4️⃣":
        return 4
    elif emoji == "5️⃣":
        return 5
    elif emoji == "6️⃣":
        return 6
    elif emoji == "7️⃣":
        return 7
    else: return ""

def fiarReactionTest(channel,message,user):
    with open("resources/games/games.json", "r") as f:
        data = json.load(f)

    with open("resources/games/oldImages/fourInARow"+str(channel), "r") as f:
        oldImage = int(f.read())

    if message.id == oldImage:
        logThis("They reacted to the fourinarow game")
        turn = data["4 in a row games"][str(channel)]["turn"]
        print(user)
        print(data["4 in a row games"][str(channel)]["players"][turn])
        if user == data["4 in a row games"][str(channel)]["players"][turn]:
            return True, turn+1
        else:
            logThis("It wasn't their turn")
            return False, 0
    else:
        return False, 0

def stopServer():
    with open("resources/games/games.json","r") as f:
        data = json.load(f)
    
    data["trivia questions"] = {}
    data["blackjack games"] = {}
    data["4 in a row games"] = {}
    
    with open("resources/games/games.json","w") as f:
        json.dump(data,f,indent=4)

def deleteGame(gameType,channel):
    with open("resources/games/games.json", "r") as f:
        data = json.load(f)
    
    del data[gameType][channel]
    with open("resources/games/games.json", "w") as f:
        json.dump(data,f,indent=4)

def addToDict(userID,userName):
    with open("resources/users.json", "r") as f:
        data = json.load(f)
    
    if userID in data:
        if data[userID]["user name"] != userName:
            logThis("changing name for "+userName)
            data[userID]["user name"] = userName
            with open("resources/users.json", "w") as f:
                json.dump(data,f,indent=4)
    else:
        logThis("creating "+userName+" in the system")

        with open("resources/games/games.json","r") as f:
            games = json.load(f)
        
        if userName.lower() in games["users"]:
            money = games["users"][userName.lower()]
            del games["users"][userName.lower()]
            with open("resources/games/games.json", "w") as f:
                json.dump(games,f,indent=4)
        else:
            money = 0

        data[userID] = {"user name" : userName, "money" : money}
        with open("resources/users.json", "w") as f:
            json.dump(data,f,indent=4)

def getName(userID):
    try:
        with open("resources/users.json", "r") as f:
            data = json.load(f)
        
        if userID in data:
            return data[userID]["user name"]
        else:
            logThis("Couldn't find user")
            return userID
    except:
        logThis("Error getting name")

def getID(userName):
    try:
        with open("resources/users.json", "r") as f:
            data = json.load(f)
        
        userID = None

        for key, value in data.items():
            if userName.lower() == value["user name"].lower():
                userID = key
                break
        
        return userID
    except:
        logThis("Error getting ID")