#! /usr/bin/env python

from flask import Flask
from flask import request
from flask_sqlalchemy import SQLAlchemy
from flask_restful import Resource, Api
import os, json

app = Flask(__name__)
api = Api(app)

app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///test.db'
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False

db = SQLAlchemy(app)

VALIDATOR = os.environ.get('VALIDATOR')
SECRET = os.environ.get('SECRET')


@app.teardown_appcontext
def shutdown_session(exception=None):
    db.session.remove()

# This class is for the SQLAlchemy ORM.
# There are a few more fields in the API, but I don't need them for
# this application.


class CMXData(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    apMac = db.Column(db.String(20))
    #apFloors = db.Column(db.String(50))
    #apTags = db.Column(db.String(50))
    clientMac = db.Column(db.String(20))
    seenString = db.Column(db.String(50))
    seenEpoch = db.Column(db.Integer)
    lat = db.Column(db.Float)
    lng = db.Column(db.Float)
    x = db.Column(db.Float)
    y = db.Column(db.Float)
    unc = db.Column(db.String(50))
    manufacturer = db.Column(db.String(50))
    os = db.Column(db.String(50))
    ssid = db.Column(db.String(50))
    ipv4 = db.Column(db.String(20))

    def __repr__(self):
        return '<clientMac %r>' % self.clientMac


# Query API - used by internal applications to search data out from
# the database built from the Meraki event stream.


class GetLocationForMac(Resource):
    def get(self):
        mac = request.args.get('mac')
        shared_secret = request.args.get('secret')
        if shared_secret != SECRET:
            return False # secret doesn't match the expected one. rudimentary
                         # security to reduce the incidence of unexpected DB queries.
        else:
            response = CMXData.query.filter_by(apMac = mac).first()
            print response.apMac
        # do things
        js_response = { 'lat': response.lat,
                        'long': response.lng,
                        'x': response.x,
                        'y': response.y }
        return json.dumps(js_response, ensure_ascii=False)

class DebugShowAll(Resource):
    def get(self):
        shared_secret = request.args.get('secret')
        if shared_secret != SECRET:
            return False # secret doesn't match the expected one. rudimentary
                         # security to reduce the incidence of unexpected DB queries.
        else:
            response = CMXData.query.first()
        return response.apMac


# Standard flask stuff for the get/post API for Meraki's dashboard
# to touch directly.


@app.route('/', methods=["GET", "POST"])
def index():
    if request.method == "GET":
        return VALIDATOR
    else:
        cmxJSON = request.json

        if cmxJSON['secret'] != SECRET:
            return "Invalid Secret", 403
        else:
            #print("Secret is good, proceeding.")

            if cmxJSON['version'] != '2.0':
                return "This receiver only works with CMX API 2.0", 403
            else:
                #print("version is ok, proceeding")

                #print (cmxJSON['type'])
                if cmxJSON['type'] == 'DevicesSeen':
                    for items in cmxJSON['data']['observations']:
                        #print(items);
                        data = CMXData()
                        data.apMac = cmxJSON['data']['apMac']
                        #data.apFloors = cmxJSON['data']['apFloors'] #TODO fix these I need them
                        #data.apTags = cmxJSON['data']['apTags']
                        data.clientMac = items['clientMac']
                        data.seenString = items['seenTime']
                        data.seenEpoch = items['seenEpoch']
                        data.lat = items['location']['lat']
                        data.lng = items['location']['lng']

                        try: # If there is no map in the dashboard, there is
                             # no x/y data in the event stream.
                            data.x = items['location']['x'][0]
                            data.y = items['location']['y'][0]
                        except IndexError:
                            data.x = 0.0
                            data.y = 0.0

                        data.unc = items['location']['unc']
                        data.manufacturer = items['manufacturer']
                        data.os = items['os']
                        data.ssid = items['ssid']
                        data.ipv4 = items['ipv4']
                        #print(data)
                        db.session.add(data)
                        db.session.commit()
    return "ok"


api.add_resource(GetLocationForMac, "/_get_loc_for_mac/")
api.add_resource(DebugShowAll, "/_debug_return_all")


if __name__ == '__main__':
    db.create_all()
    app.run(host='0.0.0.0', port=5001)
