from db import DB
from flask import Flask, Response, redirect, request, send_file
import json
import re

# We use HTTP 307 mainly so the redirection can change. This also
# allows us to log the use of links.

# TODO:
#
# - Thread safe external storage of db.
# - Use http://fontawesome.io/ icons in Web UI.

app = Flask(__name__)

app.config['DEBUG'] = True

db = None


@app.before_first_request
def _run_on_start():
    global db
    db = DB("db.json")


#
# Web UI -- single page app that lets a user manage existing names,
# create new names, see stats about what names are used, etc.
#

@app.route("/")
def home():
    return send_file('static/index.html')


#
# The actual redirector.
#

@app.route("/<name>/", defaults={'rest': None})
@app.route("/<name>/<path:rest>")
def redirection(name, rest):
    name = ''.join(filter(str.isalnum, name))
    args = rest.split('/') if rest else []
    if db.has_pattern(name, len(args)):
        return redirect(db.get_pattern(name, len(args)).format(*args))
    else:
        return send_file('static/index.html')


#
# API - Restful API for CRUDing links.
#

@app.route("/_/", methods=['GET'])
def get_all():
    return json_response(db.jsonify())


@app.route("/_/<name>", methods=['GET'])
def get_name(name):
    if db.has_name(name):
        return json_response(db.jsonify_item(name))
    else:
        return json_response({}, 404)


@app.route("/_/<name>", methods=['DELETE'])
def delete_name(name):
    if db.has_name(name):
        db.delete_name(name)
        return json_response({})
    else:
        return json_response({"error": "No such name"}, 404)


@app.route("/_/<name>/<path:pattern>", methods=['PUT'])
def put_pattern(name, pattern):
    n = count_args(pattern)
    if n is None:
        # FIXME: there's more well-formedness checking we could do
        # on the pattern.
        return json_response({"error": "Mixed arg types"}, 400)
    else:
        db.set_pattern(name, n, pattern)
        return json_response(db.jsonify_item(name))


@app.route("/_/<name>/<int:n>", methods=['DELETE'])
def delete_pattern(name, n):
    if db.get_pattern(name, n):
        db.delete_pattern(name, n)
        return json_response(db.jsonify_item(name))
    else:
        return json_response({"error": "No such pattern"}, 404)


#
# Utilities
#

def json_response(js, code=200):
    return Response(json.dumps(js), status=code, mimetype='application/json')


def count_args(pattern):
    numbered_pats = re.findall('{\d+}', pattern)
    auto_pats = re.findall('{}', pattern)

    if numbered_pats and auto_pats:
        return None  # Poor man's Maybe
    elif numbered_pats:
        return 1 + max(int(x.strip('{}')) for x in numbered_pats)
    else:
        return len(auto_pats)

@@ -75,16 +75,32 @@
 nd_file%0A
+from flask.json 
 import j
@@ -102,16 +102,19 @@
 ort json
+ify
 %0Aimport 
@@ -271,16 +271,69 @@
  of db.%0A
+# - Change REST API so patterns are created via POST%0A
 # - Use 
@@ -1233,33 +1233,27 @@
  return json
-_response
+ify
 (db.jsonify(
@@ -1359,33 +1359,27 @@
  return json
-_response
+ify
 (db.jsonify_
@@ -1423,26 +1423,20 @@
 json
-_response
+ify
 (%7B%7D
+)
 , 404
-)
 %0A%0A%0A@
@@ -1575,25 +1575,19 @@
 urn json
-_response
+ify
 (%7B%7D)%0A   
@@ -1608,33 +1608,27 @@
  return json
-_response
+ify
 (%7B%22error%22: %22
@@ -1641,22 +1641,22 @@
 h name%22%7D
+)
 , 404
-)
 %0A%0A%0A@app.
@@ -1892,33 +1892,27 @@
  return json
-_response
+ify
 (%7B%22error%22: %22
@@ -1932,14 +1932,14 @@
 es%22%7D
+)
 , 400
-)
 %0A   
@@ -2001,33 +2001,27 @@
  return json
-_response
+ify
 (db.jsonify_
@@ -2201,25 +2201,19 @@
 urn json
-_response
+ify
 (db.json
@@ -2257,25 +2257,19 @@
 urn json
-_response
+ify
 (%7B%22error
@@ -2293,14 +2293,14 @@
 rn%22%7D
+)
 , 404
-)
 %0A%0A%0A#
@@ -2319,121 +2319,8 @@
 %0A#%0A%0A
-def json_response(js, code=200):%0A    return Response(json.dumps(js), status=code, mimetype='application/json')%0A%0A%0A
 def 

Use Flask native json response method.