from flask import Flask, Response, request, render_template
import subprocess
import os
import re
import sys
import tempfile
import io
import requests
from svg_to_hpgl import svgToHPGL

app = Flask(__name__)

title = 'Cobbled paths'

fonts_directory = 'db/'
possible_extensions = [".flf"]
etherpad = 'https://pad.constantvzw.org/p/'
prefix = 'cobbled-pad-'

# VARIABLES 4 CATALOGUE
# ------------------------------

output = {
    'stroke':  { 'ascii': ' | ' , 'fonts': [] },
    'script':  { 'ascii': ' _/' , 'fonts': [] },
    'block':   { 'ascii': '|_|' , 'fonts': [] },
    'outline': { 'ascii': '/ /' , 'fonts': [] },
    'effect':  { 'ascii': ': :' , 'fonts': [] },
    'pattern': { 'ascii': ')()' , 'fonts': [] },

    # 'fill': { 'ascii': '_/', 'fonts': {} },

    # 'directions': { 'ascii': '_/', 'fonts': {} },
    # '3d': { 'ascii': '_/', 'fonts': {} },

    # 'frame': { 'ascii': '_/', 'fonts': {} },
    # 'code': { 'ascii': '_/', 'fonts': {} },
}
databases = {
    'default': 'fonts made by the figlet developpers and given with the program, early 1993',
    'contributed': 'fonts made by figlet amateurs and submitted to the official figlet ftp, from before 1993 to 2005', 
    'jave': 'figlet font library of JavE (a free Ascii drawing Editor)',
}

# VARIABLES 4 REGEX
# ------------------------------

# all the character that svgbob understand
spec = [".", ",", "’", "'", "`", "+", "*", "o", "O", "V", "\\-", "|", "~", "_", ":", "!", "<", ">", "v", "^", "/", "\\\\", '\\”', '\\"', "(", ")", "=", "#"]
r_spec = "".join(spec)
r_nspec = "[^" + r_spec + "\€\$\s]"

# autofix regex
autofix = [
     
    # every arrowshead into lines
    [re.compile("[<{]"), "("],
    [re.compile("[>}L]"), ")"],
    [re.compile("[vV]"), "-"],
    [re.compile("[\\^]"), "-"],

    [";", ":"],
    ["7", "/"],

    [re.compile("[1Tlj\\[\\]]"), "|"],
    [re.compile("[Y]"), "+"],

    # every not in the spec --> block
    [re.compile(r_nspec), "#"],
]

# FUNCTIONS
# ------------------------------

def most_common(lst):
    return max(set(lst), key=lst.count)

def text2figlet(input, figfont):
    figlet = subprocess.run(["figlet", input, "-f", figfont, "-w", "160"], stdout = subprocess.PIPE, text=True)
    return figlet.stdout

def ascii2svg(ascii_input, weight):
    svgbob = subprocess.run(["svgbob_cli", '--stroke-width', weight], input = ascii_input, stdout = subprocess.PIPE, text=True)
    return svgbob.stdout

def ascii_autofix(ascii):
    for regex, replace in autofix:
        ascii = re.sub(regex, replace, ascii)
    return ascii

def autofix_indication(ascii):
    for regex, replace in autofix:
        # the two markers have to not appear in any regex
        ascii = re.sub(regex, "$" + replace + "€", ascii)

    ascii = re.sub("[\$]", "<span class='fix'>", ascii)
    ascii = re.sub("[\€]", "</span>", ascii)
    return ascii


# ROUTES
# ------------------------------

#  _           _           
# (_)_ __   __| | _____  __
# | | '_ \ / _` |/ _ \ \/ /
# | | | | | (_| |  __/>  < 
# |_|_| |_|\__,_|\___/_/\_\
# 
# PRESENT THE TOOL

@app.route("/")
def index():

    return render_template(
        'index.html',
        title = title)

#      _                    
#   __| |_ __ __ ___      __
#  / _` | '__/ _` \ \ /\ / /
# | (_| | | | (_| |\ V  V / 
#  \__,_|_|  \__,_| \_/\_/  
# 
# ETHERPAD 2 SVGBOB INTERFACE
# one iframe for the etherpad
# another iframe to dump the generated svg

@app.route("/draw.html")
def draw():

    params = {
        'pad': request.args.get('p') or 'default',
        'weight': request.args.get('w') or '3',
    }
    params['pad-full'] = etherpad + prefix + params['pad']

    return render_template(
        'draw.html',
        title = title,
        params = params)

# this is the route of the iframe where the svg is generated and dumped

@app.route("/drawing/<id>")
def drawing(id):

    params = {
        'pad': id or 'default',
        'weight': request.args.get('w') or '3',
    }
    params['pad-full'] = etherpad + prefix + params['pad']

    # get pad content
    print('  getting ' + params['pad-full'])
    pad_export = requests.get(params['pad-full'] + '/export/txt')
    ascii_input = pad_export.text

    # to SVG
    svg = ascii2svg(ascii_input, params['weight'])

    return render_template(
        'drawing.html',
        title = title,
        params = params,
        svg = svg)

#            _        _                        
#   ___ __ _| |_ __ _| | ___   __ _ _   _  ___ 
#  / __/ _` | __/ _` | |/ _ \ / _` | | | |/ _ \
# | (_| (_| | || (_| | | (_) | (_| | |_| |  __/
#  \___\__,_|\__\__,_|_|\___/ \__, |\__,_|\___|
#                             |___/  
# 
# FIGLET 2 SVGBOB INTERACTIVE CATALOGUE

@app.route("/catalogue.html")
def catalogue():
    
    # text and weight as get parameter
    params = {
        'text': request.args.get('t') or 'Echoes',
        'weight': request.args.get('w') or '3',
    }

    # walk in the figlet font directory
    for root, dirs, files in os.walk(fonts_directory):
        for name in files:

            (basename, ext) = os.path.splitext(name)
            if  ext in possible_extensions:

                figfont = os.path.join(root, name)
                print(figfont)

                # get font category out of last folder
                catalogue = root.split('/')[-2]
                type = root.split('/')[-1]
                if type in output:
                
                    f = {}
                    output[type]['fonts'].append(f)
                    f['name'] = name
                    f['catalogue'] = catalogue
                    f['ascii'] = text2figlet(params['text'], figfont)
                    f['svg'] = ascii2svg(f['ascii'], params['weight'])
                    
                    # regex auto_fix
                    f['ascii_fix'] = ascii_autofix(f['ascii'])

                    if f['ascii'] != f['ascii_fix']:
                        f['autofix'] = True
                        f['ascii_fix_indication'] = autofix_indication(f['ascii_fix'])
                        f['svg_fix'] = ascii2svg(f['ascii_fix'], params['weight'])

    return render_template(
        'catalogue.html',
        title = title,
        databases = databases,
        output = output,
        params = params)


# ----------------------------------------------------------

def make_svg ():
    return ''

@app.route('/hpgl/<id>')
def hpgl (id):
    params = {
        'pad': id or 'default',
        'weight': request.args.get('w') or '3',
    }
    params['pad-full'] = etherpad + prefix + params['pad']

    # get pad content
    print('  getting ' + params['pad-full'])
    pad_export = requests.get(params['pad-full'] + '/export/txt')
    ascii_input = pad_export.text

    # to SVG
    svg = ascii2svg(ascii_input, params['weight'])

    # store as a temporary file
    (svg_file, svg_path) = tempfile.mkstemp('.svg')


    with open(svg_file, 'w') as svg_handle:
        svg_handle.write(svg)

    # transform to hpgl
    hpgl = svgToHPGL(svg_path)

    # remove tmp file
    os.remove(svg_path)

    r = Response(hpgl, mimetype='application/hpgl')
    r.headers.extend({
        'Content-Disposition': 'attachment; filename="cobbled-paths.hpgl"'
    })
    return r

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