import datetime
import json
import os
import ssl
import subprocess
import sys
import typing
import urllib.parse
import urllib.request

"""
official api documentation:
https://github.com/ToontownRewritten/api-doc/blob/master/login.md
https://github.com/ToontownRewritten/api-doc/blob/master/invasions.md
"""

LOGIN_API_URL = "https://www.toontownrewritten.com/api/login?format=json"

if sys.platform == "darwin":
    TOONTOWN_LIBRARY_PATH = os.path.join(
        os.path.expanduser("~"), "Library", "Application Support", "Toontown Rewritten",
    )
    TOONTOWN_ENGINE_DEFAULT_PATH = os.path.join(
        TOONTOWN_LIBRARY_PATH, "Toontown Rewritten",
    )
else:
    TOONTOWN_LIBRARY_PATH = None
    TOONTOWN_ENGINE_DEFAULT_PATH = None


def start_engine(engine_path, gameserver, playcookie, **kwargs) -> subprocess.Popen:
    env = {
        "TTR_GAMESERVER": gameserver,
        "TTR_PLAYCOOKIE": playcookie,
    }
    if sys.platform == "darwin":
        env["DYLD_LIBRARY_PATH"] = os.path.join(
            TOONTOWN_LIBRARY_PATH, "Libraries.bundle",
        )
        env["DYLD_FRAMEWORK_PATH"] = os.path.join(TOONTOWN_LIBRARY_PATH, "Frameworks",)
    elif sys.platform == "linux" and "XAUTHORITY" in os.environ:
        """
        Fix for TTREngine reporting:
        > :display:x11display(error): Could not open display ":0.0".
        > :ToonBase: Default graphics pipe is glxGraphicsPipe (OpenGL).
        > :ToonBase(warning): Unable to open 'onscreen' window.
        > Traceback (most recent call last):
        >   File "<compiled '__voltorbmain__'>", line 0, in <module>
        >   [...]
        >   File "<compiled 'direct.vlt8f63e471.ShowBase'>", line 0, in vltf05fd21b
        > Exception: Could not open window.
        """
        env["XAUTHORITY"] = os.environ["XAUTHORITY"]
    return subprocess.Popen(
        args=[engine_path], cwd=os.path.dirname(engine_path), env=env, **kwargs,
    )


def api_request(url, params=None, validate_ssl_cert=True):
    resp = urllib.request.urlopen(
        url=url,
        data=urllib.parse.urlencode(params).encode("ascii") if params else None,
        context=None if validate_ssl_cert else ssl._create_unverified_context(),
    )
    return json.loads(resp.read().decode("ascii"))


class _LoginSuccessful:
    def __init__(self, playcookie, gameserver):
        self.playcookie = playcookie
        self.gameserver = gameserver


class _LoginDelayed:
    def __init__(self, queue_token):
        self.queue_token = queue_token


def login(
    username=None, password=None, queue_token=None, validate_ssl_cert=True
) -> typing.Union[_LoginSuccessful, _LoginDelayed]:
    if username is not None and queue_token is None:
        assert password is not None
        req_params = {
            "username": username,
            "password": password,
        }
    elif username is None and queue_token is not None:
        req_params = {
            "queueToken": queue_token,
        }
    else:
        raise Exception("either specify username or queue token")
    resp_data = api_request(
        url=LOGIN_API_URL, params=req_params, validate_ssl_cert=validate_ssl_cert,
    )
    if resp_data["success"] == "true":
        return _LoginSuccessful(
            playcookie=resp_data["cookie"], gameserver=resp_data["gameserver"],
        )
    if resp_data["success"] == "delayed":
        return _LoginDelayed(queue_token=resp_data["queueToken"],)
    raise Exception(repr(resp_data))


def launch(
    engine_path, username, password, validate_ssl_certs=True, cpu_limit_percent=None
) -> None:
    result = login(
        username=username, password=password, validate_ssl_cert=validate_ssl_certs,
    )
    if isinstance(result, _LoginDelayed):
        result = login(
            queue_token=result.queue_token, validate_ssl_cert=validate_ssl_certs,
        )
    if not isinstance(result, _LoginSuccessful):
        raise Exception("unexpected response: {!r}".format(result))
    process = start_engine(
        engine_path=engine_path,
        gameserver=result.gameserver,
        playcookie=result.playcookie,
    )
    if cpu_limit_percent is not None:
        subprocess.Popen(
            args=[
                "cpulimit",
                "--pid",
                str(process.pid),
                "--limit",
                str(cpu_limit_percent),
                # '--verbose',
            ]
        )
    process.wait()

@@ -128,20 +128,18 @@
 equest%0A%0A
-%22%22%22%0A
+# 
 official
@@ -158,16 +158,18 @@
 tation:%0A
+# 
 https://
@@ -226,16 +226,18 @@
 ogin.md%0A
+# 
 https://
@@ -301,12 +301,8 @@
 s.md
-%0A%22%22%22
 %0A%0ALO
@@ -1216,27 +1216,17 @@
         
-%22%22%22%0A       
+#
  Fix for
@@ -1250,24 +1250,26 @@
 ing:%0A       
+ #
  %3E :display:
@@ -1317,32 +1317,34 @@
  %22:0.0%22.%0A       
+ #
  %3E :ToonBase: De
@@ -1399,16 +1399,18 @@
 %0A       
+ #
  %3E :Toon
@@ -1465,16 +1465,18 @@
 %0A       
+ #
  %3E Trace
@@ -1504,32 +1504,34 @@
 l last):%0A       
+ #
  %3E   File %22%3Ccomp
@@ -1579,24 +1579,26 @@
 ule%3E%0A       
+ #
  %3E   %5B...%5D%0A 
@@ -1603,16 +1603,18 @@
 %0A       
+ #
  %3E   Fil
@@ -1689,16 +1689,18 @@
 %0A       
+ #
  %3E Excep
@@ -1732,20 +1732,8 @@
 ow.%0A
-        %22%22%22%0A
     

fix pylint/pointless-string-statement