"""Handles data storage for Users, rides and requests
"""
# pylint: disable=E1101
import datetime

from flask import make_response, jsonify, current_app
from werkzeug.security import generate_password_hash
import psycopg2
import config
from databasesetup import db


class User():
    """Contains user columns and methods to add, update and delete a user"""


    def __init__(self, username, email, password, admin):
        self.username = username
        self.email = email
        self.password = generate_password_hash(password, method='sha256')
        if admin == True:
            self.admin = '1'
        else:
            self.admin = '0'

        new_user = "INSERT INTO users (username, email, password, admin) VALUES " \
                    "('" + self.username + "', '" + self.email + "', '" + self.password + "', '" + self.admin + "')"
        db_cursor = db.con()
        db_cursor.execute(new_user)
        db.commit()


    @staticmethod              
    def update_user(user_id, username, email, password, admin):
        """Updates user information"""
        try:
            db_cursor = db.con()
            db_cursor.execute("UPDATE users SET username=%s, email=%s, password=%s, admin=%s WHERE user_id=%s",
                                (username, email, password, admin, user_id))
            db.commit()
            return make_response(jsonify({"message" : "user has been successfully updated"}), 200)
        except:
            return make_response(jsonify({"message" : "user does not exist"}), 404)

    @staticmethod
    def delete_user(user_id):
        """Deletes a user"""
        try:
            db_cursor = db.con()
            db_cursor.execute("DELETE FROM users WHERE user_id=%s", (user_id,))
            db.commit()
            return make_response(jsonify({"message" : "user has been successfully deleted"}), 200)
        except:
            return make_response(jsonify({"message" : "user does not exists"}), 404)

    @staticmethod
    def get_user(user_id):
        """Gets a particular user"""
        db_cursor = db.con()
        db_cursor.execute("SELECT * FROM users WHERE user_id=%s", (user_id,))
        user = db_cursor.fetchall()

        if user != []:
            user=user[0]
            info = {user[0] : {"email": user[1],
                                "username": user[2],
                                "admin": user[4]}}
            return make_response(jsonify({"profile" : info}), 200)
        return make_response(jsonify({"message" : "user does not exists"}), 404)

    @staticmethod
    def get_all_users():
        """Gets all users"""
        db_cursor = db.con()
        db_cursor.execute("SELECT * FROM users")
        users = db_cursor.fetchall()

        all_users = []
        for user in users:
            info = {user[0] : {"email": user[1],
                                "username": user[2],
                                "admin": user[4]}}
            all_users.append(info)
        return make_response(jsonify({"All users" : all_users}), 200)


class Ride():
    """Contains ride columns and methods to add, update and delete a ride"""


    def __init__(self, ride, driver_id, departuretime, numberplate, maximum, status):
        self.ride = ride
        self.driver_id = driver_id
        self.departuretime = departuretime
        self.numberplate = numberplate
        self.maximum = maximum
        self.status = status
        new_ride = "INSERT INTO rides (ride, driver_id, departuretime, numberplate, maximum, status) VALUES " \
                    "('" + self.ride + "', '" + self.driver_id + "', '" + self.departuretime + "', '" + self.numberplate + "','" + self.maximum + "','" + self.status + "' )"
        db_cursor = db.con()
        db_cursor.execute(new_ride)
        db.commit()

    @classmethod
    def create_ride(cls, ride, driver_id, departuretime, numberplate, maximum, status="pending"):
        """Creates a new ride"""

        cls(ride, driver_id, departuretime, numberplate, maximum, status)
        return make_response(jsonify({"message" : "ride has been successfully created"}), 201)

    @staticmethod
    def update_ride(ride_id, ride, driver_id, departuretime, numberplate,
                    maximum):
        """Updates ride information"""
        try:
            db_cursor = db.con()
            db_cursor.execute("UPDATE rides SET ride=%s, driver_id=%s, departuretime=%s, numberplate=%s, maximum=%s WHERE ride_id=%s",
                                  (ride, driver_id, departuretime, numberplate, maximum, ride_id))
            db.commit()
            return make_response(jsonify({"message" : "user has been successfully updated"}), 200)
        except:
            return make_response(jsonify({"message" : "user does not exist"}), 404)


    @staticmethod
    def start_ride(ride_id, driver_id):
        """starts a ride"""
        db_cursor = db.con()
        db_cursor.execute("SELECT * FROM rides WHERE ride_id=%s", (ride_id,))
        ride = db_cursor.fetchall()
        if ride != []:
            ride = ride[0]
            if int(ride[2]) == driver_id:
                db_cursor.execute("UPDATE rides SET status=%s WHERE ride_id=%s", ("given", ride_id,))
                db_cursor.execute("UPDATE request SET status=%s WHERE ride_id=%s and accepted=%s", ("taken", ride_id, True,))
                db_cursor.execute("UPDATE request SET status=%s WHERE ride_id=%s and accepted=%s", ("rejected", ride_id, False,))
                db.commit()

                return {"message" : "ride has started"}

            return {"message" : "The ride you want to start is not your ride."}

        return {"message" : "ride does not exist"}

    @staticmethod
    def delete_ride(ride_id):
        """Deletes a ride"""
        db_cursor = db.con()
        db_cursor.execute("SELECT * FROM rides")
        rides = db_cursor.fetchall()

        for ride in rides:
            if ride[0] == ride_id:
                db_cursor.execute("DELETE FROM rides WHERE ride_id=%s", (ride_id,))
                db.commit()

                return make_response(jsonify({"message" : "ride has been successfully deleted"}), 200)
        return make_response(jsonify({"message" : "user does not exists"}), 404)

    @staticmethod
    def get_ride(ride_id):
        """Gets a particular ride"""
        db_cursor = db.con()
        db_cursor.execute("SELECT * FROM rides WHERE ride_id=%s", (ride_id,))
        ride = db_cursor.fetchall()

        if ride != []:
            ride=ride[0]
            info = {ride[0] : {"ride": ride[1],
                                "driver_id": ride[2],
                                "departure_time": ride[3],
                                "cost": ride[4],
                                "maximum": ride[5],
                                "status": ride[6]}}
            return make_response(jsonify({"ride" : info}), 200)
        return make_response(jsonify({"message" : "ride does not exists"}), 404)
        
    @staticmethod
    def get_all_rides():
        """Gets all rides"""
        db_cursor = db.con()
        db_cursor.execute("SELECT * FROM rides")
        rides = db_cursor.fetchall()
        all_rides = []
        for ride in rides:
            info = {ride[0] : {"ride": ride[1],
                                "driver_id": ride[2],
                                "departure_time": ride[3],
                                "cost": ride[4],
                                "maximum": ride[5],
                                "status": ride[6]}}
            all_rides.append(info)
        return make_response(jsonify({"All rides" : all_rides}), 200)


class Request:
    """Contains menu columns and methods to add, update and delete a request"""


    def __init__(self, ride_id, user_id, accepted, status):
        self.ride_id = str(ride_id)
        self.user_id = str(user_id)
        self.accepted = accepted
        self.status = status
        new_request = "INSERT INTO request (ride_id, user_id, accepted, status) VALUES " \
                    "('" + self.ride_id + "', '" + self.user_id + "', '" + '0' + "', '" + self.status + "')"
        db_cursor = db.con()
        db_cursor.execute(new_request)
        db.commit()

    @classmethod
    def request_ride(cls, ride_id, user_id, accepted=False, status="pending"):
        """Creates a new request"""
        db_cursor = db.con()
        db_cursor.execute("SELECT status FROM rides WHERE ride_id=%s", (ride_id,))
        ride = db_cursor.fetchone()
        if ride[0] == "pending":
            cls(ride_id, user_id, accepted, status)
            return make_response(jsonify({"message" : "request has been successfully sent for approval"}), 201)
        return make_response(jsonify({"message" : "ride is already given"}), 400)

    @staticmethod
    def delete_request(request_id):
        """Deletes a request"""

        try:

            db_cursor = db.con()
            db_cursor.execute("DELETE FROM request WHERE request_id=%s", (request_id,))
            db.commit()

            return make_response(jsonify({"message" : "ride has been successfully deleted"}), 200)
        except:
            return make_response(jsonify({"message" : "the specified request does not exist in requests"}), 404)

    @staticmethod
    def accept_request(request_id):
        """Accepts request"""

        try:
            db_cursor = db.con()
            db_cursor.execute("UPDATE request SET accepted=%s WHERE request_id=%s", (True, request_id))
            db.commit()
            return make_response(jsonify({"message" : "request has been successfully accepted"}), 200)
        except KeyError:
            return make_response(jsonify({"message" : "the specified request does not exist in requests"}), 404)


    @staticmethod
    def get_requests(request_id):
        """Gets a particular request"""
        db_cursor = db.con()
        db_cursor.execute("SELECT * FROM request WHERE request_id=%s", (request_id,))
        request = db_cursor.fetchone()

        if request != None:
            info = {request[0] : {"user_id": request[1],
                                        "ride_id": request[2],
                                        "status": request[3],
                                        "accepted": request[4]}}
            return make_response(jsonify({"request" : info}), 200)
        return make_response(jsonify({"message" : "request does not exists"}), 404)

    @staticmethod
    def get_particular_riderequests(ride_id):
        db_cursor = db.con()
        db_cursor.execute("SELECT * FROM request WHERE ride_id=%s", (ride_id,))
        requests = db_cursor.fetchall()

        if requests != []:
            ride_requests = []
            for request in requests:
                info = {request[0] : {"user_id": request[1],
                                        "ride_id": request[2],
                                        "status": request[3],
                                        "accepted": request[4]}}
                ride_requests.append(info)
            return make_response(jsonify({"ride_requests" : ride_requests}), 200)
        return make_response(jsonify({"message" : "ride does not exists"}), 404)

    @staticmethod
    def get_all_requests():
        """Gets all request"""
        db_cursor = db.con()
        db_cursor.execute("SELECT * FROM request")
        requests = db_cursor.fetchall()

        ride_requests = []
        for request in requests:
            info = {request[0] : {"user_id": request[1],
                                    "ride_id": request[2],
                                    "status": request[3],
                                    "accepted": request[4]}}
            ride_requests.append(info)
        return make_response(jsonify({"ride_requests" : ride_requests}), 200)

class Relation:
    """Contains method to get driver_id and maximum from a requested ride"""

    @staticmethod
    def get_driver_id(request_id):
        """Gets all request"""
        db_cursor = db.con()
        db_cursor.execute("SELECT * FROM request WHERE request_id=%s", (request_id,))
        request = db_cursor.fetchone()

        ride_id = str(request[2])
        db_cursor.execute("SELECT driver_id FROM rides WHERE ride_id=%s", (ride_id,))
        driver_id = db_cursor.fetchone()
        if driver_id == None:
            return make_response(jsonify({"message" : "ride does not exists"}), 404)
        driver_id = driver_id[0]

        return int(driver_id)
    
    @staticmethod
    def get_maximum(request_id):
        """Gets all request"""
        db_cursor = db.con()
        db_cursor.execute("SELECT * FROM request WHERE request_id=%s", (str(request_id),))
        request = db_cursor.fetchone()

        db_cursor.execute("SELECT maximum FROM rides WHERE ride_id=%s", (request[2],))
        maximum = db_cursor.fetchone()
        maximum = maximum[0]

        return maximum

[((20, 24, 20, 73), 'werkzeug.security.generate_password_hash', 'generate_password_hash', (), '', False, 'from werkzeug.security import generate_password_hash\n'), ((28, 20, 28, 28), 'databasesetup.db.con', 'db.con', ({}, {}), '()', False, 'from databasesetup import db\n'), ((30, 8, 30, 19), 'databasesetup.db.commit', 'db.commit', ({}, {}), '()', False, 'from databasesetup import db\n'), ((59, 20, 59, 28), 'databasesetup.db.con', 'db.con', ({}, {}), '()', False, 'from databasesetup import db\n'), ((74, 20, 74, 28), 'databasesetup.db.con', 'db.con', ({}, {}), '()', False, 'from databasesetup import db\n'), ((100, 20, 100, 28), 'databasesetup.db.con', 'db.con', ({}, {}), '()', False, 'from databasesetup import db\n'), ((102, 8, 102, 19), 'databasesetup.db.commit', 'db.commit', ({}, {}), '()', False, 'from databasesetup import db\n'), ((128, 20, 128, 28), 'databasesetup.db.con', 'db.con', ({}, {}), '()', False, 'from databasesetup import db\n'), ((148, 20, 148, 28), 'databasesetup.db.con', 'db.con', ({}, {}), '()', False, 'from databasesetup import db\n'), ((163, 20, 163, 28), 'databasesetup.db.con', 'db.con', ({}, {}), '()', False, 'from databasesetup import db\n'), ((181, 20, 181, 28), 'databasesetup.db.con', 'db.con', ({}, {}), '()', False, 'from databasesetup import db\n'), ((207, 20, 207, 28), 'databasesetup.db.con', 'db.con', ({}, {}), '()', False, 'from databasesetup import db\n'), ((209, 8, 209, 19), 'databasesetup.db.commit', 'db.commit', ({}, {}), '()', False, 'from databasesetup import db\n'), ((214, 20, 214, 28), 'databasesetup.db.con', 'db.con', ({}, {}), '()', False, 'from databasesetup import db\n'), ((252, 20, 252, 28), 'databasesetup.db.con', 'db.con', ({}, {}), '()', False, 'from databasesetup import db\n'), ((266, 20, 266, 28), 'databasesetup.db.con', 'db.con', ({}, {}), '()', False, 'from databasesetup import db\n'), ((284, 20, 284, 28), 'databasesetup.db.con', 'db.con', ({}, {}), '()', False, 'from databasesetup import db\n'), ((303, 20, 303, 28), 'databasesetup.db.con', 'db.con', ({}, {}), '()', False, 'from databasesetup import db\n'), ((319, 20, 319, 28), 'databasesetup.db.con', 'db.con', ({}, {}), '()', False, 'from databasesetup import db\n'), ((37, 24, 37, 32), 'databasesetup.db.con', 'db.con', ({}, {}), '()', False, 'from databasesetup import db\n'), ((40, 12, 40, 23), 'databasesetup.db.commit', 'db.commit', ({}, {}), '()', False, 'from databasesetup import db\n'), ((49, 24, 49, 32), 'databasesetup.db.con', 'db.con', ({}, {}), '()', False, 'from databasesetup import db\n'), ((51, 12, 51, 23), 'databasesetup.db.commit', 'db.commit', ({}, {}), '()', False, 'from databasesetup import db\n'), ((69, 29, 69, 74), 'flask.jsonify', 'jsonify', ({(69, 37, 69, 73): "{'message': 'user does not exists'}"}, {}), "({'message': 'user does not exists'})", False, 'from flask import make_response, jsonify, current_app\n'), ((84, 29, 84, 63), 'flask.jsonify', 'jsonify', ({(84, 37, 84, 62): "{'All users': all_users}"}, {}), "({'All users': all_users})", False, 'from flask import make_response, jsonify, current_app\n'), ((109, 29, 109, 88), 'flask.jsonify', 'jsonify', ({(109, 37, 109, 87): "{'message': 'ride has been successfully created'}"}, {}), "({'message': 'ride has been successfully created'})", False, 'from flask import make_response, jsonify, current_app\n'), ((116, 24, 116, 32), 'databasesetup.db.con', 'db.con', ({}, {}), '()', False, 'from databasesetup import db\n'), ((119, 12, 119, 23), 'databasesetup.db.commit', 'db.commit', ({}, {}), '()', False, 'from databasesetup import db\n'), ((158, 29, 158, 74), 'flask.jsonify', 'jsonify', ({(158, 37, 158, 73): "{'message': 'user does not exists'}"}, {}), "({'message': 'user does not exists'})", False, 'from flask import make_response, jsonify, current_app\n'), ((176, 29, 176, 74), 'flask.jsonify', 'jsonify', ({(176, 37, 176, 73): "{'message': 'ride does not exists'}"}, {}), "({'message': 'ride does not exists'})", False, 'from flask import make_response, jsonify, current_app\n'), ((193, 29, 193, 63), 'flask.jsonify', 'jsonify', ({(193, 37, 193, 62): "{'All rides': all_rides}"}, {}), "({'All rides': all_rides})", False, 'from flask import make_response, jsonify, current_app\n'), ((220, 29, 220, 75), 'flask.jsonify', 'jsonify', ({(220, 37, 220, 74): "{'message': 'ride is already given'}"}, {}), "({'message': 'ride is already given'})", False, 'from flask import make_response, jsonify, current_app\n'), ((228, 24, 228, 32), 'databasesetup.db.con', 'db.con', ({}, {}), '()', False, 'from databasesetup import db\n'), ((230, 12, 230, 23), 'databasesetup.db.commit', 'db.commit', ({}, {}), '()', False, 'from databasesetup import db\n'), ((241, 24, 241, 32), 'databasesetup.db.con', 'db.con', ({}, {}), '()', False, 'from databasesetup import db\n'), ((243, 12, 243, 23), 'databasesetup.db.commit', 'db.commit', ({}, {}), '()', False, 'from databasesetup import db\n'), ((262, 29, 262, 77), 'flask.jsonify', 'jsonify', ({(262, 37, 262, 76): "{'message': 'request does not exists'}"}, {}), "({'message': 'request does not exists'})", False, 'from flask import make_response, jsonify, current_app\n'), ((279, 29, 279, 74), 'flask.jsonify', 'jsonify', ({(279, 37, 279, 73): "{'message': 'ride does not exists'}"}, {}), "({'message': 'ride does not exists'})", False, 'from flask import make_response, jsonify, current_app\n'), ((295, 29, 295, 71), 'flask.jsonify', 'jsonify', ({(295, 37, 295, 70): "{'ride_requests': ride_requests}"}, {}), "({'ride_requests': ride_requests})", False, 'from flask import make_response, jsonify, current_app\n'), ((41, 33, 41, 92), 'flask.jsonify', 'jsonify', ({(41, 41, 41, 91): "{'message': 'user has been successfully updated'}"}, {}), "({'message': 'user has been successfully updated'})", False, 'from flask import make_response, jsonify, current_app\n'), ((52, 33, 52, 92), 'flask.jsonify', 'jsonify', ({(52, 41, 52, 91): "{'message': 'user has been successfully deleted'}"}, {}), "({'message': 'user has been successfully deleted'})", False, 'from flask import make_response, jsonify, current_app\n'), ((68, 33, 68, 60), 'flask.jsonify', 'jsonify', ({(68, 41, 68, 59): "{'profile': info}"}, {}), "({'profile': info})", False, 'from flask import make_response, jsonify, current_app\n'), ((120, 33, 120, 92), 'flask.jsonify', 'jsonify', ({(120, 41, 120, 91): "{'message': 'user has been successfully updated'}"}, {}), "({'message': 'user has been successfully updated'})", False, 'from flask import make_response, jsonify, current_app\n'), ((137, 16, 137, 27), 'databasesetup.db.commit', 'db.commit', ({}, {}), '()', False, 'from databasesetup import db\n'), ((155, 16, 155, 27), 'databasesetup.db.commit', 'db.commit', ({}, {}), '()', False, 'from databasesetup import db\n'), ((175, 33, 175, 57), 'flask.jsonify', 'jsonify', ({(175, 41, 175, 56): "{'ride': info}"}, {}), "({'ride': info})", False, 'from flask import make_response, jsonify, current_app\n'), ((219, 33, 219, 105), 'flask.jsonify', 'jsonify', ({(219, 41, 219, 104): "{'message': 'request has been successfully sent for approval'}"}, {}), "({'message': 'request has been successfully sent for approval'})", False, 'from flask import make_response, jsonify, current_app\n'), ((232, 33, 232, 92), 'flask.jsonify', 'jsonify', ({(232, 41, 232, 91): "{'message': 'ride has been successfully deleted'}"}, {}), "({'message': 'ride has been successfully deleted'})", False, 'from flask import make_response, jsonify, current_app\n'), ((244, 33, 244, 96), 'flask.jsonify', 'jsonify', ({(244, 41, 244, 95): "{'message': 'request has been successfully accepted'}"}, {}), "({'message': 'request has been successfully accepted'})", False, 'from flask import make_response, jsonify, current_app\n'), ((261, 33, 261, 60), 'flask.jsonify', 'jsonify', ({(261, 41, 261, 59): "{'request': info}"}, {}), "({'request': info})", False, 'from flask import make_response, jsonify, current_app\n'), ((278, 33, 278, 75), 'flask.jsonify', 'jsonify', ({(278, 41, 278, 74): "{'ride_requests': ride_requests}"}, {}), "({'ride_requests': ride_requests})", False, 'from flask import make_response, jsonify, current_app\n'), ((311, 33, 311, 78), 'flask.jsonify', 'jsonify', ({(311, 41, 311, 77): "{'message': 'ride does not exists'}"}, {}), "({'message': 'ride does not exists'})", False, 'from flask import make_response, jsonify, current_app\n'), ((43, 33, 43, 77), 'flask.jsonify', 'jsonify', ({(43, 41, 43, 76): "{'message': 'user does not exist'}"}, {}), "({'message': 'user does not exist'})", False, 'from flask import make_response, jsonify, current_app\n'), ((54, 33, 54, 78), 'flask.jsonify', 'jsonify', ({(54, 41, 54, 77): "{'message': 'user does not exists'}"}, {}), "({'message': 'user does not exists'})", False, 'from flask import make_response, jsonify, current_app\n'), ((122, 33, 122, 77), 'flask.jsonify', 'jsonify', ({(122, 41, 122, 76): "{'message': 'user does not exist'}"}, {}), "({'message': 'user does not exist'})", False, 'from flask import make_response, jsonify, current_app\n'), ((157, 37, 157, 96), 'flask.jsonify', 'jsonify', ({(157, 45, 157, 95): "{'message': 'ride has been successfully deleted'}"}, {}), "({'message': 'ride has been successfully deleted'})", False, 'from flask import make_response, jsonify, current_app\n'), ((234, 33, 234, 106), 'flask.jsonify', 'jsonify', ({(234, 41, 234, 105): "{'message': 'the specified request does not exist in requests'}"}, {}), "({'message': 'the specified request does not exist in requests'})", False, 'from flask import make_response, jsonify, current_app\n'), ((246, 33, 246, 106), 'flask.jsonify', 'jsonify', ({(246, 41, 246, 105): "{'message': 'the specified request does not exist in requests'}"}, {}), "({'message': 'the specified request does not exist in requests'})", False, 'from flask import make_response, jsonify, current_app\n')]