# CUBERACERS BACKEND SERVER
# COPYRIGHT REUBEN SCHIOPU (C) 2022
# CONFIDENTIAL PROPERTY OF REUBEN SCHIOPU
# UNAUTHORIZED DISTRIBUTION PROHIBITED


from better_profanity import profanity
#from waitress import serve
from flask import Flask
from flask import request
from flask_cors import CORS
from pymongo import MongoClient
import pymongo
import hashlib
app = Flask('app')
CORS(app)
connString = "mongodb+srv://dbUser:dbUserPassword@cluster0.3mrf2uh.mongodb.net/?appName=Cluster0"
client = MongoClient(connString)
print(client.server_info())
userAccountsCollection = client["CR_DATABASE"]["USER_ACCOUNTS"]
highscoresCollection = client["CR_DATABASE"]["HIGHSCORES"]
profanity.load_censor_words()

@app.route('/')
def index():
  return '404 Not Found',404

@app.route("/getRawHS")
def getrawhs():
  try:
    if hashlib.md5(request.args.get("auth").encode()).hexdigest() == "8dd95f3ecbe769ef92fdf39e0cf66122":
      hsSearch = highscoresCollection.find_one({"mode": request.args.get("mode")})
      if hsSearch == None:
        return '500 Error',500
      else:
        try:
          return str(hsSearch["score"]),200
        except:
          return "500 Error",500
      return '200 OK'
    else:
      return '403 Forbidden',403
  except:
    return '500 Error',500
  return "200 OK"

@app.route("/getHS")
def getHsHolder():
  try:
    if hashlib.md5(request.args.get("auth").encode()).hexdigest() == "8dd95f3ecbe769ef92fdf39e0cf66122":
      hsSearch = highscoresCollection.find_one({"mode": request.args.get("mode")})
      if hsSearch == None:
        return '500 Error',500
      else:
        try:
          return profanity.censor(str(hsSearch["username"]) + "\nhas the world record\nof " + str(hsSearch["score"])),200
        except:
          return "500 Error",500
      return '200 OK'
    else:
      return '403 Forbidden',403
  except:
    return '500 Error',500
  return "200 OK"

@app.route('/setHS')
def setHS():
  try:
    if hashlib.md5(request.args.get("auth").encode()).hexdigest() == "8dd95f3ecbe769ef92fdf39e0cf66122":
        try:
            newParams = {
            "score":request.args.get("score"),
            "username":request.args.get("username")
            }
            highscoresCollection.update_one({"mode":request.args.get("mode")},{"$set":newParams})
        except:
            return "500 Error",500
        return '200 OK'
    else:
      return '403 Forbidden',403
  except:
    return '500 Error',500
  return "200 OK"

@app.route('/ping')
def ping():
  return '200 OK'

@app.route('/createAccount')
def createAccount():
  try:
    if hashlib.md5(request.args.get("auth").encode()).hexdigest() == "8dd95f3ecbe769ef92fdf39e0cf66122":
      newUser = {
        "username":request.args.get("username"),
        "password":request.args.get("password")
      }
      usernameSearch = userAccountsCollection.find_one({"username": request.args.get("username")})
      if usernameSearch != None:
        return '409 Conflict',409
      else:
        userAccountsCollection.insert_one(newUser)
      return '200 OK'
    else:
      return '403 Forbidden',403
  except:
    return '500 Error',500
  return "200 OK"

@app.route('/deleteAccount')
def deleteAccount():
  # WILL BE ADDED IN FUTURE
  return '501 Not Implemented',501

@app.route('/modifyAccountParams')
def modifyAccountParams():
  try:
    if hashlib.md5(request.args.get("auth").encode()).hexdigest() == "8dd95f3ecbe769ef92fdf39e0cf66122":
      usernameSearch = userAccountsCollection.find_one({"username": request.args.get("username")})
      if usernameSearch == None:
        return '500 Error',500
      else:
        try:
          newParams = {
            request.args.get("paramToChange"):request.args.get("value")
          }
          userAccountsCollection.update_one({"username":request.args.get("username")},{"$set":newParams})
        except:
          return "500 Error",500
      return '200 OK'
    else:
      return '403 Forbidden',403
  except:
    return '500 Error',500
  return "200 OK"

@app.route('/getAccountParams')
def getAccountParams():
  try:
    if hashlib.md5(request.args.get("auth").encode()).hexdigest() == "8dd95f3ecbe769ef92fdf39e0cf66122":
      userSearch = userAccountsCollection.find_one({"username": request.args.get("username")})
      if userSearch == None:
        return '500 Error',500
      else:
        try:
          return str(userSearch[request.args.get("paramToGet")]),200
        except:
          return "500 Error",500
      return '200 OK'
    else:
      return '403 Forbidden',403
  except:
    return '500 Error',500
  return "200 OK"

app.run(host='0.0.0.0', port=8000)
#serve(app, host='0.0.0.0', port=5000, url_scheme='https')


# API Docs:
"""
What is this?
This is the code for the CubeRacers Account Server, which provides an API to communicate with the MongoDB database where the CubeRacers Accounts are stored. The MongoDB connection string is in an enviroment variable to prevent people from editing the database without sufficient permissions. All routes except for /ping are protected by a password. The password needs to be passed in as a request parameter or the request will fail. These routes are used by CubeRacers the game, which uses them to manage accounts for the game.

Route /ping - Returns code 200 if server is online
Route /createAccount?auth=<password>&username=<username>&password=<passwordForAccount> - Creates new account in database
Route /deleteAccount?auth=<password>&username=<username>&password=<passwordForAccount> - Deletes account from database
Route /modifyAccountParams?auth=<password>&username=<username>&paramToChange=<paramToChange>&value=<parameter value> - Modify account info
Route /getAccountParams?auth=<password>&username=<username>&paramToGet=<paramToGet> - Get info about account
"""
