from flask import g
from flask import request
from flask import json
import flask
import os
from functools import wraps
import sqlite3

#TODO http://blog.miguelgrinberg.com/post/designing-a-restful-api-using-flask-restful
#TODO clean up imports, modularize

app = flask.Flask(__name__)
DATABASE = 'todo.db'


from datetime import timedelta
from flask import make_response, request, current_app
from functools import update_wrapper


def crossdomain(origin=None, methods=None, headers=None,
                max_age=21600, attach_to_all=True,
                automatic_options=True):
    if methods is not None:
        methods = ', '.join(sorted(x.upper() for x in methods))
    if headers is not None and not isinstance(headers, basestring):
        headers = ', '.join(x.upper() for x in headers)
    if not isinstance(origin, basestring):
        origin = ', '.join(origin)
    if isinstance(max_age, timedelta):
        max_age = max_age.total_seconds()

    def get_methods():
        if methods is not None:
            return methods
        options_resp = current_app.make_default_options_response()
        return options_resp.headers['allow']

    def decorator(f):
        def wrapped_function(*args, **kwargs):
            
            if automatic_options and (request.method == 'OPTIONS'): # or request.method == 'DELETE'):
                resp = current_app.make_default_options_response()
            
            else:
                resp = make_response(f(*args, **kwargs))

            if not attach_to_all and request.method != 'OPTIONS': # and request.method != 'DELETE':
                return resp

            h = resp.headers

            h['Access-Control-Allow-Origin'] = origin
            h['Access-Control-Allow-Methods'] = get_methods()
            h['Access-Control-Max-Age'] = str(max_age)
            if headers is not None:
                h['Access-Control-Allow-Headers'] = headers
            return resp

        f.provide_automatic_options = False
        return update_wrapper(wrapped_function, f)
    return decorator

def connect_db():
    return sqlite3.connect(DATABASE)

@app.before_request
def before_request():
    g.db = connect_db()

    if request.method == 'OPTIONS':
        resp = app.make_default_options_response()

        headers = None
        if 'ACCESS_CONTROL_REQUEST_HEADERS' in request.headers:
            headers = request.headers['ACCESS_CONTROL_REQUEST_HEADERS']

        h = resp.headers
        # Allow the origin which made the XHR
        h['Access-Control-Allow-Origin'] = request.headers['Origin']
        # Allow the actual method
        h['Access-Control-Allow-Methods'] = request.headers['Access-Control-Request-Method']
        # Allow for 10 seconds
        h['Access-Control-Max-Age'] = "10"

        # We also keep current headers
        if headers is not None:
            h['Access-Control-Allow-Headers'] = headers
        return resp

@app.after_request
def after_request(response):
    g.db.close()
    h = response.headers
    # Allow crossdomain for other HTTP Verbs
    if request.method != 'OPTIONS' and 'Origin' in request.headers:
        h['Access-Control-Allow-Origin'] = request.headers['Origin']
    return response

'''
REST methods
------------------------------------------------------------
'''

@app.route("/api/todos", methods=['GET'])
@crossdomain(origin='*')
def getData():
    #cur = g.db.execute("SELECT id, title, (CASE WHEN is_completed = 1 THEN 'true' ELSE 'false' END) AS is_completed FROM todos")
    cur = g.db.execute("SELECT id, title, is_completed FROM todos")
    rv = [dict((cur.description[idx][0], value)
                for idx, value in enumerate(row)) for row in cur.fetchall()]
    return json.dumps(rv)


@app.route("/api/todos", methods=['POST', 'OPTIONS'])
@crossdomain(origin='*')
def postData():
    c = g.db.execute("INSERT INTO todos ('is_completed', 'title') VALUES (?, ?)", (flask.request.json['isCompleted'], flask.request.json['title']))
    g.db.commit()
    # insert the new ID and return the data
    flask.request.json['id'] = c.lastrowid
    return json.dumps(flask.request.json)


@app.route("/api/todos/<id>", methods=['DELETE'])
@crossdomain(origin='*')
def deleteData(id):
    app.logger.debug(id)
    c = g.db.execute("DELETE FROM todos WHERE id = ?", id)
    g.db.commit()
    return json.dumps(flask.request.json)


@app.route("/api/todos/<id>", methods=['PUT'])
@crossdomain(origin='*')
def updateData(id):
    app.logger.debug(id)
    c = g.db.execute("UPDATE todos SET 'is_completed' = ?, 'title' = ? WHERE id = ?", (flask.request.json['isCompleted'], flask.request.json['title'], id))
    g.db.commit()
    #return json.dumps(flask.request.json)
    return ""

'''
@app.route("/api/todos/<id>", methods=['PATCH'])
@crossdomain(origin='*')
def updateData(id):
    app.logger.debug(id)
    c = g.db.execute("UPDATE todos SET 'is_completed' = ?, 'title' = ? WHERE id = ?", (flask.request.json['isCompleted'], flask.request.json['title'], id))
    g.db.commit()
    return json.dumps(flask.request.json)
'''

if __name__ == "__main__":
	# Bind to PORT if defined, otherwise default to 5000.
	port = int(os.environ.get('PORT', 5000))
	app.run(host='0.0.0.0', port=port, debug=True)