import urllib.request
from bs4 import BeautifulSoup
from time import sleep, time
import pickle
import queue
import threading
import math

HYPER_EXPANSION_LIMIT = 2
# How many levels of links is it allowed to follow
HYPER_DEFAULT_LINK = "https://en.wikipedia.org/wiki/Vitamin_A"
HYPER_DEFAULT_SEARCH = "Vitamin A"
HYPER_DEFAULT_THREAD_TIMEOUT = 100

alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz-_=+{}[]'\\./,<>?:\";'1234567890 "

status = ""

parsedLinks = []
parsedLinksCount = 0

q = queue.Queue
threads = []
threads2 = []
times = []

currentThreadsActive = 0


def getGeneratorLen(gen):
    count = 0
    for i in gen:
        count += 1
    return count


def find_all(a_str, sub):
    start = 0
    while True:
        start = a_str.find(sub, start)
        if start == -1: return
        yield start
        start += len(sub)  # use start += 1 to find overlapping matches


def getNextStringIndexFromIndex(string, searchstring, index):
    for i in range(index, len(string)):
        # print("[DEBUG] Iterating " + str(i) + "/" + str(len(string)))
        if str(string[i]) == str(searchstring):
            return i
    return -1


def getMainInformation(text, searchString):
    final = ""
    if searchString not in text:
        return 0
    else:
        for string in searchString.split(" "):
            position = 1
            indexies = find_all(text, string)
            for index in indexies:
                # print("[DEBUG : MAIN INFO] Interating through index " + str(position) + "/" + str(getGeneratorLen(indexies)))
                sentanceEnd = getNextStringIndexFromIndex(text, ".", index)
                final += text[index:sentanceEnd]
                final += "\n"
                position += 1
    return final


def summarise(link, word):
    word = str(word.upper())
    print("Parsing " + link)
    try:
        with urllib.request.urlopen(link) as source:  # Parse Wikipedia Page
            http = source.read()
        soup = BeautifulSoup(http, 'html.parser')
    except ValueError:
        # print(link + " is not a valid link!")
        return -1

    # Inform user
    # print("Parsed " + soup.title.string)
    # print("Getting paragraph text...")
    paragraph = soup.p.getText().upper()
    # print("Retrived text")
    # print("Retriving important information...")
    if word not in paragraph:
        # print("Error, search string " + word + " has no occurance, trying non-plural form")
        if word not in paragraph:
            # print("Non-Plural valid")
            final = getMainInformation(paragraph, word[:-1])
            return final
        else:
            # print("Plural invalid")
            final = 0
    else:
        final = getMainInformation(paragraph, word)
    if (final != 0):
        return final


def getWebsiteExists(link):
    try:
        urllib.request.urlopen(link)
    except:
        # print(link + " is not a valid link!")
        return -1
    return 0


parsedInformation = {}


def getLinkInfo(aElement, betweenTag, word):
    global currentThreadsActive
    global status
    startTime = time()
    if aElement.string != "None":
        try:
            if len(betweenTag.split(" ")) > 1 or word == betweenTag:
                return
            else:
                parseLink = aElement.get("href")
                if str(parseLink) == "None":
                    # print("Passing due to missing href")
                    return
                if parseLink[0:6] == "/wiki/":
                    parseLink = "https://en.wikipedia.org" + parseLink
                    # print("Link not formatted correctly, correcting to " + parseLink)
                if (
                                    "File:" in parseLink or "Main_Page" in parseLink or parseLink == "https://wikimediafoundation.org/"):
                    # print("Continuing due to file or main page")
                    return
                if any(parseLink in str(s) for s in parsedLinks):
                    # print("Passing due to already parsed " + betweenTag)
                    return
                parsedLinks.append(parseLink)
                if getWebsiteExists(parseLink) == -1:
                    return
                else:
                    parsedInformation[betweenTag.upper()] = summarise(parseLink, betweenTag)
                    endtime = time()
                    timeSpent = math.floor((endtime - startTime) * currentThreadsActive - 1)
                    times.append(timeSpent)
                    if len(times) > 10:
                        del times[0]
                    totalTimeSpent = 0
                    for t in times:
                        totalTimeSpent += t
                    averageTimeSpent = math.floor(totalTimeSpent / len(times))
                    status = str(math.floor(averageTimeSpent / 60)) + "m Remaining"
                    currentThreadsActive -= 1
                    del threads[threads.find(threading.current_thread())]
        except AttributeError:
            return
    else:
        return


def readLinks(link, word):
    global threads
    global currentThreadsActive
    print("Parsing links to level " + str(HYPER_EXPANSION_LIMIT) + "...")
    checkedLinks = 0

    with urllib.request.urlopen(link) as source:  # Parse Wikipedia Page
        HTTP = source.read()
    SOUP = BeautifulSoup(HTTP, 'html.parser')
    threadtimes = []
    linkCount = len(SOUP.find_all("a"))

    for aElement in SOUP.find_all("a"):
        print("\n")
        print("Creating thread " + str(checkedLinks) + "/" + str(linkCount))
        betweenTag = aElement.getText()
        checkedLinks += 1
        threads.append(threading.Thread(target=getLinkInfo, args=(aElement, betweenTag, word)))
        currentThreadsActive += 1
    print("Starting Threads")
    for thread in threads:
        thread.start()
        threadtimes.append(math.floor(time()))
    print("Waiting for thread completion")
    sleep(1)
    for i in range(0, len(threads) - 1):
        threads[i].join()