# -*- coding: utf-8 -*-
# Copyright 2013 The ChromiumOS Authors
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

"""Utilities for toolchain build."""


__author__ = "asharif@google.com (Ahmad Sharif)"

from contextlib import contextmanager
import os
import re
import shutil
import sys

from cros_utils import command_executer
from cros_utils import logger


CHROMEOS_SCRIPTS_DIR = "/mnt/host/source/src/scripts"
TOOLCHAIN_UTILS_PATH = (
    "/mnt/host/source/src/third_party/toolchain-utils/"
    "cros_utils/toolchain_utils.sh"
)


def GetChromeOSVersionFromLSBVersion(lsb_version):
    """Get Chromeos version from Lsb version."""
    ce = command_executer.GetCommandExecuter()
    command = (
        "git ls-remote "
        "https://chromium.googlesource.com/chromiumos/manifest.git "
        "refs/heads/release-R*"
    )
    ret, out, _ = ce.RunCommandWOutput(command, print_to_console=False)
    assert ret == 0, "Command %s failed" % command
    lower = []
    for line in out.splitlines():
        mo = re.search(r"refs/heads/release-R(\d+)-(\d+)\.B", line)
        if mo:
            revision = int(mo.group(1))
            build = int(mo.group(2))
            lsb_build = int(lsb_version.split(".")[0])
            if lsb_build > build:
                lower.append(revision)
    lower = sorted(lower)
    if lower:
        return "R%d-%s" % (lower[-1] + 1, lsb_version)
    else:
        return "Unknown"


def ApplySubs(string, *substitutions):
    for pattern, replacement in substitutions:
        string = re.sub(pattern, replacement, string)
    return string


def UnitToNumber(unit_num, base=1000):
    """Convert a number with unit to float."""
    unit_dict = {"kilo": base, "mega": base ** 2, "giga": base ** 3}
    unit_num = unit_num.lower()
    mo = re.search(r"(\d*)(.+)?", unit_num)
    number = mo.group(1)
    unit = mo.group(2)
    if not unit:
        return float(number)
    for k, v in unit_dict.items():
        if k.startswith(unit):
            return float(number) * v
    raise RuntimeError("Unit: %s not found in byte: %s!" % (unit, unit_num))


def GetFilenameFromString(string):
    return ApplySubs(
        string,
        (r"/", "__"),
        (r"\s", "_"),
        (r'[\\$="?^]', ""),
    )


def GetRoot(scr_name):
    """Break up pathname into (dir+name)."""
    abs_path = os.path.abspath(scr_name)
    return (os.path.dirname(abs_path), os.path.basename(abs_path))


def GetChromeOSKeyFile(chromeos_root):
    return os.path.join(
        chromeos_root,
        "chromite",
        "ssh_keys",
        "testing_rsa",
    )


def GetChrootPath(chromeos_root):
    return os.path.join(chromeos_root, "chroot")


def GetInsideChrootPath(chromeos_root, file_path):
    if not file_path.startswith(GetChrootPath(chromeos_root)):
        raise RuntimeError(
            "File: %s doesn't seem to be in the chroot: %s"
            % (file_path, chromeos_root)
        )
    return file_path[len(GetChrootPath(chromeos_root)) :]


def GetOutsideChrootPath(chromeos_root, file_path):
    return os.path.join(GetChrootPath(chromeos_root), file_path.lstrip("/"))


def FormatQuotedCommand(command):
    return ApplySubs(command, ('"', r"\""))


def FormatCommands(commands):
    return ApplySubs(
        str(commands), ("&&", "&&\n"), (";", ";\n"), (r"\n+\s*", "\n")
    )


def GetImageDir(chromeos_root, board):
    return os.path.join(chromeos_root, "src", "build", "images", board)


def LabelLatestImage(chromeos_root, board, label, vanilla_path=None):
    image_dir = GetImageDir(chromeos_root, board)
    latest_image_dir = os.path.join(image_dir, "latest")
    latest_image_dir = os.path.realpath(latest_image_dir)
    latest_image_dir = os.path.basename(latest_image_dir)
    retval = 0
    with WorkingDirectory(image_dir):
        command = "ln -sf -T %s %s" % (latest_image_dir, label)
        ce = command_executer.GetCommandExecuter()
        retval = ce.RunCommand(command)
        if retval:
            return retval
        if vanilla_path:
            command = "ln -sf -T %s %s" % (vanilla_path, "vanilla")
            retval2 = ce.RunCommand(command)
            return retval2
    return retval


def DoesLabelExist(chromeos_root, board, label):
    image_label = os.path.join(GetImageDir(chromeos_root, board), label)
    return os.path.exists(image_label)


def GetBuildPackagesCommand(board, usepkg=False, debug=False):
    if usepkg:
        usepkg_flag = "--usepkg"
    else:
        usepkg_flag = "--nousepkg"
    if debug:
        withdebug_flag = "--withdebug"
    else:
        withdebug_flag = "--nowithdebug"
    return (
        "%s/build_packages %s --withdev --withtest --withautotest "
        "--skip_toolchain_update %s --board=%s "
        "--accept_licenses=@CHROMEOS"
        % (CHROMEOS_SCRIPTS_DIR, usepkg_flag, withdebug_flag, board)
    )


def GetBuildImageCommand(board, dev=False):
    dev_args = ""
    if dev:
        dev_args = "--noenable_rootfs_verification --disk_layout=2gb-rootfs"
    return "%s/build_image --board=%s %s test" % (
        CHROMEOS_SCRIPTS_DIR,
        board,
        dev_args,
    )


def GetSetupBoardCommand(board, usepkg=None, force=None):
    """Get setup_board command."""
    options = []

    if usepkg:
        options.append("--usepkg")
    else:
        options.append("--nousepkg")

    if force:
        options.append("--force")

    options.append("--accept-licenses=@CHROMEOS")

    return "setup_board --board=%s %s" % (board, " ".join(options))


def CanonicalizePath(path):
    path = os.path.expanduser(path)
    path = os.path.realpath(path)
    return path


def GetCtargetFromBoard(board, chromeos_root):
    """Get Ctarget from board."""
    base_board = board.split("_")[0]
    command = "source %s; get_ctarget_from_board %s" % (
        TOOLCHAIN_UTILS_PATH,
        base_board,
    )
    ce = command_executer.GetCommandExecuter()
    ret, out, _ = ce.ChrootRunCommandWOutput(chromeos_root, command)
    if ret != 0:
        raise ValueError("Board %s is invalid!" % board)
    # Remove ANSI escape sequences.
    out = StripANSIEscapeSequences(out)
    return out.strip()


def GetArchFromBoard(board, chromeos_root):
    """Get Arch from board."""
    base_board = board.split("_")[0]
    command = "source %s; get_board_arch %s" % (
        TOOLCHAIN_UTILS_PATH,
        base_board,
    )
    ce = command_executer.GetCommandExecuter()
    ret, out, _ = ce.ChrootRunCommandWOutput(chromeos_root, command)
    if ret != 0:
        raise ValueError("Board %s is invalid!" % board)
    # Remove ANSI escape sequences.
    out = StripANSIEscapeSequences(out)
    return out.strip()


def GetGccLibsDestForBoard(board, chromeos_root):
    """Get gcc libs destination from board."""
    arch = GetArchFromBoard(board, chromeos_root)
    if arch == "x86":
        return "/build/%s/usr/lib/gcc/" % board
    if arch == "amd64":
        return "/build/%s/usr/lib64/gcc/" % board
    if arch == "arm":
        return "/build/%s/usr/lib/gcc/" % board
    if arch == "arm64":
        return "/build/%s/usr/lib/gcc/" % board
    raise ValueError("Arch %s is invalid!" % arch)


def StripANSIEscapeSequences(string):
    string = re.sub(r"\x1b\[[0-9]*[a-zA-Z]", "", string)
    return string


def GetChromeSrcDir():
    return "var/cache/distfiles/target/chrome-src/src"


def GetEnvStringFromDict(env_dict):
    return " ".join(['%s="%s"' % var for var in env_dict.items()])


def MergeEnvStringWithDict(env_string, env_dict, prepend=True):
    """Merge env string with dict."""
    if not env_string.strip():
        return GetEnvStringFromDict(env_dict)
    override_env_list = []
    ce = command_executer.GetCommandExecuter()
    for k, v in env_dict.items():
        v = v.strip("\"'")
        if prepend:
            new_env = '%s="%s $%s"' % (k, v, k)
        else:
            new_env = '%s="$%s %s"' % (k, k, v)
        command = "; ".join([env_string, new_env, "echo $%s" % k])
        ret, out, _ = ce.RunCommandWOutput(command)
        override_env_list.append("%s=%r" % (k, out.strip()))
    ret = env_string + " " + " ".join(override_env_list)
    return ret.strip()


def GetAllImages(chromeos_root, board):
    ce = command_executer.GetCommandExecuter()
    command = "find %s/src/build/images/%s -name chromiumos_test_image.bin" % (
        chromeos_root,
        board,
    )
    ret, out, _ = ce.RunCommandWOutput(command)
    assert ret == 0, "Could not run command: %s" % command
    return out.splitlines()


def IsFloat(text):
    if text is None:
        return False
    try:
        float(text)
        return True
    except ValueError:
        return False


def RemoveChromeBrowserObjectFiles(chromeos_root, board):
    """Remove any object files from all the posible locations."""
    out_dir = os.path.join(
        GetChrootPath(chromeos_root),
        "var/cache/chromeos-chrome/chrome-src/src/out_%s" % board,
    )
    if os.path.exists(out_dir):
        shutil.rmtree(out_dir)
        logger.GetLogger().LogCmd("rm -rf %s" % out_dir)
    out_dir = os.path.join(
        GetChrootPath(chromeos_root),
        "var/cache/chromeos-chrome/chrome-src-internal/src/out_%s" % board,
    )
    if os.path.exists(out_dir):
        shutil.rmtree(out_dir)
        logger.GetLogger().LogCmd("rm -rf %s" % out_dir)


@contextmanager
def WorkingDirectory(new_dir):
    """Get the working directory."""
    old_dir = os.getcwd()
    if old_dir != new_dir:
        msg = "cd %s" % new_dir
        logger.GetLogger().LogCmd(msg)
    os.chdir(new_dir)
    yield new_dir
    if old_dir != new_dir:
        msg = "cd %s" % old_dir
        logger.GetLogger().LogCmd(msg)
    os.chdir(old_dir)


def HasGitStagedChanges(git_dir):
    """Return True if git repository has staged changes."""
    command = f"cd {git_dir} && git diff --quiet --cached --exit-code HEAD"
    return command_executer.GetCommandExecuter().RunCommand(
        command, print_to_console=False
    )


def HasGitUnstagedChanges(git_dir):
    """Return True if git repository has un-staged changes."""
    command = f"cd {git_dir} && git diff --quiet --exit-code HEAD"
    return command_executer.GetCommandExecuter().RunCommand(
        command, print_to_console=False
    )


def HasGitUntrackedChanges(git_dir):
    """Return True if git repository has un-tracked changes."""
    command = (
        f"cd {git_dir} && test -z "
        "$(git ls-files --exclude-standard --others)"
    )
    return command_executer.GetCommandExecuter().RunCommand(
        command, print_to_console=False
    )


def GitGetCommitHash(git_dir, commit_symbolic_name):
    """Return githash for the symbolic git commit.

    For example, commit_symbolic_name could be
    "cros/gcc.gnu.org/branches/gcc/gcc-4_8-mobile, this function returns the git
    hash for this symbolic name.

    Args:
      git_dir: a git working tree.
      commit_symbolic_name: a symbolic name for a particular git commit.

    Returns:
      The git hash for the symbolic name or None if fails.
    """

    command = (
        f"cd {git_dir} && git log -n 1"
        f' --pretty="format:%H" {commit_symbolic_name}'
    )
    rv, out, _ = command_executer.GetCommandExecuter().RunCommandWOutput(
        command, print_to_console=False
    )
    if rv == 0:
        return out.strip()
    return None


def IsGitTreeClean(git_dir):
    """Test if git tree has no local changes.

    Args:
      git_dir: git tree directory.

    Returns:
      True if git dir is clean.
    """
    if HasGitStagedChanges(git_dir):
        logger.GetLogger().LogWarning("Git tree has staged changes.")
        return False
    if HasGitUnstagedChanges(git_dir):
        logger.GetLogger().LogWarning("Git tree has unstaged changes.")
        return False
    if HasGitUntrackedChanges(git_dir):
        logger.GetLogger().LogWarning("Git tree has un-tracked changes.")
        return False
    return True


def GetGitChangesAsList(git_dir, path=None, staged=False):
    """Get changed files as a list.

    Args:
      git_dir: git tree directory.
      path: a relative path that is part of the tree directory, could be null.
      staged: whether to include staged files as well.

    Returns:
      A list containing all the changed files.
    """
    command = f"cd {git_dir} && git diff --name-only"
    if staged:
        command += " --cached"
    if path:
        command += " -- " + path
    _, out, _ = command_executer.GetCommandExecuter().RunCommandWOutput(
        command, print_to_console=False
    )
    rv = []
    for line in out.splitlines():
        rv.append(line)
    return rv


def IsChromeOsTree(chromeos_root):
    return os.path.isdir(
        os.path.join(chromeos_root, "src/third_party/chromiumos-overlay")
    ) and os.path.isdir(os.path.join(chromeos_root, "manifest"))


def DeleteChromeOsTree(chromeos_root, dry_run=False):
    """Delete a ChromeOs tree *safely*.

    Args:
      chromeos_root: dir of the tree, could be a relative one (but be careful)
      dry_run: only prints out the command if True

    Returns:
      True if everything is ok.
    """
    if not IsChromeOsTree(chromeos_root):
        logger.GetLogger().LogWarning(
            f'"{chromeos_root}" does not seem to be a'
            " valid chromeos tree, do nothing."
        )
        return False
    cmd0 = f"cd {chromeos_root} && cros_sdk --delete"
    if dry_run:
        print(cmd0)
    else:
        if (
            command_executer.GetCommandExecuter().RunCommand(
                cmd0, print_to_console=True
            )
            != 0
        ):
            return False

    cmd1 = (
        f'export CHROMEOSDIRNAME="$(dirname $(cd {chromeos_root} && pwd))" && '
        f'export CHROMEOSBASENAME="$(basename $(cd {chromeos_root} && pwd))" && '
        "cd $CHROMEOSDIRNAME && sudo rm -fr $CHROMEOSBASENAME"
    )
    if dry_run:
        print(cmd1)
        return True

    return (
        command_executer.GetCommandExecuter().RunCommand(
            cmd1, print_to_console=True
        )
        == 0
    )


def BooleanPrompt(
    prompt="Do you want to continue?",
    default=True,
    true_value="yes",
    false_value="no",
    prolog=None,
):
    """Helper function for processing boolean choice prompts.

    Args:
      prompt: The question to present to the user.
      default: Boolean to return if the user just presses enter.
      true_value: The text to display that represents a True returned.
      false_value: The text to display that represents a False returned.
      prolog: The text to display before prompt.

    Returns:
      True or False.
    """
    true_value, false_value = true_value.lower(), false_value.lower()
    true_text, false_text = true_value, false_value
    if true_value == false_value:
        raise ValueError(
            "true_value and false_value must differ: got %r" % true_value
        )

    if default:
        true_text = true_text[0].upper() + true_text[1:]
    else:
        false_text = false_text[0].upper() + false_text[1:]

    prompt = "\n%s (%s/%s)? " % (prompt, true_text, false_text)

    if prolog:
        prompt = "\n%s\n%s" % (prolog, prompt)

    while True:
        try:
            # pylint: disable=input-builtin, bad-builtin
            response = input(prompt).lower()
        except EOFError:
            # If the user hits CTRL+D, or stdin is disabled, use the default.
            print()
            response = None
        except KeyboardInterrupt:
            # If the user hits CTRL+C, just exit the process.
            print()
            print("CTRL+C detected; exiting")
            sys.exit()

        if not response:
            return default
        if true_value.startswith(response):
            if not false_value.startswith(response):
                return True
            # common prefix between the two...
        elif false_value.startswith(response):
            return False


# pylint: disable=unused-argument
def rgb2short(r, g, b):
    """Converts RGB values to xterm-256 color."""

    redcolor = [255, 124, 160, 196, 9]
    greencolor = [255, 118, 82, 46, 10]

    if g == 0:
        return redcolor[r // 52]
    if r == 0:
        return greencolor[g // 52]
    return 4
