#  THE LIBRARY #


from itertools import groupby  # to handle complex iterations
import os

import sqlite3
from webbrowser import get
from flask import Flask, render_template, url_for, request, redirect, flash


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

def get_db_connection():
    conn = sqlite3.connect('library.db')
    conn.row_factory = sqlite3.Row
    return conn
# Added row_factory attribute to the sqlite connection, in this way you can have name-based access to columns; this means that the database connection will return rows that behave like regular Python dictionaries.


# ----- 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__)
app.config['SECRET KEY']='this should be a secret random string'

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


@ app.route("/")
def home():
    conn=get_db_connection()
    todos=conn.execute('SELECT c.id, c.content, cat.title  \
                          FROM cards c JOIN categories cat \
                          ON c.category_id = cat.id ORDER BY cat.title').fetchall()

    categories={}

    # for each category and group of cards for each cat in groupby() grouper object
    for k, g in groupby(todos, key=lambda t: t['title']):
        cards=[]

        for card in g:
            card=dict(card)
            print('card is:', card)
            cards.append(card)
        # print(categories[k])

        categories[k]=list(cards)

    for cat, cards in categories.items():  # ♥ .items is a build in attribute of the dictionary(?)
        print(cat)
        for card in cards:
            print('    ', card['content'])

    conn.close()
    return render_template('home.html', categories=categories)


@ app.route("/add/", methods=['GET', 'POST'])
def create():
    conn=get_db_connection()

    if request.method == 'POST':
        content=request.form['content']
        cat_title=request.form['cat']

        #create a new category:
        new_category = request.form['new_category']
        # if a new category_title is created add it to the table of categories
        if cat_title == 'New category' and new_category:
            conn.execute('INSERT INTO categories (title) VALUES (?)',
                            (new_category,))
            conn.commit()
            # update cat_title to refer to the newly added category
            cat_title = new_category


        if not content:
            flash('plz write a content!')
            return redirect(url_for('home'))

        cat_id=conn.execute('SELECT id FROM categories WHERE title = (?);',
                              (cat_title,)).fetchone()['id']
        conn.execute('INSERT INTO cards (content, category_id) VALUES (?,?)',
                     (content, cat_id))
        conn.commit()
        conn.close()
        return redirect(url_for('home'))

    categories=conn.execute('SELECT title FROM categories;').fetchall()

    conn.close()
    return render_template('create.html', categories=categories)


@ app.route('/<int:id>/edit/', methods=('GET', 'POST'))
def edit(id):
    conn=get_db_connection()

    todo=conn.execute('SELECT c.id, c.category_id, c.content, cat.title \
                         FROM cards c JOIN categories cat \
                         ON c.category_id = cat.id WHERE c.id = ?', (id,)).fetchone()

    categories=conn.execute('SELECT title FROM categories;').fetchall()

    if request.method == 'POST':
        content=request.form['content']
        cat_title=request.form['cat']

        if not content:
            flash('plz insert any content!')
            return redirect(url_for('home'))

        cat_id=conn.execute('SELECT id FROM categories WHERE title = (?);',
                              (cat_title,)).fetchone()['id']

        conn.execute('UPDATE cards SET content = ?, category_id = ? \
                    WHERE id = ?',
                     (content, cat_id, id))
        conn.commit()
        conn.close()
        return redirect(url_for('home'))

    return render_template('edit.html', todo=todo, categories=categories)


@ app.route('/<int:id>/delete/', methods=('POST',))
def delete(id):
    conn=get_db_connection()
    conn.execute('DELETE FROM cards WHERE id = ?', (id,))
    conn.commit()
    conn.close()
    return redirect(url_for('home'))

# app.run(port=3148)


# TODO:
# - list the cards
# - put its category inside
