from flask import Flask, request, redirect, jsonify, render_template, Response,url_for, send_from_directory
import os
import json
from flask_socketio import SocketIO
from threading import Thread
from pprint import pprint as pp
from pathlib import Path
import time,random,string,sqlite3,csv
import numpy as np
import re #regex
import rebrick #rebrickable api
import requests # request img from web
import shutil # save img locally
import eventlet
from downloadRB import download_and_unzip,get_nil_images,get_retired_sets
from db import initialize_database,get_rows,delete_tables
from werkzeug.middleware.proxy_fix import ProxyFix
from werkzeug.utils import secure_filename


app = Flask(__name__)
app.wsgi_app = ProxyFix(app.wsgi_app, x_for=1, x_proto=1, x_host=1, x_port=1, x_prefix=1)
socketio = SocketIO(app,cors_allowed_origins=os.getenv("DOMAIN_NAME"))
count = 0

if os.getenv("RANDOM") == 'True':
    RANDOM = True
else:
    RANDOM = False

if os.getenv("LINKS"):
    LINKS = os.getenv("LINKS")
else:
    LINKS = False

DIRECTORY = os.path.join(os.getcwd(), 'static', 'instructions')

UPLOAD_FOLDER = DIRECTORY
ALLOWED_EXTENSIONS = {'pdf'}
app.config['UPLOAD_FOLDER'] = UPLOAD_FOLDER

@app.route('/favicon.ico')

# SocketIO event handler for client connection
@socketio.on('connect', namespace='/progress')
def test_connect():
    print('Client connected')
    return ('', 301)

# SocketIO event handler for client disconnection
@socketio.on('disconnect', namespace='/progress')
def test_disconnect():
    print('Client disconnected')

# SocketIO event handler for starting the task
@socketio.on('start_task', namespace='/progress')
def start_task(data):
    input_value = data.get('inputField')
    print(input_value)
    
    

    input_value = input_value.replace(" ","")
    if '-' not in input_value:
        input_value = input_value + '-1'



    total_set_file = np.genfromtxt("sets.csv",delimiter=",",dtype="str",usecols=(0))
    print(total_set_file)

    if input_value not in total_set_file:
        print('ERROR: ' + input_value)
        # Reload create.html with error message
        socketio.emit('task_failed', namespace='/progress')
        #return render_template('create.html',error=input_value)


        # Start the task in a separate thread to avoid blocking the serve
    else:
        print('starting servers')
        thread = Thread(target=new_set, args=(input_value,))
        thread.start()

    #return redirect('/')

def hyphen_split(a):
    if a.count("-") == 1:
        return a.split("-")[0]
    return "-".join(a.split("-", 2)[:2])

def allowed_file(filename):
    return '.' in filename and \
        filename.rsplit('.', 1)[1].lower() in ALLOWED_EXTENSIONS

@app.route('/upload',methods=['GET','POST'])
def uploadInst():
    if request.method == 'POST':
        # 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):
            filename = secure_filename(file.filename)
            file.save(os.path.join(app.config['UPLOAD_FOLDER'], filename))
            return redirect('/')
    return '''
        <!doctype html>
        <title>Upload instructions</title>
        <h1>Upload instructions</h1>
        <p>Files must be named like:</p>
        <code>&lt;set number&gt;-&lt;version&gt;-&lt;part&gt;.pdf</code>
        <ul>
          <li><code>7595-1.pdf</code> for set 7595</li>
          <li><code>71039-2.pdf</code> for Moon Knight in <code>Collectible Minifigures: Marvel Series 2</code></li>
          <li><code>71039-13.pdf</code> for the whole set <code>Collectible Minifigures: Marvel Series 2</code></li>
          <li><code>10294-1-1.pdf</code> for the 1st pdf in the 10294 set
          <li><code>10294-1-2.pdf</code> for the 2nd pdf in the 10294 set
          <li><code>10294-1-3.pdf</code> for the 3rd pdf in the 10294 set
          <li><code>10937-1-0.pdf</code> for the comic that comes with set 10937.
          <li><code>10937-1-1.pdf</code> for the 1st pdf in the 10937 set
        </ul>   
        <form method=post enctype=multipart/form-data>
          <input type=file name=file>
          <input type=submit value=Upload>
        </form>
        '''

@app.route('/delete/<tmp>',methods=['POST', 'GET'])
def delete(tmp):

    conn = sqlite3.connect('app.db')
    cursor = conn.cursor()

    if request.method == 'POST':
        print("POST")
    if request.method == "GET":
        print("GET")
        print(tmp)
        tables = ['inventory', 'sets', 'minifigures', 'missing']
        for t in tables:
            cursor.execute('DELETE FROM ' + t + ' where u_id="' +tmp+ '";')
            conn.commit()
        cursor.close()
        conn.close()
    return redirect('/')

def progress(count,total_parts,state):
    print (state)
    socketio.emit('update_progress', {'progress': int(count/total_parts*100), 'desc': state}, namespace='/progress')

def new_set(set_num):
    global count
    ###### total count ####
    # 1 for set
    # 1 for set image

    total_parts = 20



    # add_duplicate = request.form.get('addDuplicate', False) == 'true'
    # Do something with the input value and the checkbox value
    # print("Input value:", set_num)
    # print("Add duplicate:", add_duplicate)
    # You can perform any further processing or redirect to another page
    
    # >>>>>>>>
    progress(count, total_parts,'Opening database')

    conn = sqlite3.connect('app.db')
    cursor = conn.cursor()

    # >>>>>>>>
    progress(count, total_parts,'Adding set: ' + set_num)

    #with open('api','r') as f:
    #    api_key = f.read().replace('\n','')
    # TODO add 401 error on wrong key
    rb = rebrick.init(os.getenv("REBRICKABLE_API_KEY"))

    # >>>>>>>>
    progress(count, total_parts,'Generating Unique ID')
    unique_set_id = generate_unique_set_unique()

    # Get Set info and add to SQL
    response = ''
    
    # >>>>>>>>
    progress(count, total_parts,'Get set info')
    response = json.loads(rebrick.lego.get_set(set_num).read()) 
        
    # except Exception as e:
    #     #print(e.code)
    #     if e.code == 404:
    #         return render_template('create.html',error=set_num)
    
    count+=1
    
    # >>>>>>>>
    progress(count, total_parts,'Adding set to database')

    cursor.execute('''INSERT INTO sets (
        set_num,
        name,
        year,
        theme_id,
        num_parts,
        set_img_url,
        set_url,
        last_modified_dt,
        mini_col,
        set_check,
        set_col,
        u_id
        ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) ''', (response['set_num'], response['name'], response['year'], response['theme_id'], response['num_parts'],response['set_img_url'],response['set_url'],response['last_modified_dt'],False,False,False,unique_set_id))

    conn.commit()



    # Get set image. Saved under ./static/sets/xxx-x.jpg
    set_img_url = response["set_img_url"]

    #print('Saving set image:',end='')

    # >>>>>>>>
    progress(count, total_parts,'Get set image')

    res = requests.get(set_img_url, stream = True)
    count+=1
    if res.status_code == 200:
        # >>>>>>>>
        progress(count, total_parts,'Saving set image')
        with open("./static/sets/"+set_num+".jpg",'wb') as f:
            shutil.copyfileobj(res.raw, f)
            #print(' OK')
    else:
        #print('Image Couldn\'t be retrieved for set ' + set_num)
        logging.error('set_img_url: ' + set_num)
        #print(' ERROR')


    # Get inventory and add to SQL
    # >>>>>>>>
    progress(count, total_parts,'Get set inventory')
    response = json.loads(rebrick.lego.get_set_elements(set_num,page_size=500).read())
    count+=1
    total_parts += len(response['results'])
    
    for i in response['results']:
        if i['is_spare']:
            continue
        # Get part image. Saved under ./static/parts/xxxx.jpg
        part_img_url = i['part']['part_img_url']
        part_img_url_id = 'nil'

        try:
            pattern = r'/([^/]+)\.(?:png|jpg)$'
            match = re.search(pattern, part_img_url)

            if match:
                part_img_url_id = match.group(1)
                #print("Part number:", part_img_url_id)
            else:        
                #print("Part number not found in the URL.")
                print(">>> " + part_img_url)
        except Exception as e:
                #print("Part number not found in the URL.")
                #print(">>> " + str(part_img_url))
                print(str(e))

        # >>>>>>>>
        progress(count, total_parts,'Adding ' + i['part']['name'] + ' to database')
        cursor.execute('''INSERT INTO inventory (
            set_num,
            id,
            part_num,
            name,
            part_img_url,
            part_img_url_id,
            color_id,
            color_name,
            quantity,
            is_spare,
            element_id,
            u_id
        ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)''', (set_num, i['id'], i['part']['part_num'],i['part']['name'],i['part']['part_img_url'],part_img_url_id,i['color']['id'],i['color']['name'],i['quantity'],i['is_spare'],i['element_id'],unique_set_id))
        
        
        if not Path("./static/parts/"+part_img_url_id+".jpg").is_file():
            #print('Saving part image:',end='')
            if part_img_url is not None:
                # >>>>>>>>
                progress(count, total_parts,'Get part image')
                res = requests.get(part_img_url, stream = True)
                count+=1
                if res.status_code == 200:
                    # >>>>>>>>
                    progress(count, total_parts,'Saving part image')
                    with open("./static/parts/"+part_img_url_id+".jpg",'wb') as f:
                        shutil.copyfileobj(res.raw, f)
                        #print(' OK')
                else:
                    #print('Image Couldn\'t be retrieved for set ' + part_img_url_id)
                    logging.error('part_img_url: ' + part_img_url_id)
                    #print(' ERROR')
            else:
                #print('Part url is None')
                print(i)
        

    conn.commit()

    # Get minifigs
    #print('Savings minifigs')
    tmp_set_num = set_num
    # >>>>>>>>
    progress(count, total_parts,'Get set minifigs')
    response = json.loads(rebrick.lego.get_set_minifigs(set_num).read())
    count+=1
    
    #print(response)
    for i in response['results']:

        # Get set image. Saved under ./static/minifigs/xxx-x.jpg
        set_img_url = i["set_img_url"]
        set_num = i['set_num']

        #print('Saving set image:',end='')
        if not Path("./static/minifigs/"+set_num+".jpg").is_file():
            if set_img_url is not None:
                # >>>>>>>>
                progress(count, total_parts,'Get minifig image')
                res = requests.get(set_img_url, stream = True) 
                count+=1
                if res.status_code == 200:
                    # >>>>>>>>
                    progress(count, total_parts,'Saving minifig image')
                    with open("./static/minifigs/"+set_num+".jpg",'wb') as f:
                        shutil.copyfileobj(res.raw, f)
                        #print(' OK')
                else:
                    #print('Image Couldn\'t be retrieved for set ' + set_num)
                    logging.error('set_img_url: ' + set_num)
                    #print(' ERROR')
            else:
               print(i) 
        # >>>>>>>>
        progress(count, total_parts,'Adding minifig to database')
        cursor.execute('''INSERT INTO minifigures (
            fig_num,
            set_num,
            name,
            quantity,
            set_img_url,
            u_id
        ) VALUES (?, ?, ?, ?, ?, ?) ''', (i['set_num'],tmp_set_num, i['set_name'], i['quantity'],i['set_img_url'],unique_set_id))

        conn.commit()
    
        # Get minifigs inventory
        # >>>>>>>>
        progress(count, total_parts,'Get minifig inventory')
        response_minifigs = json.loads(rebrick.lego.get_minifig_elements(i['set_num']).read())
        count+=1
        for i in response_minifigs['results']:

            # Get part image. Saved under ./static/parts/xxxx.jpg
            part_img_url = i['part']['part_img_url']
            part_img_url_id = 'nil'
            try:
                pattern = r'/([^/]+)\.(?:png|jpg)$'
                match = re.search(pattern, part_img_url)

                if match:
                    part_img_url_id = match.group(1)
                    #print("Part number:", part_img_url_id)
                    if not Path("./static/parts/"+part_img_url_id+".jpg").is_file():
                        #print('Saving part image:',end='')
                        
                        # >>>>>>>>
                        progress(count, total_parts,'Get minifig image')
                        res = requests.get(part_img_url, stream = True)
                        count+=1
                        if res.status_code == 200:
                            # >>>>>>>>
                            progress(count, total_parts,'Saving minifig image')
                            with open("./static/parts/"+part_img_url_id+".jpg",'wb') as f:
                                shutil.copyfileobj(res.raw, f)
                                #print(' OK')
                        else:
                            #print('Image Couldn\'t be retrieved for set ' + part_img_url_id)
                            logging.error('part_img_url: ' + part_img_url_id)
                            #print(' ERROR')
                    else: 
                        print(part_img_url_id + '.jpg exists!')
            except Exception as e:
                    #print("Part number not found in the URL.")
                    #print(">>> " + str(part_img_url))
                    print(str(e))
            # >>>>>>>>
            progress(count, total_parts,'Adding minifig inventory to database')
            cursor.execute('''INSERT INTO inventory (
                set_num,
                id,
                part_num,
                name,
                part_img_url,
                part_img_url_id,
                color_id,
                color_name,
                quantity,
                is_spare,
                element_id,
                u_id
            ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)''', (i['set_num'], i['id'], i['part']['part_num'],i['part']['name'],i['part']['part_img_url'],part_img_url_id,i['color']['id'],i['color']['name'],i['quantity'],i['is_spare'],i['element_id'],unique_set_id))
            
            
        
        conn.commit()
    conn.close()
    # >>>>>>>>
    progress(count, total_parts,'Closing database')
    #print('End Count: ' + str(count))
    #print('End Total: ' + str(total_parts))
    count = total_parts

    # >>>>>>>>
    progress(count, total_parts,'Cleaning up')

    count = 0
    socketio.emit('task_completed', namespace='/progress')

def get_file_creation_dates(file_list):
    creation_dates = {}
    for file_name in file_list:
        file_path = f"{file_name}"
        if os.path.exists(file_path):
            creation_time = os.path.getctime(file_path)
            creation_dates[file_name] = time.ctime(creation_time)
        else:
            creation_dates[file_name] = "File not found"
    return creation_dates

@app.route('/config',methods=['POST','GET'])
def config():

    file_list = ['themes.csv', 'colors.csv', 'sets.csv','static/nil.png','static/nil_mf.jpg','retired_sets.csv']
    creation_dates = get_file_creation_dates(file_list)
    
    row_counts = [0]
    db_exists = Path("app.db")
    if db_exists.is_file(): 
        db_is_there = True
        row_counts = get_rows()
    else:
        db_is_there = False

    if request.method == 'POST':

        if request.form.get('CreateDB') == 'Create Database':
            initialize_database()
            row_counts = get_rows() 
            return redirect(url_for('config'))
        elif  request.form.get('Update local data') == 'Update local data':
            urls = ["themes","sets","colors"]
            for i in urls:
                download_and_unzip("https://cdn.rebrickable.com/media/downloads/"+i+".csv.gz") 
            get_nil_images()
            get_retired_sets()
            return redirect(url_for('config'))

        elif  request.form.get('deletedb') == 'Delete Database':
           delete_tables()
           initialize_database()

        else:
            # pass # unknown
            return render_template("config.html")
    elif request.method == 'GET':
        # return render_template("index.html")
        print("No Post Back Call")
    return render_template("config.html",db_is_there=db_is_there,creation_dates = creation_dates,row_counts=row_counts)

@app.route('/missing',methods=['POST','GET'])
def missing():
    conn = sqlite3.connect('app.db')
    cursor = conn.cursor()
    #cursor.execute("SELECT part_num,  color_id, element_id, part_img_url_id, SUM(quantity) AS total_quantity, GROUP_CONCAT(set_num, ', ') AS set_number FROM missing GROUP BY part_num, color_id, element_id;") 

    cursor.execute("SELECT part_num, color_id, element_id, part_img_url_id, SUM(quantity) AS total_quantity, GROUP_CONCAT(set_num || ',' || u_id, ',') AS set_number FROM missing GROUP BY part_num, color_id, element_id, part_img_url_id ORDER BY part_num;")

    results = cursor.fetchall()
    missing_list = [list(i) for i in results]
    cursor.close()
    conn.close()

    color_file = np.loadtxt("colors.csv",delimiter=",",dtype="str")

    color_dict = {str(code): name for code, name, _, _ in color_file}

    for item in missing_list:
        color_code = str(item[1])
        if color_code in color_dict:
            item[1] = color_dict[color_code]

    return render_template('missing.html',missing_list=missing_list)

@app.route('/parts',methods=['POST','GET'])
def parts():
    conn = sqlite3.connect('app.db')
    cursor = conn.cursor()
    cursor.execute('SELECT id, part_num, color_id, color_name, element_id, part_img_url_id, SUM(quantity) AS total_quantity, name FROM inventory GROUP BY part_num, part_img_url_id, color_id, color_name, element_id, name;') 

    results = cursor.fetchall()
    missing_list = [list(i) for i in results]
    cursor.close()
    conn.close()

    #color_file = np.loadtxt("colors.csv",delimiter=",",dtype="str")

    #color_dict = {str(code): name for code, name, _, _ in color_file}

    #for item in missing_list:
    #    color_code = str(item[2])
    #    if color_code in color_dict:
    #        item[2] = color_dict[color_code]

    return render_template('parts.html',missing_list=missing_list)

@app.route('/minifigs',methods=['POST','GET'])
def minifigs():
    conn = sqlite3.connect('app.db')
    cursor = conn.cursor()
    cursor.execute('SELECT fig_num, name, SUM(quantity) AS total_quantity FROM minifigures GROUP BY fig_num, name;') 

    results = cursor.fetchall()
    missing_list = [list(i) for i in results]
    cursor.close()
    conn.close()


    return render_template('minifigs.html',missing_list=missing_list)

@app.route('/wishlist',methods=['POST','GET'])
def wishlist():
    input_value = 'None'

    if request.method == 'POST':
        if 'create_submit' in request.form:
            input_value = request.form.get('inputField')
            print(input_value)
        

            input_value = input_value.replace(" ","")
            if '-' not in input_value:
                input_value = input_value + '-1'

            total_set_file = np.genfromtxt("sets.csv",delimiter=",",dtype="str",usecols=(0))
            if input_value not in total_set_file:
                print('ERROR: ' + input_value)
                #return render_template('wishlist.html',error=input_value)

            else:
                set_num = input_value
                
                input_value = 'None'
                conn = sqlite3.connect('app.db')
                cursor = conn.cursor()
                rb = rebrick.init(os.getenv("REBRICKABLE_API_KEY"))
                response = json.loads(rebrick.lego.get_set(set_num).read()) 
                cursor.execute('''INSERT INTO wishlist (
                    set_num,
                    name,
                    year,
                    theme_id,
                    num_parts,
                    set_img_url,
                    set_url,
                    last_modified_dt
                    ) VALUES (?, ?, ?, ?, ?, ?, ?, ?) ''', (response['set_num'], response['name'], response['year'], response['theme_id'], response['num_parts'],response['set_img_url'],response['set_url'],response['last_modified_dt']))
                set_img_url = response["set_img_url"]
                res = requests.get(set_img_url, stream = True)
                if res.status_code == 200:
                    with open("./static/sets/"+set_num+".jpg",'wb') as f:
                        shutil.copyfileobj(res.raw, f)
                else:
                    logging.error('set_img_url: ' + set_num)

                conn.commit()
                conn.close()
        elif 'add_to_list' in request.form:
            set_num = request.form.get('set_num')
            conn = sqlite3.connect('app.db')
            cursor = conn.cursor()

            cursor.execute('DELETE FROM wishlist where set_num="' +set_num+ '";')
            conn.commit()
            cursor.close()
            conn.close()

    conn = sqlite3.connect('app.db')
    cursor = conn.cursor()
    cursor.execute('SELECT * from wishlist;')
    
    results = cursor.fetchall()
    wishlist = [list(i) for i in results]
    retired_sets_dict = {}
    
    try:
        with open('retired_sets.csv', mode='r', encoding='utf-8') as csvfile:
            reader = csv.reader(csvfile)
            header = next(reader)
            for row in reader:
                key = row[2]
                retired_sets_dict[key] = row
        for w in wishlist:
            set_num = w[0].split('-')[0]
            w.append(retired_sets_dict.get(set_num,[""]*7)[6])
    except:
        print('No retired list')

    if wishlist == None or wishlist == '':
        wishlist = ''
    conn.commit()
    conn.close()
    return render_template('wishlist.html',error=input_value,wishlist=wishlist)

@app.route('/create',methods=['POST','GET'])
def create():
    
    global count

    

    print('Count: ' + str(count))

    return render_template('create.html')

def generate_unique_set_unique():
    timestamp = int(time.time() * 1000)  # Current timestamp in milliseconds
    random_chars = ''.join(random.choices(string.ascii_uppercase + string.digits, k=8))  # 8-digit alphanumeric
    return f'{timestamp}{random_chars}'

@app.route('/',methods=['GET','POST'])
def index():
    set_list = []
    try:
        theme_file = np.loadtxt("themes.csv",delimiter=",",dtype="str")
    except: #First time running, no csvs.
        initialize_database()
        urls = ["themes","sets","colors"]
        for i in urls:
            download_and_unzip("https://cdn.rebrickable.com/media/downloads/"+i+".csv.gz")
        get_nil_images()
        return redirect('/create')

    if request.method == 'GET':
        
        conn = sqlite3.connect('app.db')
        cursor = conn.cursor()
        cursor.execute('SELECT * from sets;')

        results = cursor.fetchall()
        set_list = [list(i) for i in results]
        if RANDOM:
            random.shuffle(set_list)
        cursor.execute('SELECT DISTINCT u_id from missing;')
        results = cursor.fetchall()
        missing_list = [list(i)[0] for i in results]

        #print(set_list)
        for i in set_list:
            try:
                i[3] = theme_file[theme_file[:, 0] == str(i[3])][0][1]
            except Exception as e:
                print(e)

        cursor.execute('select distinct set_num from minifigures;')
        results = cursor.fetchall()
        minifigs = [list(i)[0] for i in results]

        cursor.close()
        conn.close()


        files = [f for f in os.listdir(DIRECTORY) if f.endswith('.pdf')]
        #files = [re.match(r'^([\w]+-[\w]+)', f).group() for f in os.listdir(DIRECTORY) if f.endswith('.pdf')]
        files.sort()

        return render_template('index.html',set_list=set_list,themes_list=theme_file,missing_list=missing_list,files=files,minifigs=minifigs,links=LINKS)
    
    if request.method == 'POST':
        set_num = request.form.get('set_num')
        u_id = request.form.get('u_id')
        minif = request.form.get('minif')
        scheck = request.form.get('scheck')
        scol = request.form.get('scol')

        conn = sqlite3.connect('app.db')
        cursor = conn.cursor()

        if minif != None:
            if minif == 'true':
               val = 1
            else:
                val = 0 
            cursor.execute('''UPDATE sets
                SET mini_col = ?
                WHERE   set_num = ? AND
                        u_id = ?''',
                (val, set_num, u_id))
            conn.commit()
        
        if scheck != None:
            if scheck == 'true':
               val = 1
            else:
                val = 0 
            cursor.execute('''UPDATE sets
                SET set_check = ?
                WHERE   set_num = ? AND
                        u_id = ?''',
                (val, set_num, u_id))
            conn.commit()
        if scol != None:
            if scol == 'true':
               val = 1
            else:
                val = 0 
            cursor.execute('''UPDATE sets
                SET set_col = ?
                WHERE   set_num = ? AND
                        u_id = ?''',
                (val, set_num, u_id))
            conn.commit()

        cursor.close()
        conn.close()
        
        
        
        return ('', 204)

# Route to serve individual files
@app.route('/files/<path:filename>', methods=['GET'])
def serve_file(filename):
    try:
        return send_from_directory(DIRECTORY, filename)
    except Exception as e:
        return jsonify({'error': str(e)}), 404

@app.route('/<tmp>/<u_id>', methods=['GET', 'POST'])
def inventory(tmp,u_id):
    
    if request.method == 'GET':
        
        conn = sqlite3.connect('app.db')
        cursor = conn.cursor()

        # Get set info
        cursor.execute("SELECT * from sets where set_num = '" + tmp + "' and u_id = '" + u_id + "';")
        results = cursor.fetchall()
        set_list = [list(i) for i in results]

        # Get inventory
        cursor.execute("SELECT * from inventory where set_num = '" + tmp + "' and u_id = '" + u_id + "';")
        results = cursor.fetchall()
        inventory_list =  [list(i) for i in results]

        # Get missing parts
        cursor.execute("SELECT * from missing where u_id = '" + u_id + "';")
        results = cursor.fetchall()
        missing_list =  [list(i) for i in results]
        print(missing_list)

        # Get minifigures
        cursor.execute("SELECT * from minifigures where set_num = '" + tmp + "' and u_id = '" + u_id + "';")
        results = cursor.fetchall()
        minifig_list =  [list(i) for i in results]

        minifig_inventory_list = []

        for i in minifig_list:
            cursor.execute("SELECT * from inventory where set_num = '" + i[0] + "' and u_id = '" + u_id + "';")
            results = cursor.fetchall()
            tmp_inv = [list(i) for i in results]
            minifig_inventory_list.append(tmp_inv)

        cursor.close()
        conn.close()

        return render_template('table.html', u_id=u_id,tmp=tmp,title=set_list[0][1],set_list=set_list,inventory_list=inventory_list,missing_list=missing_list,minifig_list=minifig_list,minifig_inventory_list=minifig_inventory_list)


    if request.method == 'POST':
        set_num = request.form.get('set_num')
        id = request.form.get('id')
        part_num = request.form.get('part_num')
        part_img_url_id = request.form.get('part_img_url_id')
        color_id = request.form.get('color_id')
        element_id = request.form.get('element_id')
        u_id = request.form.get('u_id')
        missing = request.form.get('missing')
            
        conn = sqlite3.connect('app.db')
        cursor = conn.cursor()

        # If quantity is not empty
        if missing != '' and missing != '0':
            #Check if there's an existing entry
            #print('in first')
            #print(missing)
            #cursor.execute('''SELECT quantity FROM missing 
            #    WHERE   set_num = ? AND 
            #            id = ? AND 
            #            part_num = ? AND 
            #            part_img_url_id = ? AND   
            #            color_id = ? AND 
            #            element_id = ? AND 
            #            u_id = ?''',
            #            (set_num, id, part_num, part_img_url_id, color_id, element_id, u_id))
            #
            #existing_quantity = cursor.fetchone()
            #print("existing" + str(existing_quantity))
            #conn.commit()


            #If there's an existing entry or if entry isn't the same as the new value 
            # First, check if a row with the same values for the other columns exists
            cursor.execute('''
                SELECT quantity FROM missing WHERE 
                set_num = ? AND
                id = ? AND
                part_num = ? AND
                part_img_url_id = ? AND
                color_id = ? AND
                element_id = ? AND
                u_id = ?
            ''', (set_num, id, part_num, part_img_url_id, color_id, element_id, u_id))

            # Fetch the result
            row = cursor.fetchone()

            if row:
                # If a row exists and the missing value is different, update the row
                if row[0] != missing:
                    cursor.execute('''
                        UPDATE missing SET 
                        quantity = ?
                        WHERE set_num = ? AND
                        id = ? AND
                        part_num = ? AND
                        part_img_url_id = ? AND
                        color_id = ? AND
                        element_id = ? AND
                        u_id = ?
                    ''', (missing, set_num, id, part_num, part_img_url_id, color_id, element_id, u_id))
            else:
                # If no row exists, insert a new row
                cursor.execute('''
                    INSERT INTO missing (
                        set_num,
                        id,
                        part_num,
                        part_img_url_id, 
                        color_id,
                        quantity,
                        element_id,
                        u_id
                    ) VALUES (?, ?, ?, ?, ?, ?, ?, ?)
                ''', (set_num, id, part_num, part_img_url_id, color_id, missing, element_id, u_id))
            conn.commit()

#            if existing_quantity is None:
#                print('in second')
#                print(existing_quantity)
#                cursor.execute('''INSERT INTO missing (
#                        set_num,
#                        id,
#                        part_num,
#                        part_img_url_id, 
#                        color_id,
#                        quantity,
#                        element_id,
#                        u_id
#                    ) VALUES (?, ?, ?, ?, ?, ?, ?, ?)''', 
#                   (set_num, id, part_num, part_img_url_id, color_id, missing, element_id, u_id))
#
#                conn.commit()
#
#            else:
#                try:
#                    if int(existing_quantity[0]) != int(missing):
#                        print('in third')
#                        print(existing_quantity)
#                        cursor.execute('''update missing set (
#                                set_num,
#                                id,
#                                part_num,
#                                part_img_url_id, 
#                                color_id,
#                                quantity,
#                                element_id,
#                                u_id
#                            ) VALUES (?, ?, ?, ?, ?, ?, ?, ?)''', 
#                           (set_num, id, part_num, part_img_url_id, color_id, missing, element_id, u_id))
#
#                        conn.commit()
#                except:
#                    pass
        
        # If quantity is empty, delete the entry.
        else:
            cursor.execute('''DELETE FROM missing
                WHERE   set_num = ? AND
                        id = ? AND
                        part_num = ? AND
                        part_img_url_id = ? AND
                        color_id = ? AND
                        element_id = ? AND
                        u_id = ?''',
                (set_num, id, part_num, part_img_url_id, color_id, element_id, u_id))

            conn.commit()

        cursor.close()
        conn.close()
        return ('', 204)

@app.route('/old', methods=['GET', 'POST'])
def frontpage():
    pathlist = Path('./info/').rglob('*.json')
    set_list = []
    json_file = {}
    theme_file = np.loadtxt("themes.csv", delimiter=",",dtype="str")
    if request.method == 'GET':
        for path in pathlist:
            set_num = re.findall(r"\b\d+(?:-\d+)?\b",str(path))[0]
            with open('./static/sets/'+set_num+'/info.json') as info:
                info_file = json.loads(info.read())
            try:
                info_file['theme_id'] = theme_file[theme_file[:, 0] == str(info_file['theme_id'])][0][1]
            except Exception as e:
                print(e)
            
            with open('./info/'+set_num+'.json') as info:
                json_file[set_num] = json.loads(info.read())
            
            set_list.append(info_file)

        return render_template('frontpage.html',set_list=set_list,themes_list=theme_file,json_file=json_file)
    
    if request.method == 'POST':
        set_num = request.form.get('set_num')
        index = request.form.get('index')
        minif = request.form.get('minif')
        scheck = request.form.get('scheck')
        scol = request.form.get('scol')
        
        with open('./info/'+set_num+'.json') as info:
            json_file = json.loads(info.read())
        if minif != None:
            json_file['unit'][int(index)]['Minifigs Collected'] = minif
        if scheck != None:
            json_file['unit'][int(index)]['Set Checked'] = scheck
        if scol != None:
            json_file['unit'][int(index)]['Set Collected'] = scol
       
        with open('./info/'+set_num+'.json', 'w') as dump_file:
            json.dump(json_file,dump_file)
        return ('', 204)

@app.route('/old/<tmp>', methods=['GET', 'POST'])
def sets(tmp):
   
    with open('./static/sets/'+tmp+'/info.json') as info:
          info_file = json.loads(info.read())
    with open('./static/sets/'+tmp+'/minifigs.json') as info:
          minifigs_file = json.loads(info.read())
    with open('./static/sets/'+tmp+'/inventory.json') as inventory:
          inventory_file = json.loads(inventory.read())
    with open('./info/'+tmp+'.json') as info:
          json_file = json.loads(info.read())

    if request.method == 'POST':
        part_num = request.form.get('brickpartpart_num')
        color = request.form.get('brickcolorname')
        index = request.form.get('index')
        number = request.form.get('numberInput')
        is_spare = request.form.get('is_spare')

        # print(part_num)
        # print(color)
        # print(index)
        # print(number)
        # print(is_spare)
        
        if number is not None:

            print(part_num)
            print(color)
            print(number)
            print(is_spare)

            with open('./info/'+tmp+'.json') as info:
                json_file = json.loads(info.read())
            print(json_file['count'])

            data = '{"brick" : {"ID":"' + part_num + '","is_spare": "' + is_spare + '","color_name": "' + color + '","amount":"' + number + '"}}'
            
            if len(json_file['unit'][int(index)]['bricks']['missing']) == 0:
                json_file['unit'][int(index)]['bricks']['missing'].append(json.loads(data))
                print(json_file)
            elif number == '':
                for idx,i in enumerate(json_file['unit'][int(index)]['bricks']['missing']):
                    if i['brick']['ID'] == part_num and i['brick']['is_spare'] == is_spare and i['brick']['color_name'] == color:
                        json_file['unit'][int(index)]['bricks']['missing'].pop(idx)
            else:
                found = False
                for idx,i in enumerate(json_file['unit'][int(index)]['bricks']['missing']):
                    if not found and i['brick']['ID'] == part_num and i['brick']['is_spare'] == is_spare and i['brick']['color_name'] == color:
                        json_file['unit'][int(index)]['bricks']['missing'][idx]['brick']['amount'] = number
                        found = True
                if not found:
                    json_file['unit'][int(index)]['bricks']['missing'].append(json.loads(data))

            
            with open('./info/'+tmp+'.json', 'w') as dump_file:
                json.dump(json_file,dump_file)
        #return Response(status=200)
        return ('', 204)
    else:
       return render_template('bootstrap_table.html', tmp=tmp,title=info_file['name'],
                       info_file=info_file,inventory_file=inventory_file,json_file=json_file,minifigs_file=minifigs_file)



@app.route('/<tmp>/saveNumber', methods=['POST'])
def save_number(tmp):
    part_num = request.form.get('brickpartpart_num')
    color = request.form.get('brickcolorname')
    index = request.form.get('index')
    number = request.form.get('numberInput')
    is_spare = request.form.get('is_spare')

    if number is not None:

        print(part_num)
        print(color)
        print(number)
        print(is_spare)

        with open('./info/'+tmp+'.json') as info:
            json_file = json.loads(info.read())

        data = '{"brick" : {"ID":"' + part_num + '","is_spare": "' + is_spare + '","color_name": "' + color + '","amount":"' + number + '"}}'
        
        if len(json_file['unit'][int(index)]['bricks']['missing']) == 0:
            json_file['unit'][int(index)]['bricks']['missing'].append(json.loads(data))
            print(json_file)
        elif number == '':
            for idx,i in enumerate(json_file['unit'][int(index)]['bricks']['missing']):
                if i['brick']['ID'] == part_num and i['brick']['is_spare'] == is_spare and i['brick']['color_name'] == color:
                    json_file['unit'][int(index)]['bricks']['missing'].pop(idx)
        else:
            found = False
            for idx,i in enumerate(json_file['unit'][int(index)]['bricks']['missing']):
                if not found and i['brick']['ID'] == part_num and i['brick']['is_spare'] == is_spare and i['brick']['color_name'] == color:
                    json_file['unit'][int(index)]['bricks']['missing'][idx]['brick']['amount'] = number
                    found = True
            if not found:
                json_file['unit'][int(index)]['bricks']['missing'].append(json.loads(data))

        
        with open('./info/'+tmp+'.json', 'w') as dump_file:
            json.dump(json_file,dump_file)
        
    return Response(status=204)

if __name__ == '__main__':
    socketio.run(app.run(host='0.0.0.0', debug=True, port=3333))