import multiprocessing
import os
import pathlib
import platform
import sys
from argparse import ArgumentParser


def main() -> int:
    if getattr(sys, 'frozen', False) or ('__compiled__' in globals()):
        # If we are on Windows, and we are in a "compiled" GUI application form
        # stdout (and stderr?) will be None. So to avoid `'NoneType' object has no attribute 'write'`
        # errors, redirect both of them to devnull
        if os.name == 'nt':
            # Check if stdout and stderr are None before redirecting
            # This is useful in the case of test builds that enable console
            if sys.stdout is None:
                sys.stdout = open(os.devnull, 'w')  # noqa: SIM115
            if sys.stderr is None:
                sys.stderr = open(os.devnull, 'w')  # noqa: SIM115
        # Nuitka and possibly cx_freeze have issues with launching multiprocessing's resource_tracker due
        # to the way it is invoked. To accomodate for that, check here if the "-c" argument was used, and
        # execute the incoming command instead of Rare itself.
        if 'MULTIPROCESSING_LAUNCH_TOKEN' in os.environ:
            if len(sys.argv) == 5 and sys.argv[1:4] == ['-S', '-s', '-c']:
                exec(sys.argv[4])
                return 0
        os.environ['MULTIPROCESSING_LAUNCH_TOKEN'] = '1'

    # remove QT_QPA_PLATFORMTHEME to avoid broken theming
    if 'QT_QPA_PLATFORMTHEME' in os.environ:
        del os.environ['QT_QPA_PLATFORMTHEME']
    os.environ['QT_STYLE_OVERRIDE'] = 'fusion'
    # remove XDG_CONFIG_HOME if running under Wine to stop legendary from using the Linux client config
    if platform.system() == 'Windows' and 'XDG_CONFIG_HOME' in os.environ:
        del os.environ['XDG_CONFIG_HOME']
    if 'LEGENDARY_CONFIG_PATH' in os.environ:
        os.environ['LEGENDARY_CONFIG_PATH'] = os.path.expanduser(os.environ['LEGENDARY_CONFIG_PATH'])

    # fix cx_freeze
    multiprocessing.freeze_support()

    # CLI Options
    parser = ArgumentParser()
    parser.add_argument('-V', '--version', action='store_true', help='Shows version and exits')
    parser.add_argument(
        '-S',
        '--silent',
        action='store_true',
        help='Launch Rare in background. Open it from System Tray Icon',
    )
    parser.add_argument('--debug', action='store_true', help='Launch in debug mode')
    parser.add_argument('--offline', action='store_true', help='Launch Rare in offline mode')
    parser.add_argument('--test-start', action='store_true', help='Quit immediately after launch')

    parser.add_argument(
        '--desktop-shortcut',
        action='store_true',
        dest='desktop_shortcut',
        help='Use this, if there is no link on desktop to start Rare',
    )
    parser.add_argument(
        '--startmenu-shortcut',
        action='store_true',
        dest='startmenu_shortcut',
        help='Use this, if there is no link in start menu to launch Rare',
    )
    subparsers = parser.add_subparsers(title='Commands', dest='subparser')

    # Launch command
    launch_parser = subparsers.add_parser('launch', aliases=['start'])
    launch_parser.add_argument('--dry-run', action='store_true', help='Print arguments and exit')
    launch_parser.add_argument('--offline', action='store_true', help='Launch game offline')
    launch_parser.add_argument('--ask-sync-saves', action='store_true', help='Ask to sync cloud saves')
    launch_parser.add_argument('--skip-update-check', action='store_true', help='Do not check for updates')
    launch_parser.add_argument(
        '--show-console',
        action='store_true',
        help="Show a console window to log the application's output",
    )
    if platform.system() != 'Windows':
        launch_parser.add_argument(
            '--wine-bin',
            action='store',
            dest='wine_bin',
            default=os.environ.get('LGDRY_WINE_BINARY', None),
            metavar='<wine binary>',
            help='Set WINE binary to use to launch the app',
        )
        launch_parser.add_argument(
            '--wine-prefix',
            action='store',
            dest='wine_pfx',
            default=os.environ.get('LGDRY_WINE_PREFIX', None),
            metavar='<wine pfx path>',
            help='Set WINE prefix to use',
        )
    launch_parser.add_argument(
        'app_name',
        action='store',
        metavar='<App Name>',
        help='AppName of the game to launch',
    )

    # Login command
    login_parser = subparsers.add_parser('login', aliases=['auth'])
    login_parser.add_argument(
        'egl_version',
        action='store',
        metavar='<EGL Version>',
        help='Epic Games Launcher User Agent version',
    )

    # Subreaper command
    subparsers.add_parser('subreaper', aliases=['reaper'])

    args, other = parser.parse_known_args()

    if args.desktop_shortcut or args.startmenu_shortcut:
        from rare.utils.paths import create_desktop_link

        if args.desktop_shortcut:
            create_desktop_link(app_name='rare_shortcut', link_type='desktop')

        if args.startmenu_shortcut:
            create_desktop_link(app_name='rare_shortcut', link_type='start_menu')

        print('Link created', file=sys.stderr)
        return 0

    if args.version:
        from rare import __codename__, __version__

        print(f'Rare {__version__} Codename: {__codename__}', file=sys.stderr)
        return 0

    if args.subparser in {'login', 'auth'}:
        from rare.commands.webview import webview

        return webview(args)

    if args.subparser in {'launch', 'start'}:
        from rare.commands.launcher import launcher

        return launcher(args)

    if args.subparser in {'subreaper', 'reaper'}:
        from rare.commands.subreaper import subreaper

        sep = other.index('--')
        other = other[sep + 1 :]
        args.command = other.pop(0)
        args.workdir = os.getcwd()

        return subreaper(args, other)

    from rare.utils import singleton

    try:
        # this object only allows one instance per machine

        me = singleton.SingleInstance()  # noqa: F841
    except singleton.SingleInstanceException:
        print('Rare is already running', file=sys.stderr)
        from rare.utils.paths import lock_file

        with open(lock_file(), 'w') as file:
            file.write('show')
            file.close()
        return -1

    from rare.components import start

    ec = start(args)
    if os.name == 'nt':
        if not sys.stdout.closed:
            sys.stdout.close()
        if not sys.stderr.closed:
            sys.stderr.close()
    return ec


if __name__ == '__main__':
    # insert source directory if running `main.py` as python script
    # Required by AppImage
    if '__compiled__' not in globals():
        sys.path.insert(0, str(pathlib.Path(__file__).parents[1].absolute()))

    sys.exit(main())
