# Copyright 2015 The ChromiumOS Authors
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

"""Install/copy the image to the device."""

from __future__ import division

import logging
import os
import re
import shutil

from chromite.cli import device_imager
from chromite.cli.cros import cros_chrome_sdk
from chromite.lib import commandline
from chromite.lib import cros_build_lib
from chromite.lib import dev_server_wrapper as ds_wrapper
from chromite.lib import operation
from chromite.lib import osutils
from chromite.lib import path_util
from chromite.lib import remote_access


def GetDefaultBoard():
    """Look up default board.

    In a chrome checkout, return $SDK_BOARD. In a chromeos checkout,
    return the contents of .default_board.
    """
    if path_util.DetermineCheckout().type == path_util.CHECKOUT_TYPE_GCLIENT:
        return os.environ.get(cros_chrome_sdk.SDKFetcher.SDK_BOARD_ENV)
    return cros_build_lib.GetDefaultBoard()


class UsbImagerOperation(operation.ProgressBarOperation):
    """Progress bar for flashing image to operation."""

    def __init__(self, image):
        super().__init__()
        self._size = os.path.getsize(image)
        self._transferred = 0
        self._bytes = re.compile(r"(\d+) bytes")

    def _GetDDPid(self):
        """Get the Pid of dd."""
        try:
            pids = cros_build_lib.run(
                ["pgrep", "dd"],
                capture_output=True,
                print_cmd=False,
                encoding="utf-8",
            ).stdout
            for pid in pids.splitlines():
                if osutils.IsChildProcess(int(pid), name="dd"):
                    return int(pid)
            return -1
        except cros_build_lib.RunCommandError:
            # If dd isn't still running, then we assume that it is finished.
            return -1

    def _PingDD(self, dd_pid):
        """Send USR1 signal to dd to get status update."""
        try:
            cmd = ["kill", "-USR1", str(dd_pid)]
            cros_build_lib.sudo_run(cmd, print_cmd=False)
        except cros_build_lib.RunCommandError:
            # Here we assume that dd finished in the background.
            return

    def ParseOutput(self, output=None):
        """Parse the output of dd to update progress bar."""
        dd_pid = self._GetDDPid()
        if dd_pid == -1:
            return

        self._PingDD(dd_pid)

        if output is None:
            stdout = self._stdout.read()
            stderr = self._stderr.read()
            output = stdout + stderr

        match = self._bytes.search(output)
        if match:
            self._transferred = int(match.groups()[0])

        self.ProgressBar(self._transferred / self._size)


def _IsFilePathGPTDiskImage(file_path, require_pmbr=False):
    """Determines if a file is a valid GPT disk.

    Args:
        file_path: Path to the file to test.
        require_pmbr: Whether to require a PMBR in LBA0.
    """
    if os.path.isfile(file_path):
        with open(file_path, "rb") as image_file:
            if require_pmbr:
                # Seek to the end of LBA0 and look for the PMBR boot signature.
                image_file.seek(0x1FE)
                if image_file.read(2) != b"\x55\xaa":
                    return False
                # Current file position is start of LBA1 now.
            else:
                # Seek to LBA1 where the GPT starts.
                image_file.seek(0x200)

            # See if there's a GPT here.
            if image_file.read(8) == b"EFI PART":
                return True

    return False


def _ChooseImageFromDirectory(dir_path):
    """Lists all image files in |dir_path| and ask user to select one.

    Args:
        dir_path: Path to the directory.
    """
    images = sorted(
        [
            x
            for x in os.listdir(dir_path)
            if _IsFilePathGPTDiskImage(os.path.join(dir_path, x))
        ]
    )
    idx = 0
    if not images:
        raise ValueError("No image found in %s." % dir_path)
    elif len(images) > 1:
        idx = cros_build_lib.GetChoice(
            "Multiple images found in %s. Please select one to continue:"
            % ((dir_path,)),
            images,
        )

    return os.path.join(dir_path, images[idx])


class FlashError(Exception):
    """Thrown when there is an unrecoverable error during flash."""


class USBImager:
    """Copy image to the target removable device."""

    def __init__(self, device, board, image, version, debug=False, yes=False):
        """Initializes USBImager."""
        self.device = device
        self.board = board if board else GetDefaultBoard()
        self.image = image
        self.version = version
        self.debug = debug
        self.debug_level = logging.DEBUG if debug else logging.INFO
        self.yes = yes

    def DeviceNameToPath(self, device_name):
        return "/dev/%s" % device_name

    def GetRemovableDeviceDescription(self, device):
        """Returns a informational description of the removable |device|.

        Args:
            device: the device name (e.g. sdc).

        Returns:
            A string describing |device| (e.g. Patriot Memory 7918 MB).
        """
        desc = [
            osutils.GetDeviceInfo(device, keyword="manufacturer"),
            osutils.GetDeviceInfo(device, keyword="product"),
            osutils.GetDeviceSize(self.DeviceNameToPath(device)),
            "(%s)" % self.DeviceNameToPath(device),
        ]
        return " ".join([x for x in desc if x])

    def ListAllRemovableDevices(self):
        """Returns a list of removable devices.

        Returns:
            A list of device names (e.g. ['sdb', 'sdc']).
        """
        devices = osutils.ListBlockDevices()
        removable_devices = []
        for d in devices:
            if d.TYPE == "disk" and (d.RM == "1" or d.HOTPLUG == "1"):
                removable_devices.append(d.NAME)

        return removable_devices

    def ChooseRemovableDevice(self, devices):
        """Lists all removable devices and asks user to select/confirm.

        Args:
            devices: a list of device names (e.g. ['sda', 'sdb']).

        Returns:
            The device name chosen by the user.
        """
        idx = cros_build_lib.GetChoice(
            "Removable device(s) found. Please select/confirm to continue:",
            [self.GetRemovableDeviceDescription(x) for x in devices],
        )

        return devices[idx]

    def CopyImageToDevice(self, image, device):
        """Copies |image| to the removable |device|.

        Args:
            image: Path to the image to copy.
            device: Device to copy to.
        """
        cmd = [
            "dd",
            "if=%s" % image,
            "of=%s" % device,
            "bs=4M",
            "iflag=fullblock",
            "oflag=direct",
            "conv=fdatasync",
        ]
        if logging.getLogger().getEffectiveLevel() <= logging.NOTICE:
            op = UsbImagerOperation(image)
            op.Run(
                cros_build_lib.sudo_run,
                cmd,
                debug_level=logging.NOTICE,
                encoding="utf-8",
                update_period=0.5,
            )
        else:
            cros_build_lib.sudo_run(
                cmd,
                debug_level=logging.NOTICE,
                print_cmd=logging.getLogger().getEffectiveLevel()
                < logging.NOTICE,
            )

        # dd likely didn't put the backup GPT in the last block. sfdisk fixes
        # this up for us with a 'write' command, so we have a
        # standards-conforming GPT. Ignore errors because sfdisk (util-linux <
        # v2.32) isn't always happy to fix GPT correctness issues.
        cros_build_lib.sudo_run(
            ["sfdisk", device],
            input="write\n",
            check=False,
            debug_level=self.debug_level,
        )

        cros_build_lib.sudo_run(
            ["partx", "-u", device], debug_level=self.debug_level
        )
        osutils.sync_storage(device, data_only=True, sudo=True)

    def _GetImagePath(self):
        """Returns the image path to use."""
        image_path = None
        if os.path.isfile(self.image):
            if not self.yes and not _IsFilePathGPTDiskImage(self.image):
                # TODO(wnwen): Open the tarball and if there is just one file in
                #   it, use that instead. Existing code in upload_symbols.py.
                if cros_build_lib.BooleanPrompt(
                    prolog="The given image file is not a valid disk image. "
                    "Perhaps you forgot to untar it.",
                    prompt="Terminate the current flash process?",
                ):
                    raise FlashError("Update terminated by user.")
            image_path = self.image
        elif os.path.isdir(self.image):
            # Ask user which image (*.bin) in the folder to use.
            image_path = _ChooseImageFromDirectory(self.image)
        else:
            # Translate the xbuddy path to get the exact image to use.
            _, image_path = ds_wrapper.GetImagePathWithXbuddy(
                self.image, self.board, self.version
            )

        logging.info("Using image %s", image_path)
        return image_path

    def Run(self):
        """Image the removable device."""
        devices = self.ListAllRemovableDevices()

        if self.device:
            # If user specified a device path, check if it exists.
            if not os.path.exists(self.device):
                raise FlashError("Device path %s does not exist." % self.device)

            # Then check if it is removable.
            if self.device not in [self.DeviceNameToPath(x) for x in devices]:
                msg = "%s is not a removable device." % self.device
                if not (
                    self.yes
                    or cros_build_lib.BooleanPrompt(default=False, prolog=msg)
                ):
                    raise FlashError(
                        "You can specify usb:// to choose from a list of "
                        "removable devices."
                    )
        target = None
        if self.device:
            # Get device name from path (e.g. sdc in /dev/sdc).
            target = self.device.rsplit(os.path.sep, 1)[-1]
        elif devices:
            # Ask user to choose from the list.
            target = self.ChooseRemovableDevice(devices)
        else:
            raise FlashError("No removable devices detected.")

        image_path = self._GetImagePath()
        device = self.DeviceNameToPath(target)

        device_size_bytes = osutils.GetDeviceSize(device, in_bytes=True)
        image_size_bytes = os.path.getsize(image_path)
        if device_size_bytes < image_size_bytes:
            raise FlashError(
                "Removable device %s has less storage (%d) than the image size "
                "(%d)." % (device, device_size_bytes, image_size_bytes)
            )

        try:
            self.CopyImageToDevice(image_path, device)
        except cros_build_lib.RunCommandError:
            logging.error(
                "Failed copying image to device %s",
                self.DeviceNameToPath(target),
            )


class FileImager(USBImager):
    """Copy image to the target path."""

    def Run(self):
        """Copy the image to the path specified by self.device."""
        if not os.path.isdir(os.path.dirname(self.device)):
            raise FlashError(
                "Parent of path %s is not a directory." % self.device
            )

        image_path = self._GetImagePath()
        if os.path.isdir(self.device):
            logging.info(
                "Copying to %s",
                os.path.join(self.device, os.path.basename(image_path)),
            )
        else:
            logging.info("Copying to %s", self.device)
        try:
            shutil.copy(image_path, self.device)
        except IOError:
            logging.error(
                "Failed to copy image %s to %s", image_path, self.device
            )


# TODO(b/190631159, b/196056723): Change default of no_minios_update to |False|.
def Flash(
    device,
    image,
    board=None,
    version=None,
    no_rootfs_update=False,
    no_stateful_update=False,
    no_minios_update=True,
    clobber_stateful=False,
    reboot=True,
    ssh_private_key=None,
    ping=True,
    disable_rootfs_verification=False,
    clear_cache=False,
    yes=False,
    force=False,
    debug=False,
    clear_tpm_owner=False,
    delta=False,
    reboot_timeout=None,
):
    """Flashes a device, USB drive, or file with an image.

    This provides functionality common to `cros flash` and `brillo flash`
    so that they can parse the commandline separately but still use the
    same underlying functionality.

    Args:
        device: commandline.Device object; None to use the default device.
        image: Path (string) to the update image. Can be a local or xbuddy path;
            non-existent local paths are converted to xbuddy.
        board: Board to use; None to automatically detect.
        no_rootfs_update: Don't update rootfs partition; SSH |device| scheme
            only.
        no_stateful_update: Don't update stateful partition; SSH |device| scheme
            only.
        no_minios_update: Don't update miniOS partition; SSH |device| scheme
            only.
        clobber_stateful: Clobber stateful partition; SSH |device| scheme only.
        clear_tpm_owner: Clear the TPM owner on reboot; SSH |device| scheme
            only.
        reboot: Reboot device after update; SSH |device| scheme only.
        ssh_private_key: Path to an SSH private key file; None to use test keys.
        ping: Ping the device before attempting update; SSH |device| scheme
            only.
        disable_rootfs_verification: Remove rootfs verification after update;
            SSH |device| scheme only.
        clear_cache: Clear the devserver static directory.
        yes: Assume "yes" for any prompt.
        force: Ignore confidence checks and prompts. Overrides |yes| if True.
        debug: Print additional debugging messages.
        version: Default version.
        delta: Whether to use delta compression when transferring image bytes.
        reboot_timeout: The timeout for reboot.

    Raises:
        FlashError: An unrecoverable error occurred.
        ValueError: Invalid parameter combination.
    """
    if force:
        yes = True

    if clear_cache:
        ds_wrapper.DevServerWrapper.WipeStaticDirectory()
    ds_wrapper.DevServerWrapper.CreateStaticDirectory()

    # The user may not have specified a source image, use version as the
    # default.
    image = image or version
    if not device or device.scheme == commandline.DEVICE_SCHEME_SSH:
        if device:
            hostname, port = device.hostname, device.port
        else:
            hostname, port = None, None

        with remote_access.ChromiumOSDeviceHandler(
            hostname, port=port, private_key=ssh_private_key, ping=ping
        ) as device_p:
            device_imager.DeviceImager(
                device_p,
                image,
                board=board,
                version=version,
                no_rootfs_update=no_rootfs_update,
                no_stateful_update=no_stateful_update,
                no_minios_update=no_minios_update,
                no_reboot=not reboot,
                disable_verification=disable_rootfs_verification,
                clobber_stateful=clobber_stateful,
                clear_tpm_owner=clear_tpm_owner,
                delta=delta,
                reboot_timeout=reboot_timeout,
            ).Run()
    elif device.scheme == commandline.DEVICE_SCHEME_USB:
        path = osutils.ExpandPath(device.path) if device.path else ""
        logging.info("Preparing to image the removable device %s", path)
        imager = USBImager(path, board, image, version, debug=debug, yes=yes)
        imager.Run()
    elif device.scheme == commandline.DEVICE_SCHEME_FILE:
        logging.info("Preparing to copy image to %s", device.path)
        imager = FileImager(
            device.path, board, image, version, debug=debug, yes=yes
        )
        imager.Run()
