#!/usr/bin/env python3

import datetime
from typing import List
from bs4 import BeautifulSoup
import tempfile
import sys
import os
import urllib.request
from datetime import date, timedelta

URL_SLADOVNICKA = "https://sladovnicka.unasplzenchutna.cz/cz/denni-nabidka"
URL_MOTLICI = "https://www.umotliku.cz"
URL_TECHTOWER = "https://www.equifarm.cz/restaurace-techtower"

DAY_NAMES = ['pondělí', 'úterý', 'středa',
             'čtvrtek', 'pátek', 'sobota', 'neděle']

# Fráze v názvech jídel, které naznačují že se jedná o polévku
SOUP_NAMES = ['polévka', 'česnečka', 'česnekový krém', 'cibulačka', 'vývar']


class bcolors:
    HEADER = '\033[95m'
    OKBLUE = '\033[94m'
    OKCYAN = '\033[96m'
    OKGREEN = '\033[92m'
    WARNING = '\033[93m'
    FAIL = '\033[91m'
    ENDC = '\033[0m'
    BOLD = '\033[1m'
    UNDERLINE = '\033[4m'


class Food:
    name = None
    amount = None
    price = None
    is_soup = False

    def __init__(self, name, amount, price, is_soup=False) -> None:
        self.name = name
        self.amount = amount
        self.price = price
        self.is_soup = is_soup


def getOrDownloadHtml(prefix: str, url: str):
    '''Vrátí HTML pro daný prefix pro aktuální den.
    Pokud v tempu neexistuje, provede jeho stažení z předané URL a uložení.'''
    filename = prefix + "_" + date.today().strftime("%Y_%m_%d") + ".html"
    filepath = os.path.join(tempfile.gettempdir(), filename)
    if not os.path.isfile(filepath):
        urllib.request.urlretrieve(url, filepath)
    file = open(filepath, "r")
    contents = file.read()
    file.close()
    return contents


def isNameOfDay(text: str):
    '''Vrátí True, pokud předaný text představuje název dne v týdnu (např. "pondělí")'''
    return text.strip().lower() in DAY_NAMES


def getDayNameOfDate(date: datetime.datetime):
    '''Vrátí název dne v týdnu - např. pondělí, úterý, ...'''
    return DAY_NAMES[date.weekday()]


def getStartOfWeekDate():
    '''Vrátí datetime představující pondělí v aktuálním týdnu.'''
    today = datetime.datetime.now()
    return today - timedelta(days=today.weekday())


def isTextSoupName(text: str):
    '''Vrátí True, pokud se předaný text jeví jako název polévky.
    Používá se tam, kde nemáme lepší způsob detekce (TechTower).'''
    for name in SOUP_NAMES:
        if name in text.lower():
            return True
    return False


def printMenu(name: str, foodList: List[Food]):
    '''Vytiskne jídelní lístek na obrazovku.'''
    print(f"{bcolors.OKGREEN}{name}{bcolors.ENDC}\n---------------------------------------------------------------------------------")
    maxLength = 0
    for jidlo in foodList:
        if len(jidlo.name) > maxLength:
            maxLength = len(jidlo.name)
    for jidlo in foodList:
        barva = bcolors.HEADER if jidlo.is_soup else bcolors.WARNING
        print(f"{barva}{jidlo.amount}\t{jidlo.name.ljust(maxLength)}\t{bcolors.ENDC}{bcolors.OKCYAN}{jidlo.price}{bcolors.ENDC}")
    print('\n')


def getMenuSladovnicka() -> List[Food]:
    html = getOrDownloadHtml('sladovnicka', URL_SLADOVNICKA)
    soup = BeautifulSoup(html, "html.parser")
    div = soup.select_one("div.tab-pane.fade.in.active")
    datumDen = div.find("h2").text
    split = datumDen.split(".")
    denMesic = split[0] + "." + split[1] + "."
    # nazevDen = split[2]
    dnesniDatum = date.today().strftime("%-d.%-m.")
    if denMesic != dnesniDatum:
        print('Chyba: neočekávané datum na stránce Sladovnické (' +
              denMesic + '), očekáváno ' + dnesniDatum, file=sys.stderr)
        sys.exit(1)
    tables = div.find_all("table", {"class": "simple"})
    if len(tables) != 2:
        print('Chyba: neočekávaný počet tabulek na stránce Sladovnické (' +
              str(len(tables)) + '), očekávány 2', file=sys.stderr)
        sys.exit(1)

    foodList: List[Food] = []

    polevkaValues = tables[0].find_all("td")
    amount = polevkaValues[0].text.strip()
    name = polevkaValues[1].text.strip()
    price = polevkaValues[2].text.strip()
    foodList.append(Food(name, amount, price, True))

    foodTables = tables[1].find_all("tr")
    for food in foodTables:
        rows = food.find_all("td")
        if (len(rows) != 3):
            print("Neočekávaný počet řádek hlavního jídla Sladovnické (" +
                  str(len(rows)) + ", očekávány 3, přeskakuji...")
            continue
        amount = rows[0].text.strip()
        name = rows[1].text.strip()
        price = rows[2].text.strip()
        foodList.append(Food(name, amount, price))
    return foodList


def getMenuUMotliku() -> List[Food]:
    html = getOrDownloadHtml('u_motliku', URL_MOTLICI)
    soup = BeautifulSoup(html, "html.parser")
    table = soup.find("table", {"class": "Xtable-striped"})
    rows = table.find_all("tr")
    if len(rows) < 4:
        print('Chyba: neočekávaný celkový počet řádek tabulky (' +
              str(len(rows)) + '), očekáváno 4 a více', file=sys.stderr)
        sys.exit(1)

    foodList: List[Food] = []

    if rows[0].td.text.strip() == 'Polévka':
        tds = rows[1].find_all("td")
        if len(tds) != 3:
            print('Chyba: neočekávaný počet <td> elementů v řádce polévky (' +
                  str(len(tds)) + '), očekáváno 3', file=sys.stderr)
            sys.exit(1)
        amount = tds[0].text.strip()
        name = tds[1].text.strip()
        price = tds[2].text.strip().replace(',-', '')
        foodList.append(Food(name, amount, price, True))
        rows = rows[2:]

    if rows[0].td.text.strip() == 'Hlavní jídlo':
        for i in range(1, len(rows)):
            tds = rows[i].find_all("td")
            if len(tds) != 3:
                print("Neočekávaný počet <td> elementů (" + str(len(tds)
                                                                ) + ") pro hlavní jídlo " + str(i) + ", přeskakuji")
                continue
            amount = tds[0].text.strip()
            name = tds[1].text.strip()
            price = tds[2].text.strip().replace(',-', '')
            foodList.append(Food(name, amount, price))
    return foodList


def getMenuTechTower() -> List[Food]:
    html = getOrDownloadHtml('techtower', URL_TECHTOWER)
    soup = BeautifulSoup(html, "html.parser")
    fonts = soup.find_all("font", {"class": ["wsw-41"]})
    font = None
    for f in fonts:
        if (f.text.strip().startswith("Obědy")):
            font = f
    if font is None:
        print('Chyba: nenalezen <font> pro obědy v HTML Techtower.', file=sys.stderr)
        sys.exit(1)
    siblings = font.parent.parent.find_next_siblings("p")
    # dayNumber = date.today().strftime("%w")
    currentDayName = getDayNameOfDate(datetime.datetime.now())
    foodList = []
    doParse = False
    for i in range(0, len(siblings)):
        text = siblings[i].text.strip().replace('\t', '').replace('\n', ' ')
        if isNameOfDay(text):
            if text == currentDayName:
                # Našli jsme dnešní den, odtud začínáme parsovat jídla
                doParse = True
            elif doParse == True:
                # Už parsujeme jídla, ale narazili jsme na následující den - končíme
                break
        elif doParse:
            if len(text.strip()) == 0:
                # Prázdná řádka - končíme (je za pátečním menu TechTower)
                break
            price = '? Kč'
            if text.endswith('Kč'):
                split = text.rsplit(' ', 2)
                price = " ".join(split[1:])
                text = split[0]
            foodList.append(Food(text, '-', price, isTextSoupName(text)))
    return foodList


if __name__ == "__main__":
    if len(sys.argv) > 1:
        input = sys.argv[1].lower()
        selectedDate = None
        if input[0].isalpha():
            matches = []
            for day in DAY_NAMES:
                if day.startswith(input):
                    matches.append(day)
            if len(matches) == 1:
                print("Match - den v týdnu - " + matches[0])
                selectedDate = getStartOfWeekDate(
                ) + timedelta(DAY_NAMES.index(matches[0]))
            elif len(matches) == 0:
                # TODO zkusit v, z (včera, zítra)
                if 'zítra'.startswith(input):
                    print("Match - zítra")
                    selectedDate = datetime.datetime.now() + timedelta(days=1)
                elif 'včera'.startswith(input):
                    print("Match - včera")
                    selectedDate = datetime.datetime.now() + timedelta(days=-1)
                elif 'dneska'.startswith(input):
                    print("Match - dnes")
                    selectedDate = datetime.datetime.now()
            else:
                print('Nejasný parametr "' + input +
                      '" - může znamenat jednu z možností: ' + ', '.join(matches), file=sys.stderr)
                sys.exit(1)
        else:
            # TODO implementovat zadání datem
            print('Zadání datem není aktuálně implementováno', file=sys.stderr)
            sys.exit(1)
        print("Datum: " + selectedDate.strftime('%d.%m.%Y'))
        print("Den: " + getDayNameOfDate(selectedDate))
    # printMenu('Sladovnická', getMenuSladovnicka())
    # printMenu('U Motlíků', getMenuUMotliku())
    # printMenu('TechTower', getMenuTechTower())