import sqlite3
import io
import os
import sys
from PIL import Image, ImageTk
import tkinter as tk
from tkinter import ttk

SEARCH = """
    SELECT recipe.ROWID, item.uniquename, title.en, title.ru, recipe.amountcrafted 
    FROM title JOIN item ON title.item=item.ROWID JOIN recipe ON recipe.item=item.ROWID
    WHERE UPPER(title.en) LIKE ?1
    OR UPPER(title.ru) LIKE ?1
    ORDER BY title.en;
"""
SEARCH2 = """
    SELECT item.ROWID
    FROM title JOIN item ON title.item=item.ROWID 
    WHERE UPPER(title.en) LIKE ?1
    OR UPPER(title.ru) LIKE ?1
    ORDER BY title.en;
"""

RECIPES = """
    SELECT ingredient.recipe, i2.uniquename, t2.en, t2.ru, recipe.amountcrafted, ingredient.amount
    FROM ingredient JOIN item ON item.ROWID=ingredient.item JOIN title ON title.item=item.ROWID
    JOIN recipe on ingredient.recipe=recipe.ROWID JOIN item as i2 ON i2.ROWID=recipe.item 
    JOIN title as t2 ON i2.ROWID=t2.item
    WHERE ingredient.item = ?;
"""

INGREDIENTS = """
    SELECT item.ROWID, item.uniquename, ingredient.amount, title.en, title.ru 
    FROM ingredient JOIN item ON ingredient.item=item.ROWID JOIN title ON title.item=item.ROWID
    WHERE ingredient.recipe = ?;
"""


def update(db, frame, entry, event, images):
    search = entry.get().strip().split()
    if len(search) < 2:
        return
    n = None
    ni = None
    try:
        n = int(search[0])
        ni = 0
    except:
        pass
    if n is None:
        try:
            n = int(search[-1])
            ni = -1
        except:
            pass
    if n is None:
        return
    del search[ni]
    search = " ".join(search).upper()
    if len(search) < 3:
        return
    for w in frame.winfo_children():
        w.destroy()

    inner = tk.Canvas(frame)
    inner.pack(side="left", fill="both", expand=1)
    scrollbar = ttk.Scrollbar(frame, orient="vertical", command=inner.yview)
    scrollbar.pack(side="right", fill="y")
    inner.configure(yscrollcommand=scrollbar.set)
    inner.update()
    scrollable_frame = tk.Frame(inner)
    w = inner.create_window((0, 0), window=scrollable_frame, anchor="nw")
    inner.itemconfig(w, width=inner.winfo_width())
    search_by_recipe(db, images, n, search, scrollable_frame)
    search_by_ingredient(db, images, n, search, scrollable_frame)
    inner.update()
    try:
        inner.configure(scrollregion=inner.bbox("all"))
    except:
        pass


def search_by_recipe(db, images, n, search, inner):
    for i, un, en, ru, ac in db.execute(SEARCH, ("%" + search + "%",)).fetchall():
        row = ttk.Frame(inner)
        row.pack(fill="x", expand=1)
        left = ttk.Frame(row)
        left.pack(side="left", fill="y")
        ttk.Label(left, image=images[un]).pack()
        ttk.Label(left, text=en, font=("TkDefaultFont", 10, "bold")).pack()
        ttk.Label(left, text=ru, font=("TkDefaultFont", 10, "bold")).pack()
        ttk.Label(left, text=f"{n}/{ac}", font=("TkDefaultFont", 10, "bold")).pack()
        right = ttk.Frame(row)
        right.pack(side="right")
        for j, iun, iam, ien, iru in db.execute(INGREDIENTS, (i,)).fetchall():
            ingr = ttk.Frame(right)
            ingr.pack(side="left")
            ttk.Label(ingr, image=images[iun]).pack()
            ttk.Label(ingr, text=ien).pack()
            ttk.Label(ingr, text=iru).pack()
            ttk.Label(ingr, text=f"{iam}*{n//ac}={iam*(n//ac)}").pack()


def search_by_ingredient(db, images, n, search, inner):
    for (i,) in db.execute(SEARCH2, ("%" + search + "%",)).fetchall():
        for j, un, en, ru, ac, ami in db.execute(RECIPES, (i,)):
            c = n // ami
            row = ttk.Frame(inner)
            row.pack(fill="x", expand=1)
            left = ttk.Frame(row)
            left.pack(side="left", fill="y")
            ttk.Label(left, image=images[un]).pack()
            ttk.Label(left, text=en).pack()
            ttk.Label(left, text=ru).pack()
            ttk.Label(left, text=f"{ac}*{c}={ac*c}").pack()
            right = ttk.Frame(row)
            right.pack(side="right")
            for ii, iun, iam, ien, iru in db.execute(INGREDIENTS, (j,)).fetchall():
                ingr = ttk.Frame(right)
                ingr.pack(side="left")
                ttk.Label(ingr, image=images[iun]).pack()
                if ii == i:
                    ttk.Label(ingr, font=("TkDefaultFont", 10, "bold"), text=ien).pack()
                    ttk.Label(ingr, font=("TkDefaultFont", 10, "bold"), text=iru).pack()
                    ttk.Label(
                        ingr,
                        text=f"{iam}*{c}={iam*(c)}",
                        font=("TkDefaultFont", 10, "bold"),
                    ).pack()
                else:
                    ttk.Label(ingr, text=ien).pack()
                    ttk.Label(ingr, text=iru).pack()
                    ttk.Label(ingr, text=f"{iam}*{c}={iam*(c)}").pack()


def close(root, db):
    db.close()
    root.destroy()


def main():
    root = tk.Tk()
    root.geometry("900x900+20+20")
    path = "recipes.db"
    if hasattr(sys, '_MEIPASS'):
        path = os.path.join(sys._MEIPASS, "recipes.db")
    db = sqlite3.connect(path)
    db.create_function("UPPER", 1, str.upper)
    images = {
        a: b
        for a, b in db.execute(
            "SELECT item.uniquename, image.image FROM item JOIN image ON item.ROWID=image.item;"
        ).fetchall()
    }
    images = {
        a: ImageTk.PhotoImage(Image.open(io.BytesIO(b)).resize((100, 100)))
        for a, b in images.items()
    }
    root.title("Albion Online Recipes Helper")
    f = ttk.Frame(root)
    f.pack(fill="both", expand=1, padx=5, pady=5)
    ttk.Label(f, text="Напечатай сколько и чего надо:").pack(anchor="nw")
    s = ttk.Entry(f)
    s.focus()
    s.pack(anchor="nw")
    ttk.Label(f, text="Вот что можно сделать:").pack(anchor="nw")
    b = ttk.Frame(f)
    b.pack(fill="both", expand=1)
    s.bind("<KeyRelease>", lambda e: update(db, b, s, e, images))

    root.protocol("WM_DELETE_WINDOW", lambda: close(root, db))
    root.mainloop()


if __name__ == "__main__":
    main()
