# Copyright 2018 - The Android Open Source Project
#
# 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.
r"""Reconnect entry point.

Reconnect will:
 - re-establish ssh tunnels for adb/vnc port forwarding for a remote instance
 - adb connect to forwarded ssh port for remote instance
 - restart vnc for remote/local instances
"""

import logging
import os
import re

from acloud import errors
from acloud.internal import constants
from acloud.internal.lib import auth
from acloud.internal.lib import android_compute_client
from acloud.internal.lib import cvd_runtime_config
from acloud.internal.lib import utils
from acloud.internal.lib import ssh as ssh_object
from acloud.internal.lib.adb_tools import AdbTools
from acloud.list import list as list_instance
from acloud.public import config
from acloud.public import report


logger = logging.getLogger(__name__)

_RE_DISPLAY = re.compile(r"([\d]+)x([\d]+)\s.*")
_VNC_STARTED_PATTERN = "ssvnc vnc://127.0.0.1:%(vnc_port)d"
_WEBRTC_PORTS_SEARCH = "".join(
    [utils.PORT_MAPPING % {"local_port":port["local"],
                           "target_port":port["target"]}
     for port in utils.WEBRTC_PORTS_MAPPING])


def _IsWebrtcEnable(instance, host_user, host_ssh_private_key_path,
                    extra_args_ssh_tunnel):
    """Check local/remote instance webRTC is enable.

    Args:
        instance: Local/Remote Instance object.
        host_user: String of user login into the instance.
        host_ssh_private_key_path: String of host key for logging in to the
                                   host.
        extra_args_ssh_tunnel: String, extra args for ssh tunnel connection.

    Returns:
        Boolean: True if cf_runtime_cfg.enable_webrtc is True.
    """
    if instance.islocal:
        return instance.cf_runtime_cfg.enable_webrtc
    ssh = ssh_object.Ssh(ip=ssh_object.IP(ip=instance.ip), user=host_user,
                         ssh_private_key_path=host_ssh_private_key_path,
                         extra_args_ssh_tunnel=extra_args_ssh_tunnel)
    remote_cuttlefish_config = os.path.join(constants.REMOTE_LOG_FOLDER,
                                            constants.CUTTLEFISH_CONFIG_FILE)
    raw_data = ssh.GetCmdOutput("cat " + remote_cuttlefish_config)
    try:
        cf_runtime_cfg = cvd_runtime_config.CvdRuntimeConfig(
            raw_data=raw_data.strip())
        return cf_runtime_cfg.enable_webrtc
    except errors.ConfigError:
        logger.debug("No cuttlefish config[%s] found!",
                     remote_cuttlefish_config)
    return False


def _WebrtcPortOccupied():
    """To decide whether need to release port.

    Remote webrtc instance will create a ssh tunnel which may conflict with
    local webrtc instance default port. Searching process cmd in the pattern
    of _WEBRTC_PORTS_SEARCH to decide whether to release port.

    Return:
        True if need to release port.
    """
    process_output = utils.CheckOutput(constants.COMMAND_PS)
    for line in process_output.splitlines():
        match = re.search(_WEBRTC_PORTS_SEARCH, line)
        if match:
            return True
    return False


def StartVnc(vnc_port, display):
    """Start vnc connect to AVD.

    Confirm whether there is already a connection before VNC connection.
    If there is a connection, it will not be connected. If not, connect it.
    Before reconnecting, clear old disconnect ssvnc viewer.

    Args:
        vnc_port: Integer of vnc port number.
        display: String, vnc connection resolution. e.g., 1080x720 (240)
    """
    vnc_started_pattern = _VNC_STARTED_PATTERN % {"vnc_port": vnc_port}
    if not utils.IsCommandRunning(vnc_started_pattern):
        #clean old disconnect ssvnc viewer.
        utils.CleanupSSVncviewer(vnc_port)

        match = _RE_DISPLAY.match(display)
        if match:
            utils.LaunchVncClient(vnc_port, match.group(1), match.group(2))
        else:
            utils.LaunchVncClient(vnc_port)


def AddPublicSshRsaToInstance(cfg, user, instance_name):
    """Add the public rsa key to the instance's metadata.

    When the public key doesn't exist in the metadata, it will add it.

    Args:
        cfg: An AcloudConfig instance.
        user: String, the ssh username to access instance.
        instance_name: String, instance name.
    """
    credentials = auth.CreateCredentials(cfg)
    compute_client = android_compute_client.AndroidComputeClient(
        cfg, credentials)
    compute_client.AddSshRsaInstanceMetadata(
        user,
        cfg.ssh_public_key_path,
        instance_name)


@utils.TimeExecute(function_description="Reconnect instances")
def ReconnectInstance(ssh_private_key_path,
                      instance,
                      reconnect_report,
                      extra_args_ssh_tunnel=None,
                      connect_vnc=True):
    """Reconnect to the specified instance.

    It will:
     - re-establish ssh tunnels for adb/vnc port forwarding
     - re-establish adb connection
     - restart vnc client
     - update device information in reconnect_report

    Args:
        ssh_private_key_path: Path to the private key file.
                              e.g. ~/.ssh/acloud_rsa
        instance: list.Instance() object.
        reconnect_report: Report object.
        extra_args_ssh_tunnel: String, extra args for ssh tunnel connection.
        connect_vnc: Boolean, True will launch vnc.

    Raises:
        errors.UnknownAvdType: Unable to reconnect to instance of unknown avd
                               type.
    """
    if instance.avd_type not in utils.AVD_PORT_DICT:
        raise errors.UnknownAvdType("Unable to reconnect to instance (%s) of "
                                    "unknown avd type: %s" %
                                    (instance.name, instance.avd_type))

    adb_cmd = AdbTools(instance.adb_port)
    vnc_port = instance.vnc_port
    adb_port = instance.adb_port
    # ssh tunnel is up but device is disconnected on adb
    if instance.ssh_tunnel_is_connected and not adb_cmd.IsAdbConnectionAlive():
        adb_cmd.DisconnectAdb()
        adb_cmd.ConnectAdb()
    # ssh tunnel is down and it's a remote instance
    elif not instance.ssh_tunnel_is_connected and not instance.islocal:
        adb_cmd.DisconnectAdb()
        forwarded_ports = utils.AutoConnect(
            ip_addr=instance.ip,
            rsa_key_file=ssh_private_key_path,
            target_vnc_port=utils.AVD_PORT_DICT[instance.avd_type].vnc_port,
            target_adb_port=utils.AVD_PORT_DICT[instance.avd_type].adb_port,
            ssh_user=constants.GCE_USER,
            extra_args_ssh_tunnel=extra_args_ssh_tunnel)
        vnc_port = forwarded_ports.vnc_port
        adb_port = forwarded_ports.adb_port
    if _IsWebrtcEnable(instance,
                       constants.GCE_USER,
                       ssh_private_key_path,
                       extra_args_ssh_tunnel):
        if instance.islocal:
            if _WebrtcPortOccupied():
                raise errors.PortOccupied("\nReconnect to a local webrtc instance "
                                          "is not work because remote webrtc "
                                          "instance has established ssh tunnel "
                                          "which occupied local webrtc instance "
                                          "port. If you want to connect to a "
                                          "local-instance of webrtc. please run "
                                          "'acloud create --local-instance "
                                          "--autoconnect webrtc' directly.")
        else:
            utils.EstablishWebRTCSshTunnel(
                ip_addr=instance.ip,
                rsa_key_file=ssh_private_key_path,
                ssh_user=constants.GCE_USER,
                extra_args_ssh_tunnel=extra_args_ssh_tunnel)
        utils.LaunchBrowser(constants.WEBRTC_LOCAL_HOST,
                            constants.WEBRTC_LOCAL_PORT)
    elif(vnc_port and connect_vnc):
        StartVnc(vnc_port, instance.display)

    device_dict = {
        constants.IP: instance.ip,
        constants.INSTANCE_NAME: instance.name,
        constants.VNC_PORT: vnc_port,
        constants.ADB_PORT: adb_port
    }

    if vnc_port and adb_port:
        reconnect_report.AddData(key="devices", value=device_dict)
    else:
        # We use 'ps aux' to grep adb/vnc fowarding port from ssh tunnel
        # command. Therefore we report failure here if no vnc_port and
        # adb_port found.
        reconnect_report.AddData(key="device_failing_reconnect", value=device_dict)
        reconnect_report.AddError(instance.name)


def Run(args):
    """Run reconnect.

    Args:
        args: Namespace object from argparse.parse_args.
    """
    cfg = config.GetAcloudConfig(args)
    instances_to_reconnect = []
    if args.instance_names is not None:
        # user input instance name to get instance object.
        instances_to_reconnect = list_instance.GetInstancesFromInstanceNames(
            cfg, args.instance_names)
    if not instances_to_reconnect:
        instances_to_reconnect = list_instance.ChooseInstances(cfg, args.all)

    reconnect_report = report.Report(command="reconnect")
    for instance in instances_to_reconnect:
        if instance.avd_type not in utils.AVD_PORT_DICT:
            utils.PrintColorString("Skipping reconnect of instance %s due to "
                                   "unknown avd type (%s)." %
                                   (instance.name, instance.avd_type),
                                   utils.TextColors.WARNING)
            continue
        if not instance.islocal:
            AddPublicSshRsaToInstance(cfg, constants.GCE_USER, instance.name)
        ReconnectInstance(cfg.ssh_private_key_path,
                          instance,
                          reconnect_report,
                          cfg.extra_args_ssh_tunnel,
                          connect_vnc=(args.autoconnect is True))

    utils.PrintDeviceSummary(reconnect_report)
