from flask import Flask, render_template, request, redirect, url_for
from werkzeug.utils import secure_filename
import yaml
from yaml.loader import SafeLoader

import os
import json
from pathlib import Path


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/workbook')


def create_instrument(name, description, params, sockets, panel):
    slug = secure_filename(name)
    os.mkdir(f'static/instruments/{slug}')
    os.mkdir(f'static/instruments/{slug}/patches')
    os.mkdir(f'static/instruments/{slug}/samples')
    instrument = {
        "name": name,
        "slug": slug,
        "description": description,
        "params": params,
        "sockets": sockets
    }

    with open(f'static/instruments/{slug}/model.yml', 'w') as f:
        yaml.dump(instrument, f, sort_keys=False)

    panel.save(f'static/instruments/{slug}/panel.svg')


@app.route("/")
def workbook():
    return render_template('workbook.html')


@app.route("/<slug>")
def page(slug):
    return render_template(f'{slug}.html')

@app.route("/instruments")
def instruments():
 
    instruments = []

    for filename in os.listdir('static/instruments'):
        with open(f'static/instruments/{filename}/model.yml') as f:
            instrument = yaml.load(f, Loader=SafeLoader)
            instruments.append(instrument)

    return render_template('instruments.html', instruments=instruments)

@app.route("/instruments/<instrument>")
def patches(instrument):


    with open(f'static/instruments/{instrument}/panel.svg') as f:
        panel = f.read()


    patches = []
    for filename in os.listdir(f'static/instruments/{instrument}/patches'):
        with open(f'static/instruments/{instrument}/patches/{filename}/{filename}.yml') as f:
            patch = yaml.load(f, Loader=SafeLoader)
            patches.append(patch)

    return render_template('patches.html', instrument=instrument, patches=patches, panel=panel)


@app.route("/instruments/add", methods=['GET', 'POST'])    
def add_instrument():
    if request.method == 'POST':
        
        name = request.form.get('name')
        description = request.form.get('description')
        
        params = json.loads(request.form.get('params'))
        sockets = json.loads(request.form.get('sockets'))
        
        panel = request.files['panel']

        create_instrument(name, description, params, sockets, panel)
        return redirect(url_for('instruments'))

    return render_template('add_instrument.html')

@app.route("/instruments/<instrument>/add", methods=['GET', 'POST'])
def add_patch(instrument):

    if request.method == 'POST':
        patch = request.form.to_dict()
        patch = {k: v for k, v in patch.items() if v}
        
        slug = secure_filename(patch["name"])
        patch['slug'] = slug
    
        Path(f'static/instruments/{instrument}/patches/{slug}').mkdir()
        with open(f'static/instruments/{instrument}/patches/{slug}/{slug}.yml', 'w') as f:
            yaml.dump(patch, f)
        return redirect(url_for('patches', instrument=instrument))

    with open(f'static/instruments/{instrument}/panel.svg') as f:
        panel = f.read()

    with open(f'static/instruments/{instrument}/model.yml') as f:
        instrument = yaml.load(f, Loader=SafeLoader)


    return render_template('add_patch.html', instrument=instrument, panel=panel)


@app.route("/instruments/<instrument>/<name>", methods=['GET', 'POST'])
def patch(instrument, name):
    
    if request.method == 'POST':
        
        file = request.files['snippet']

        if file:
            Path(f'static/instruments/{instrument}/patches/{name}/snippets').mkdir(exist_ok=True)
            filename = secure_filename(file.filename)
            file.save(os.path.join(f'static/instruments/{instrument}/patches/{name}/snippets', filename))
            # description = request.form['description']
            redirect(url_for('patch', instrument=instrument, name=name))
        
    snippets = []
    
    if os.path.exists(f'static/instruments/{instrument}/patches/{name}/snippets'):
        for filename in os.listdir(f'static/instruments/{instrument}/patches/{name}/snippets'):
            snippets.append(filename)

    with open(f'static/instruments/{instrument}/panel.svg') as f:
        panel = f.read()

    with open(f'static/instruments/{instrument}/patches/{name}/{name}.yml') as f:
        patch = yaml.load(f, Loader=SafeLoader)

    with open(f'static/instruments/{instrument}/model.yml') as f:
        instrument = yaml.load(f, Loader=SafeLoader)


    return render_template('patch.html', instrument=instrument, patch=patch, panel=panel, snippets=snippets)



app.run(port=3146, debug=True)