from flask import Flask, request, redirect, url_for, jsonify, session, render_template, abort
from functools import wraps
import requests
import urllib.parse
import os
import json
import sys


SETTINGS_FILENAME = 'loco.json'
if not os.path.exists(SETTINGS_FILENAME):
    print("Cannot find settings file `{}`".format(SETTINGS_FILENAME))
    sys.exit(1)
app_settings = json.load(open(SETTINGS_FILENAME))

app = Flask(__name__)
app.config['RC_API_URI'] = 'http://www.recurse.com/api/v1'
app.config['RC_OAUTH_AUTH_URI'] = 'https://www.recurse.com/oauth/authorize'
app.config['RC_OAUTH_TOKEN_URI'] = 'https://www.recurse.com/oauth/token'
app.config['RC_OAUTH_CLIENT_ID'] = app_settings['client_id']
app.config['RC_OAUTH_CLIENT_SECRET'] = app_settings['client_secret']
app.config['RC_OAUTH_CLIENT_REDIRECT_URI'] = app_settings['redirect_uri']
app.config['SESSION_SECRET'] = app_settings['session_secret']
app.secret_key = app.config['SESSION_SECRET']

# DB Stuff
from flask_sqlalchemy import SQLAlchemy
from sqlalchemy.ext.declarative import declarative_base
from geoalchemy2.types import Geometry
from geoalchemy2.elements import WKTElement, WKBElement
from geoalchemy2.shape import to_shape


# TODO: Read database credentials from file, env variables etc.
app.config['SQLALCHEMY_DATABASE_URI'] = app_settings["db_uri"]
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False

db = SQLAlchemy(app)

class RcLoco(db.Model):
    __tablename__ = 'locos'
    id = db.Column(db.BigInteger, primary_key=True)
    name = db.Column(db.String(256))
    image = db.Column(db.Text)
    address = db.Column(db.Text)
    coords = db.Column(Geometry(geometry_type='POINT', srid=4326))
    is_shared = db.Column(db.Boolean, default=False)


class ModelSerializer(json.JSONEncoder):

    OMITTED_KEYS = {'_sa_instance_state'}

    def default(self, o):
        try:
            d = {}
            for k, v in o.__dict__.items():
                if k not in self.OMITTED_KEYS:
                    if k == "coords" and isinstance(v, WKTElement) \
                       or isinstance(v, WKBElement):
                        lat, lng = list(to_shape(v).coords)[0]
                        d['lat'] = lat
                        d['lng'] = lng
                    else:
                        d[k] = v
            return d
        except AttributeError:
            return {}


# App

sessions = {}


def check_authentication(method):
    @wraps(method)
    def auth_checked(*args, **kwargs):
        if 'user' not in session or session['user'] not in sessions:
            params = {
                "client_id": app.config['RC_OAUTH_CLIENT_ID'],
                "redirect_uri": app.config['RC_OAUTH_CLIENT_REDIRECT_URI'],
                "response_type": 'code'