#
#    Copyright (c) 2021 Project CHIP Authors
#    All rights reserved.
#
#    Licensed under the Apache License, Version 2.0 (the "License");
#    you may not use this file except in compliance with the License.
#    You may obtain a copy of the License at
#
#        http://www.apache.org/licenses/LICENSE-2.0
#
#    Unless required by applicable law or agreed to in writing, software
#    distributed under the License is distributed on an "AS IS" BASIS,
#    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
#    See the License for the specific language governing permissions and
#    limitations under the License.
#
"""Console for interacting with CHIP lighting app over RPC.

To start the console, provide a serial port as the --device argument

  python -m chip_rpc.console --device /dev/ttyUSB0

Alternatively to connect to a linux CHIP device provide the port.

  python -m chip_rpc.console -s localhost:33000

This starts an IPython console for communicating with the connected device. A
few variables are predefined in the interactive console. These include:

    rpcs   - used to invoke RPCs
    device - the serial device used for communication
    client - the pw_rpc.Client
    protos - protocol buffer messages indexed by proto package

An example RPC command:
  rpcs.chip.rpc.DeviceCommon.GetDeviceInfo()
"""

import argparse
import logging
import re
import socket
import sys
import threading
from collections import namedtuple
from concurrent.futures import ThreadPoolExecutor
from inspect import cleandoc
from typing import Any, BinaryIO, Callable, Collection

import pw_cli.log
from chip_rpc.plugins.device_toolbar import DeviceToolbar
from chip_rpc.plugins.helper_scripts import HelperScripts
from pw_console import PwConsoleEmbed
from pw_console.__main__ import create_temp_log_file
from pw_console.pyserial_wrapper import SerialWithLogging
from pw_hdlc.rpc import HdlcRpcClient, default_channels
from pw_rpc import callback_client
from pw_rpc.console_tools.console import ClientInfo, flattened_rpc_completions
from pw_tokenizer import tokens
from pw_tokenizer.database import LoadTokenDatabases
from pw_tokenizer.detokenize import Detokenizer

# Protos
# isort: off
from attributes_service import attributes_service_pb2
from button_service import button_service_pb2
from descriptor_service import descriptor_service_pb2
from device_service import device_service_pb2
from echo_service import echo_pb2
from lighting_service import lighting_service_pb2
from locking_service import locking_service_pb2
from ot_cli_service import ot_cli_service_pb2
from thread_service import thread_service_pb2
from wifi_service import wifi_service_pb2

_LOG = logging.getLogger(__name__)
_DEVICE_LOG = logging.getLogger('rpc_device')

PW_RPC_MAX_PACKET_SIZE = 256
SOCKET_SERVER = 'localhost'
SOCKET_PORT = 33000

PROTOS = [attributes_service_pb2,
          button_service_pb2,
          descriptor_service_pb2,
          device_service_pb2,
          echo_pb2,
          lighting_service_pb2,
          locking_service_pb2,
          ot_cli_service_pb2,
          thread_service_pb2,
          wifi_service_pb2]


def _parse_args():
    """Parses and returns the command line arguments."""
    parser = argparse.ArgumentParser(description=__doc__)
    group = parser.add_mutually_exclusive_group(required=True)
    group.add_argument('-d', '--device', help='the serial port to use')
    parser.add_argument('-b',
                        '--baudrate',
                        type=int,
                        default=115200,
                        help='the baud rate to use')
    parser.add_argument(
        '-o',
        '--output',
        type=argparse.FileType('wb'),
        default=sys.stdout.buffer,
        help=('The file to which to write device output (HDLC channel 1); '
              'provide - or omit for stdout.'))
    parser.add_argument(
        '-r',
        '--raw_serial',
        action="store_true",
        help=('Use raw serial instead of HDLC/RPC'))
    parser.add_argument("--token-databases",
                        metavar='elf_or_token_database',
                        nargs="+",
                        action=LoadTokenDatabases,
                        help="Path to tokenizer database csv file(s).")
    group.add_argument('-s',
                       '--socket-addr',
                       type=str,
                       help='use socket to connect to server, type default for\
            localhost:33000, or manually input the server address:port')
    return parser.parse_args()


def _start_ipython_raw_terminal() -> None:
    """Starts an interactive IPython terminal with preset variables. This raw
       terminal does not use HDLC and provides no RPC functionality, this is
       just a serial log viewer."""
    local_variables = dict(
        LOG=_DEVICE_LOG,
    )

    welcome_message = cleandoc("""
        Welcome to the CHIP Console!

        This has been started in raw serial mode,
        and all RPC functionality is disabled.

        Press F1 for help.
    """)

    interactive_console = PwConsoleEmbed(
        global_vars=local_variables,
        local_vars=None,
        loggers={
            'Device Logs': [_DEVICE_LOG],
            'Host Logs': [logging.getLogger()],
            'Serial Debug': [logging.getLogger('pw_console.serial_debug_logger')],
        },
        repl_startup_message=welcome_message,
        help_text=__doc__,
        app_title="CHIP Console",
    )

    interactive_console.hide_windows('Host Logs')
    interactive_console.hide_windows('Serial Debug')
    interactive_console.hide_windows('Python Repl')

    # Setup Python logger propagation
    interactive_console.setup_python_logging()
    # Don't send device logs to the root logger.
    _DEVICE_LOG.propagate = False
    interactive_console.embed()


def _start_ipython_hdlc_terminal(client: HdlcRpcClient) -> None:
    """Starts an interactive IPython terminal with preset variables."""
    local_variables = dict(
        client=client,
        channel_client=client.client.channel(1),
        rpcs=client.client.channel(1).rpcs,
        scripts=HelperScripts(client.client.channel(1).rpcs),
        protos=client.protos.packages,
        # Include the active pane logger for creating logs in the repl.
        LOG=_DEVICE_LOG,
    )

    client_info = ClientInfo('channel_client',
                             client.client.channel(1).rpcs, client.client)
    completions = flattened_rpc_completions([client_info])

    welcome_message = cleandoc("""
        Welcome to the CHIP RPC Console!

        Press F1 for help.
        Example commands:

          rpcs.chip.rpc.Device.GetDeviceInfo()

          LOG.warning('Message appears console log window.')
    """)

    interactive_console = PwConsoleEmbed(
        global_vars=local_variables,
        local_vars=None,
        loggers={
            'Device Logs': [_DEVICE_LOG],
            'Host Logs': [logging.getLogger()],
            'Serial Debug': [logging.getLogger('pw_console.serial_debug_logger')],
        },
        repl_startup_message=welcome_message,
        help_text=__doc__,
        app_title="CHIP Console",
    )

    interactive_console.add_sentence_completer(completions)
    interactive_console.add_bottom_toolbar(
        DeviceToolbar(client.client.channel(1).rpcs))

    interactive_console.hide_windows('Host Logs')
    interactive_console.hide_windows('Serial Debug')

    # Setup Python logger propagation
    interactive_console.setup_python_logging()
    # Don't send device logs to the root logger.
    _DEVICE_LOG.propagate = False
    interactive_console.embed()


class SocketClientImpl:
    def __init__(self, config: str):
        self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        socket_server = ''
        socket_port = 0

        if config == 'default':
            socket_server = SOCKET_SERVER
            socket_port = SOCKET_PORT
        else:
            socket_server, socket_port_str = config.split(':')
            socket_port = int(socket_port_str)
        self.socket.connect((socket_server, socket_port))

    def write(self, data: bytes):
        self.socket.sendall(data)

    def read(self, num_bytes: int = PW_RPC_MAX_PACKET_SIZE):
        return self.socket.recv(num_bytes)


def write_to_output(data: bytes,
                    unused_output: BinaryIO = sys.stdout.buffer,
                    detokenizer=None):
    log_line = data
    RegexStruct = namedtuple('RegexStruct', 'platform type regex match_num')
    LEVEL_MAPPING = {"I": logging.INFO, "W": logging.WARNING, "P": logging.INFO,
                     "E": logging.ERROR, "F": logging.FATAL, "V": logging.DEBUG, "D": logging.DEBUG,
                     "<inf>": logging.INFO, "<dbg>": logging.DEBUG, "<err>": logging.ERROR,
                     "<info  >": logging.INFO, "<warn  >": logging.WARNING,
                     "<error >": logging.ERROR, "<detail>": logging.DEBUG,
                     "ERR": logging.ERROR, "DBG": logging.DEBUG, "INF": logging.INFO}

    ESP_CHIP_REGEX = r"(?P<level>[IWEFV]) \((?P<time>\d+)\) (?P<mod>chip\[[a-zA-Z]+\]):\s(?P<msg>.*)"
    ESP_APP_REGEX = r"(?P<level>[IWEFVD]) \((?P<time>\d+)\) (?P<mod>[a-z\-_A-Z]+):\s(?P<msg>.*)"

    EFR_CHIP_REGEX = r"(?P<level><detail>|<info  >|<error >|<warn  >)\s(?P<mod>\[[a-zA-Z\-]+\])\s(?P<msg>.*)"
    EFR_APP_REGEX = r"<efr32 >\s(?P<msg>.*)"

    NRF_CHIP_REGEX = r"\[(?P<time>\d+)\] (?P<level><inf>|<dbg>|<err>) chip.*: \[(?P<mod>[a-z\-A-Z]+)\](?P<msg>.*)"
    NRF_APP_REGEX = r"\[(?P<time>\d+)\] (?P<level><inf>|<dbg>|<err>) (?P<msg>.*)"

    NXP_CHIP_REGEX = r"\[(?P<time>\d+)\]\[(?P<level>[EPDF])\]\[(?P<mod>[a-z\-A-Z]+)\](?P<msg>.*)"
    NXP_APP_REGEX = r"\[(?P<time>\d+)\]\[(?P<mod>[a-z\-A-Z]+)\](?P<msg>.*)"

    LINUX_REGEX = r".*(?P<level>INF|DBG|ERR).*\s+\[(?P<time>[0-9]+\.?[0-9]*)\]\[(?P<pid>\d+)\:(?P<tid>\d+)\] CHIP:(?P<mod>[a-z\-A-Z]+)\: (?P<msg>.*)"

    LogRegexes = [RegexStruct("ESP", "CHIP", re.compile(ESP_CHIP_REGEX), 4),
                  RegexStruct("ESP", "APP", re.compile(ESP_APP_REGEX), 4),
                  RegexStruct("EFR", "CHIP", re.compile(EFR_CHIP_REGEX), 3),
                  RegexStruct("EFR", "APP", re.compile(EFR_APP_REGEX), 1),
                  RegexStruct("NRF", "CHIP", re.compile(NRF_CHIP_REGEX), 4),
                  RegexStruct("NRF", "APP", re.compile(NRF_APP_REGEX), 3),
                  RegexStruct("NXP", "CHIP", re.compile(NXP_CHIP_REGEX), 4),
                  RegexStruct("NXP", "APP", re.compile(NXP_APP_REGEX), 3),
                  RegexStruct("LINUX", "CHIP", re.compile(LINUX_REGEX), 6)
                  ]
    for line in log_line.decode(errors="surrogateescape").splitlines():
        fields = {'level': logging.INFO, "time": "",
                  "mod": "", "type": "", "msg": line}
        for log_regex in LogRegexes:
            match = log_regex.regex.search(line)
            if match and len(match.groups()) == log_regex.match_num:
                fields['type'] = log_regex.type
                fields.update(match.groupdict())
                if "level" in match.groupdict():
                    fields["level"] = LEVEL_MAPPING[fields["level"]]
                if detokenizer:
                    _LOG.warn(fields["msg"])
                    if len(fields["msg"]) % 2:
                        # TODO the msg likely wrapped, trim for now
                        fields["msg"] = fields["msg"][:-1]
                    fields["msg"] = detokenizer.detokenize(
                        bytes.fromhex(fields["msg"]))
                break

        _DEVICE_LOG.log(fields["level"], fields["msg"], extra={'extra_metadata_fields': {
                        "timestamp": fields["time"], "type": fields["type"], "mod": fields["mod"]}})


def _read_raw_serial(read: Callable[[], bytes], output):
    """Continuously read and pass to output."""
    with ThreadPoolExecutor() as executor:
        while True:
            try:
                data = read()
            except Exception as exc:  # pylint: disable=broad-except
                continue
            if data:
                output(data)


def console(device: str, baudrate: int,
            token_databases: Collection[tokens.Database],
            socket_addr: str, output: Any, raw_serial: bool) -> int:
    """Starts an interactive RPC console for HDLC."""
    # argparse.FileType doesn't correctly handle '-' for binary files.
    if output is sys.stdout:
        output = sys.stdout.buffer

    logfile = create_temp_log_file()
    pw_cli.log.install(logging.INFO, True, False, logfile)

    serial_impl = SerialWithLogging

    if socket_addr is None:
        serial_device = serial_impl(device, baudrate, timeout=0.1)
        def read(): return serial_device.read(8192)
        write = serial_device.write
    else:
        try:
            socket_device = SocketClientImpl(socket_addr)
            read = socket_device.read
            write = socket_device.write
        except ValueError:
            _LOG.exception('Failed to initialize socket at %s', socket_addr)
            return 1

    callback_client_impl = callback_client.Impl(
        default_unary_timeout_s=5.0,
        default_stream_timeout_s=None,
    )

    detokenizer = Detokenizer(tokens.Database.merged(*token_databases),
                              show_errors=False) if token_databases else None

    if raw_serial:
        threading.Thread(target=_read_raw_serial,
                         daemon=True,
                         args=(read,
                               lambda data: write_to_output(
                                   data, output, detokenizer),
                               )).start()
        _start_ipython_raw_terminal()
    else:
        _start_ipython_hdlc_terminal(
            HdlcRpcClient(read, PROTOS, default_channels(write),
                          lambda data: write_to_output(
                              data, output, detokenizer),
                          client_impl=callback_client_impl)
        )
    return 0


def main() -> int:
    return console(**vars(_parse_args()))


if __name__ == '__main__':
    sys.exit(main())
