#  THE LIBRARY #

from crypt import methods
import os

import sqlite3
from flask import Flask, render_template, url_for, request, redirect


# ----- functions ----- #

# create table
def createNewTable(tab_name):
    ''' input types str, and list of strings'''
    try:
        connection = sqlite3.connect('library.db')
        cursor = connection.cursor()
        print(f'connected to library.db')

        table = f'''CREATE TABLE {tab_name}
                    (author, title, description)
        '''
        cursor.execute(table)
        print(f'table {tab_name} created successfully')
        cursor.close()

    except sqlite3.Error as error:
        print("Failed to create a new table", error)
    finally:
        if connection:
            connection.close()
            print("The Sqlite connection is closed")


def getAllTables(db_name):
    '''input type str, returns a list'''
    tables = []
    try:
        connection = sqlite3.connect(db_name)
        cursor = connection.cursor()
        print("connected to" + db_name)
        sql_query = """SELECT name FROM sqlite_master
        WHERE type='table';"""
        cursor.execute(sql_query)
        print("list of tables:")
        tables_available = cursor.fetchall()
        for table in tables_available:
            print(table)

    except sqlite3.Error as error:
        print("Failed to execute the above query", error)

    finally:
        if connection:
            connection.close()
            print("the sqlite connection is closed")
    return tables

# probably need to make this more general and put add book inside the routes' functions
# add entry for the table "reading list"


def add_book(author_n, book_title, text):
    db = sqlite3.connect('library.db')
    cursor = db.cursor()

    cursor.execute("INSERT INTO reading_list VALUES (?,?,?)",
                   (author_n, book_title, text))
    db.commit()
    print(f"added {book_title} to the reading_list db")
    db.close()


def getAllRows(db):
    '''input type string, get all the rows of a db'''
    rows_list = []

    try:
        connection = sqlite3.connect(db)
        cursor = connection.cursor()
        print("Connected to reading_list")

        sqlite_select_query = """SELECT * from reading_list"""
        cursor.execute(sqlite_select_query)
        records = cursor.fetchall()
        print("Total rows are:  ", len(records))
        print("Printing each row")
        print("\n")

        # f.e. the following is very specific of the library.db
        for row in records:
            row = {"author": row[0],
                   "title": row[1],
                   "description": row[2]}
            rows_list.append(row)
            print(row)
        cursor.close()

    except sqlite3.Error as error:
        print("Failed to read data from table", error)
    finally:
        if connection:
            connection.close()
            print("The Sqlite connection is closed")
    return rows_list


# ----- FLASK ----- #

class PrefixMiddleware(object):
    def __init__(self, app, prefix=""):
        self.app = app
        self.prefix = prefix

    def __call__(self, environ, start_response):

        if environ["PATH_INFO"].startswith(self.prefix):
            environ["PATH_INFO"] = environ["PATH_INFO"][len(self.prefix):]
            environ["SCRIPT_NAME"] = self.prefix
            return self.app(environ, start_response)
        else:
            start_response("404", [("Content-Type", "text/plain")])
            return ["This url does not belong to the app.".encode()]


app = Flask(__name__)

# register the middleware to prefix all the requests with our base_url
app.wsgi_app = PrefixMiddleware(app.wsgi_app, prefix='/soupboat/library')


@app.route("/", methods=['GET', 'POST'])
def home():
    getAllTables('./library.db')

    if request.method == 'POST':
        title = request.form.get('title')
        author = request.form.get('author')
        description = request.form.get('description')
        add_book(author, title, description)
#         if author:
#             return url_for('add_new_author')
        add_new_author()
        return redirect(url_for('home'))

    return render_template('home.html', reading_list=getAllRows('library.db'))

# def reading_list():
#     rows = getAllRows('library.db') #it's type list, you can try to print it
#     reading_list = []
#     for entry in rows:
#         entry = {"author": entry["author"],
#                 "title": entry["title"],
#                 "description": entry["description"]}
#         reading_list.append(entry)
#     return reading_list


@app.route("/add", methods=['GET', 'POST'])
def add_new_page():
    # the goal here is to choose from a list of parameters what you want to add
    # 1- ogni blocco del form dovrebbe essere una tabella a parte
    if request.method == 'POST':
        title = request.form.get('title')
        author = request.form.get('author')
        description = request.form.get('description')
        add_book(author, title, description)
#         if author:
#             return url_for('add_new_author')
        add_new_author()
        return redirect(url_for('home'))
    return render_template('add_new.html')

# so instead of having a function for everything there will be a unique function to create the category with relative table (it will probably be an augmented "create_table()" function


# def add_new_book():
#     if request.method == 'POST':
#         title = request.form.get('title')
#         author = request.form.get('author')
#         description = request.form.get('description')
#         add_book(author, title, description)
# #         if author:
# #             return url_for('add_new_author')
#         add_new_author()
#         return redirect(url_for('home'))
#     return render_template('add_book.html')

def add_new_author():
    print('testetest this function is working')
#     if request.method == 'POST':
#         table


# the list of books doesn't have to coincide with the list of authors, but when you add a new book that has a new author the function will automacally add a new author so. shall it be in the home page?? (no mettiamo tutto nell'add new page con una funzione che aggiunge ogni elemento del form nella tabella corrispondente, se non esiste, aggiunge una nuova categoria)


app.run(port=3148)
# -------------------
# TODO:
#
# - ⭐ create flask app
# - ⭐ create symple db with readings
# - ⭐ add the form input to db
# - ⭐ fetch all rows
# - ⭐ getallrows returns a list to be iterated with jinja
# - ⭐ and visualize them in the homepage (<table></table>)
# - ⭐ fetch all tables function
# - show all tables
# - edit items
# - remove item/entry from a table


# - create tag system (type, topics, notes)
# - sort notes (what if notes had their own tag system that interacts with the one of the resources?)
# same goes for authors,create a table of authors that then can relate to biografies and connections for the topics they treat or for their personal connections... too much?

# ----- Notes ----- #

# I wanted to create a reading list for the summer, in which I could add my comments and organize the readings through some personal categories. As I was also interested in relational tables and databases I started to do some tutorials with sqlite. This is the first attempt to apply those tutorials to the library, it's gonna be very basic initially, but I'll try to document the steps on the way. At the moment I have a vague idea of how the project can be developed but I'm really not aware of all the steps for sure.

# So this is the process: I write initially a raw todo list with main steps I want to reach (like using flask, creating database etc), then I try to figure out the steps in-between to accomplish a main step. It ain't easy though.

# I got stuck immediately when I tried to create the Flask application: I needed to register the prefix middleware to be able to see the front-end on the right port and url (asked to kamo and then copy pasted the lines about the prefix middleware from another project on the soupboat)

# I created the first table of the database by running the create_table() funct in the add() url, which was a pretty ugly procedure, but then I could write a simpler function to add_book() that refers directly to that table (not so abstracted in this case, but will fix this part later on)

# getAllRow() is also related to specific table of a db, so need to make it more abstract/general

# In the beginning I wasn't sure that getAllRows() should return something, but as I understood I need to display the rows with jinja and html I got that I need a list of objects (in this case the rows of the db with books) to be able to populate the html table with my data

# ok, it took me a while to understand how to pass the list of dictionaries (the reading list that i got from the funct getAllRows()) to the frontend. but it was because I didn't want to recreate the object of the row again, is there a quicker way to pass the list with all the arguments of its dictionaries?
# yes there was a muh quiker way, just return the function getAllRows directly with the name of the db, it will pass directly the reding list to jinja

# Right now I have something that looks like a very raw table. I'm thinking what's the next step. I'd like to create a system of tags but also a system of notation for each book. I'll do some research on notation and tag systems and a tutorial on relational tables


# didn't do anything for days hahah I don't remember clearly what i was doing so documentation really helps me getting back on track

# 15/09/22
# It's been a month that I haven't touched this proj. really difficult to pick up on what i did, because there is not a clear method in the documentation either. so now I will try to write the process only here and to reference the (current) lines of things
