#
#
# DEPENDENCIES
import os
from flask import Flask, url_for, render_template, flash, request, redirect
from werkzeug.utils import secure_filename
import json
import mariadb
import sys
from PIL import Image

#
#
# GLOBAL VARIABLES
UPLOAD_FOLDER = os.path.join(os.getcwd(), 'static/uploads/annotation-compass/')
ALLOWED_EXTENSIONS = {'png', 'jpg', 'jpeg', 'gif'}
#
#
# FUNCTIONS

def connection():
    ''' Open a connection to the mariaDB database '''
    try:
        conn = mariadb.connect(
                user="guardian_of_the_labels",
                password="soup_of_the_labels",
                host="localhost",
                port=3306,
                database='collecting_labels',
                autocommit=True
        )
    except mariadb.Error as e:
        print(f'Error connecting to MariaDB Platflorm: {e}')
        sys.exit(1)

    return conn


def make_link_list(names, base_url):
    ''' Generate a list of link from the files in a folder '''
    link_list = ''
    for name in names:
        if allowed_file(name, ALLOWED_EXTENSIONS):
            link = f'<a href="{base_url}/{name}/">{name}</a><br/>'
            link_list = link_list + link
    return link_list


def allowed_file(filename, extensions):
    ''' Check if the file extension is in the allowed extensions array '''
    return '.' in filename and \
           filename.rsplit('.', 1)[1].lower() in extensions


def temp_fix_date(timestamp):
    ''' JS Date to mySQL Date '''
    from datetime import datetime
    from time import strftime
    date = datetime.fromtimestamp(timestamp / 1000.0)
    return date.strftime('%Y-%m-%d %H:%M:%S')


def add_label(cursor, label):
    ''' Insert a new label in the database '''
    x = label['position']['x']
    y = label['position']['y']
    width = label['size']['width']
    height = label['size']['height']
    text = label['text']
    timestamp = temp_fix_date(label['timestamp'])
    user_id = str(label['userID'])
    image = label['image']
    
    try:
        cursor.execute(f'INSERT INTO labels (x,y,width,height,text,timestamp,userID,image) VALUES (?, ?, ?, ?, ?, ?, ?, ?)', (x, y, width, height, text, timestamp, user_id, image ))
        print(f'Insert label#{cursor.lastrowid} from user {user_id} on {image} at {timestamp}.')
    except mariadb.Error as e:
        print(f"Error error error in MariaDB Platform: {e}")
        return {"message":"oh no", "error":e}


def get_labels(cursor, filename):
    ''' List the labels for a specific image from the database '''
    try:
        cursor.execute(f"SELECT * FROM labels WHERE image = '{filename}'")
        db_labels = cursor.fetchall()
        labels = []
        for (index, x, y, width, height, text, timestamp, user_id, image) in db_labels:
            label = {
                'position': {
                    'x': x,
                    'y': y
                    },
                'size': {
                    'width': width,
                    'height': height
                    },
                'text': text,
                'timestamp': timestamp,
                'userID': user_id,
                'image': image
                }
            labels.append(label)
        return labels
    except mariadb.Error as e:
        print(f"Error error error in MariaDB Platform: {e}")
        return {"message":"oh no", "error":e}
    

def add_image_description(filename, description):
    ''' Set description for an image during upload '''
    image_description_output = {}
    with open(os.path.join(os.getcwd(), "projects/annotation-compass/descriptions.json"), "r") as f:
        image_description_input = json.loads(f.read())
        image_description_output = image_description_input
        image_description_output[filename] = {
         'description': description   
        }
    
    with open(os.path.join(os.getcwd(), "projects/annotation-compass/descriptions.json"), "w") as f:
        f.write(json.dumps(image_description_output))


        
        
def get_image_description(filename):
    ''' Get the description of an uploaded image '''
    with open(os.path.join(os.getcwd(), "projects/annotation-compass/descriptions.json"), "r") as f:
        descriptions = json.loads(f.read()) 
        return descriptions[filename]['description']

    
def thumbnail(image):
    try:
        img = Image.open(image)
        img.thumbnail((128,128))
        name = image.rsplit('.', 1)[0]
        ext = image.rsplit('.', 1)[1]
        img.save(f'{name}_thumb.{ext}')
    except IOError:
        pass
    

# TODO: clean up this dai
# /generic-labels/ → /si16/annotation-compass/ (GET, POST)
def upload_file(request):
    ''' Upload a new image in the Annotation Compass '''
    # check if the post request has the file part
    if 'file' not in request.files:
        flash('No file part')
        return redirect(request.url)
    file = request.files['file']
    # If the user does not select a file, the browser submits an
    # empty file without a filename.
    if file.filename == '':
        flash('No selected file')
        return redirect(request.url)
    if file and allowed_file(file.filename, ALLOWED_EXTENSIONS):
        filename = secure_filename(file.filename)
        file.save(os.path.join(UPLOAD_FOLDER, filename))
        thumbnail(os.path.join(UPLOAD_FOLDER, filename))
        description = request.form['description']
        add_image_description(filename, description)

        
def list_images():  
    '''  List the images in the Annotation Compass. '''
    files = os.listdir(UPLOAD_FOLDER)
    files.sort()
    
    not_thumbs = filter(lambda file: '_thumb.' not in file, files)
    
    images = []
    for image in not_thumbs:
        if allowed_file(image, ALLOWED_EXTENSIONS):
            name = image.rsplit('.', 1)[0]
            ext = image.rsplit('.', 1)[1]
            img = image
            thumb = f'{name}_thumb.{ext}'
            images.append((img, thumb))
    return images
    
#     links = make_link_list(images, 'annotate/' )
    
    # TODO: transform this in a template
#     return f'''
#         <!doctype html>
#         <title>Collecting Labels</title>
#         {links}
#         <h2>Upload new File</h2>
#         <form method=post enctype=multipart/form-data>
#           <input type=file name=file>
#           <input type=submit value=Upload>
#           <textarea name=description ></textarea>
#         </form>
#         '''

# /generic-labels/annotate/<image>/ → /si16/annotation-compass/annotate/<image>/
# def annotate_image(image=None):
#     ''' Open the Annotation Compass on a specific image '''
#     description = ''
#     try:
#         description = get_image_description(image)
#     except:
#         print("There is no description")
#     return render_template('annotate_image.html', image=image, description=description)


# /generic-labels/add-label/ → /si16/annotation-compass/add-label
# in the URL there is no reference to the image because the info is in the json body of the label itself
def insert_label(request):
    ''' Insert a new label in the database '''
    connect = connection()
    cursor = connect.cursor()
    add_label(cursor, request.json)
    connect.close()
    return {"response": "ok"}

# /generic-labels/get-labels/ → /si16/annotation-compass/get-labels/<image>/  
# TODO: adapt the old url with the query 
# OLD: /get-labels/?image=<image> 
# NEW: /get-labels/<image>/

def get_labels_list(image = None):
        connect = connection()
        cursor = connect.cursor()
        labels = get_labels(cursor, image)
        connect.close()
        return {"response": "ok", "labels": labels }