import argparse
import atexit
import builtins
import logging
import os
import pathlib

import chip.CertificateAuthority
import chip.FabricAdmin
import chip.logging
import chip.native
import coloredlogs
from chip.ChipStack import ChipStack
from rich import inspect, pretty
from rich.console import Console

_fabricAdmins = None


def ReplInit(debug):
    #
    # Install the pretty printer that rich provides to replace the existing
    # printer.
    #
    pretty.install(indent_guides=True, expand_all=True)

    console = Console()

    console.rule('Matter REPL')
    console.print('''
            [bold blue]

            Welcome to the Matter Python REPL!

            For help, please type [/][bold green]matterhelp()[/][bold blue]

            To get more information on a particular object/class, you can pass
            that into [bold green]matterhelp()[/][bold blue] as well.

            ''')
    console.rule()

    coloredlogs.install(level='DEBUG')
    chip.logging.RedirectToPythonLogging()

    if debug:
        logging.getLogger().setLevel(logging.DEBUG)
    else:
        logging.getLogger().setLevel(logging.WARN)


certificateAuthorityManager = None


@atexit.register
def StackShutdown():
    if not certificateAuthorityManager:
        return
    certificateAuthorityManager.Shutdown()
    builtins.chipStack.Shutdown()


def matterhelp(classOrObj=None):
    if (classOrObj is None):
        inspect(builtins.devCtrl, methods=True, help=True, private=False)
        inspect(mattersetlog)
        inspect(mattersetdebug)
    else:
        inspect(classOrObj, methods=True, help=True, private=False)


def mattersetlog(level):
    logging.getLogger().setLevel(level)


def mattersetdebug(enableDebugMode: bool = True):
    ''' Enables debug mode that is utilized by some Matter modules
        to better facilitate debugging of failures (e.g throwing exceptions instead
        of returning well-formatted results).
    '''
    builtins.enableDebugMode = enableDebugMode


def main():
    console = Console()

    parser = argparse.ArgumentParser()
    parser.add_argument(
        "-p", "--storagepath",
        help="Path to persistent storage configuration file (default: /tmp/repl-storage.json)",
        action="store",
        default="/tmp/repl-storage.json")
    parser.add_argument(
        "-d", "--debug", help="Set default logging level to debug.", action="store_true")
    parser.add_argument(
        "-t", "--trust-store", help="Path to the PAA trust store.", action="store", default="./credentials/development/paa-root-certs")
    args = parser.parse_args()

    if not os.path.exists(args.trust_store):
        # there is a chance that the script is being run from a sub-path of a checkout.
        # try to adjust for convenience
        store_path = pathlib.Path(args.trust_store)
        if not store_path.is_absolute():
            prefix = pathlib.Path().absolute()
            while prefix != prefix.parent:
                if prefix.joinpath(store_path).exists():
                    oldpath = args.trust_store
                    args.trust_store = prefix.joinpath(store_path).as_posix()
                    console.print(f'''
[bold] Replacing [/] store path {oldpath} with {args.trust_store}
Note that you are still running from {os.getcwd()} so other relative paths may be off.
                    ''')
                    break
                prefix = prefix.parent

    if not os.path.exists(args.trust_store):
        console.print(f'''
[bold red] Missing directory:     [/]{args.trust_store}
[bold] Your current directory: [/]{os.getcwd()}

Please add a valid `--trust-store` argument to your script. If using jupyterlab,
the command should look like:

%run {{module.path}} --trust-store /chip/root/credentials/development/paa-root-certs

or run `os.chdir` to the root of your CHIP repository checkout.
        ''')
        # nothing we can do ... things will NOT work
        return

    chip.native.Init()

    global certificateAuthorityManager
    global chipStack
    global caList
    global devCtrl

    ReplInit(args.debug)

    chipStack = ChipStack(persistentStoragePath=args.storagepath, enableServerInteractions=False)
    certificateAuthorityManager = chip.CertificateAuthority.CertificateAuthorityManager(chipStack, chipStack.GetStorageManager())

    certificateAuthorityManager.LoadAuthoritiesFromStorage()

    if not certificateAuthorityManager.activeCaList:
        ca = certificateAuthorityManager.NewCertificateAuthority()
        ca.NewFabricAdmin(vendorId=0xFFF1, fabricId=1)
    elif not certificateAuthorityManager.activeCaList[0].adminList:
        certificateAuthorityManager.activeCaList[0].NewFabricAdmin(vendorId=0xFFF1, fabricId=1)

    caList = certificateAuthorityManager.activeCaList

    devCtrl = caList[0].adminList[0].NewController(paaTrustStorePath=args.trust_store)
    builtins.devCtrl = devCtrl

    console.print(
        '\n\n[blue]The following objects have been created:')

    console.print(
        '''\t[red]certificateAuthorityManager[blue]:\tManages a list of CertificateAuthority instances.
    \t[red]caList[blue]:\t\t\t\tThe list of CertificateAuthority instances.
    \t[red]caList[n][m][blue]:\t\t\tA specific FabricAdmin object at index m for the nth CertificateAuthority instance.''')

    console.print(
        f'\n\n[blue]Default CHIP Device Controller (NodeId: {devCtrl.nodeId}): '
        f'has been initialized to manage [bold red]caList[0].adminList[0][blue] (FabricId = {caList[0].adminList[0].fabricId}), '
        'and is available as [bold red]devCtrl')


if __name__ == "__main__":
    main()
