# basic setup for almost any flask app

# required dependencies
from flask import Flask, request, make_response, jsonify
from flask_restful import Resource, Api
from pymongo import MongoClient
from bson.objectid import ObjectId
from utils.mongo_json_encoder import JSONEncoder

# create flask instance
app = Flask(__name__)
# connect to local MongoDB
mongo = MongoClient('localhost', 27017)
# specify database to store data, assigned to app.db to
# communicate with database
app.db = mongo.develop_database
# create flask_restful API (communicate over HTTP for server data over web)
# using flask_restful library provides specific fortmat
# for resources in our app
api = Api(app)


class MyObject(Resource):
    def post(self):
        # access the JSON(readable format data structure)
        # provided by client through the variable
        new_myobject = request.json
        # access the collection to store new objects
        # usually one collection per entity type (eg. User, Trips)
        myobject_collection = app.db.myobjects
        # insert JSON document into the collection
        result = myobject_collection.insert_one(new_myobject)
        # after inserting object, we automatically retrieve the result
        # (result will be used to fetch inserted document from collection using
        # following find_one method)
        # find one method uses a dictionary to output filter criteria for
        # document (by specific ID) MongoDB maintains IDs which contain
        # unique IDs for documents in database
        myobject = myobject_collection.find_one({"_id": ObjectID(result.insert_id)})
        # returns id (generated by MongoDB) of inser object for retrieval later
        return myobject

    def get(self, myobject_id):
        # refernce to database from which client is requesting access
        myobject_collection = app.db.myobjects
        # build a query based on myobject_id
        myobject = myobject_collection.find_one({"_id": ObjectID(myobject_id)})
        # how to handle is object is found or not
        if myobject is None:
            response = jsonify(data=[])
            response.status_code = 404
            return response
        else:
            return myobject

# mapping between resources and routes; a route is URL called by client app
# add resource to API
api.add_resource(MyObject, '/myobject/', '/myobject/<string:myobject_id>')
# first parameter is the resource to map to
# second and third are URLs that mao to the resource
# one operates on the collection of myobjects
# the other operates on a specific myobjects (object id)
# this line tells server which class to call when URL requested by client app
# HTTP verb of the request tells which method of the class to call


# configure custom JSON serializer for flask_restful
@api.representation('application/json')
def output_json(data, code, headers=None):
    resp = make_response(JSONEncoder().encode(data), code)
    resp.headers.extend(headers or {})
# JSON encoder turns python objects into JSON text representation
# default serializer doesnt know how to handle MongoDB ObjectID
# ObjectID is a MongoDB specific type and not a string that default
# serilization can use
# with code, any MIME type 'application/json' gets custom encoding
# encoder file is last imported dependency at top


# start flask server
if __name__ == '__main__':
    # debug mode to find request exceptions
    app.config['TRAP_BAD_REQUEST_ERRORS'] = True
    app.run(deubg=True)
