import os
from bson import json_util
from flask import Flask, request
from flask_pymongo import PyMongo

app = Flask(__name__)
app.config["MONGO_URI"] = "mongodb://mongo:27017/entities"
mongo = PyMongo(app)

CAR1_SV = int(os.environ.get('DSE2021_CAR1_SV', 130))
CAR2_SV = int(os.environ.get('DSE2021_CAR2_SV', 130))
CAR3_SV = int(os.environ.get('DSE2021_CAR3_SV', 130))

CAR1_SD = int(os.environ.get('DSE2021_CAR1_SD', 300))
CAR2_SD = int(os.environ.get('DSE2021_CAR2_SD', 500))
CAR3_SD = int(os.environ.get('DSE2021_CAR3_SD', 400))

CAR1_ST = int(os.environ.get('DSE2021_CAR1_ST', 10))
CAR2_ST = int(os.environ.get('DSE2021_CAR2_ST', 15))
CAR3_ST = int(os.environ.get('DSE2021_CAR3_ST', 25))

TL1_R = int(os.environ.get('DSE2021_TL1_R', 2000))
TL2_R = int(os.environ.get('DSE2021_TL2_R', 800))
TL3_R = int(os.environ.get('DSE2021_TL3_R', 1000))

mongo.db.trafficLights.update_one({"id": "1"}, {"$set": {"range": TL1_R}})
mongo.db.trafficLights.update_one({"id": "2"}, {"$set": {"range": TL2_R}})
mongo.db.trafficLights.update_one({"id": "3"}, {"$set": {"range": TL3_R}})

mongo.db.cars.update_one({"vin": "SCBFR7ZA5CC072256"}, {"$set": {"startingVelocity": CAR1_SV}})
mongo.db.cars.update_one({"vin": "5GZCZ43D13S812715"}, {"$set": {"startingVelocity": CAR2_SV}})
mongo.db.cars.update_one({"vin": "5GZCZ43D13S812716"}, {"$set": {"startingVelocity": CAR3_SV}})

mongo.db.cars.update_one({"vin": "SCBFR7ZA5CC072256"}, {"$set": {"startingDistance": CAR1_SD}})
mongo.db.cars.update_one({"vin": "5GZCZ43D13S812715"}, {"$set": {"startingDistance": CAR2_SD}})
mongo.db.cars.update_one({"vin": "5GZCZ43D13S812716"}, {"$set": {"startingDistance": CAR3_SD}})

mongo.db.cars.update_one({"vin": "SCBFR7ZA5CC072256"}, {"$set": {"startingTime": CAR1_ST}})
mongo.db.cars.update_one({"vin": "5GZCZ43D13S812715"}, {"$set": {"startingTime": CAR2_ST}})
mongo.db.cars.update_one({"vin": "5GZCZ43D13S812716"}, {"$set": {"startingTime": CAR3_ST}})


@app.route('/api/v1/resources/cars', methods=['GET'])
def get_cars():
    """
    Get all cars stored in entity ident database or filter by vin.
    """
    query_parameters = request.args
    vin = query_parameters.get('vin')

    if vin is not None:
        cars = [car for car in mongo.db.cars.find({'vin': vin})]
    else:
        cars = [car for car in mongo.db.cars.find({})]

    return json_util.dumps({'cursor': cars})


@app.route('/api/v1/resources/traffic_lights', methods=['GET'])
def get_traffic_lights():
    """
    Get all traffic lights stored in entity ident database or filter by id.
    """

    query_parameters = request.args
    tl_id = query_parameters.get('id')

    if tl_id is not None:
        traffic_lights = [traffic_light for traffic_light in
                          mongo.db.trafficLights.find({'id': tl_id})]
    else:
        traffic_lights = [traffic_light for traffic_light in mongo.db.trafficLights.find({})]

    return json_util.dumps({'cursor': traffic_lights})


@app.route('/api/v1/resources/traffic_lights_geo', methods=['GET'])
def get_traffic_lights_geo():
    """
    Get traffic light which is in range and south of coordinates (lat, lon).
    """

    query_parameters = request.args

    lat = float(query_parameters.get('lat'))
    lon = float(query_parameters.get('lon'))

    traffic_lights = [
        traffic_light for traffic_light in
        mongo.db.trafficLights.aggregate([
            {"$geoNear": {
                "near": {
                    "type": "Point",
                    "coordinates": [lon, lat]
                },
                "spherical": True,
                "distanceField": "calculatedRange"
            }},
            {"$redact": {
                "$cond": {
                    "if": {
                        "$lte": ["$calculatedRange", "$range"]
                    },
                    "then": "$$KEEP",
                    "else": "$$PRUNE"
                }
            }}
        ]
        )
        if lat < traffic_light['location'][1]
    ]

    return json_util.dumps({'cursor': traffic_lights[:1]})


if __name__ == '__main__':
    app.run('0.0.0.0', 5002)
