#!/usr/bin/env python
#
# 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"""AVDSpec class.

AVDSpec will take in args from the user and be the main data type that will
get passed into the create classes. The inferring magic will happen within
initialization of AVDSpec (like LKGB build id, image branch, etc).
"""

import glob
import logging
import os
import re
import subprocess
import tempfile

from acloud import errors
from acloud.create import create_common
from acloud.internal import constants
from acloud.internal.lib import android_build_client
from acloud.internal.lib import auth
from acloud.internal.lib import utils
from acloud.public import config

# Default values for build target.
_BRANCH_RE = re.compile(r"^Manifest branch: (?P<branch>.+)")
_BUILD_TARGET = "build_target"
_BUILD_BRANCH = "build_branch"
_BUILD_ID = "build_id"
_COMMAND_REPO_INFO = ["repo", "info"]
_CF_ZIP_PATTERN = "*img*.zip"
_DEFAULT_BUILD_BITNESS = "x86"
_DEFAULT_BUILD_TYPE = "userdebug"
_ENV_ANDROID_PRODUCT_OUT = "ANDROID_PRODUCT_OUT"
_ENV_ANDROID_BUILD_TOP = "ANDROID_BUILD_TOP"
_GCE_LOCAL_IMAGE_CANDIDATES = ["avd-system.tar.gz",
                               "android_system_disk_syslinux.img"]
_LOCAL_ZIP_WARNING_MSG = "'adb sync' will take a long time if using images " \
                         "built with `m dist`. Building with just `m` will " \
                         "enable a faster 'adb sync' process."
_RE_ANSI_ESCAPE = re.compile(r"(\x9B|\x1B\[)[0-?]*[ -\/]*[@-~]")
_RE_FLAVOR = re.compile(r"^.+_(?P<flavor>.+)-img.+")
_RE_GBSIZE = re.compile(r"^(?P<gb_size>\d+)g$", re.IGNORECASE)
_RE_INT = re.compile(r"^\d+$")
_RE_RES = re.compile(r"^(?P<x_res>\d+)x(?P<y_res>\d+)$")
_X_RES = "x_res"
_Y_RES = "y_res"
_COMMAND_GIT_REMOTE = ["git", "remote"]

# The branch prefix is necessary for the Android Build system to know what we're
# talking about. For instance, on an aosp remote repo in the master branch,
# Android Build will recognize it as aosp-master.
_BRANCH_PREFIX = {"aosp": "aosp-"}
_DEFAULT_BRANCH_PREFIX = "git_"

# The target prefix is needed to help concoct the lunch target name given a
# the branch, avd type and device flavor:
# aosp, cf and phone -> aosp_cf_x86_phone.
_BRANCH_TARGET_PREFIX = {"aosp": "aosp_"}

logger = logging.getLogger(__name__)


def EscapeAnsi(line):
    """Remove ANSI control sequences (e.g. temrinal color codes...)

    Args:
        line: String, one line of command output.

    Returns:
        String without ANSI code.
    """
    return _RE_ANSI_ESCAPE.sub('', line)


class AVDSpec(object):
    """Class to store data on the type of AVD to create."""

    def __init__(self, args):
        """Process the args into class vars.

        Args:
            args: Namespace object from argparse.parse_args.
        """
        # Let's define the private class vars here and then process the user
        # args afterwards.
        self._client_adb_port = args.adb_port
        self._autoconnect = None
        self._report_internal_ip = None
        self._avd_type = None
        self._flavor = None
        self._image_source = None
        self._instance_type = None
        self._kernel_build_id = None
        self._local_image_dir = None
        self._local_image_artifact = None
        self._image_download_dir = None
        self._num_of_instances = None
        self._remote_image = None
        self._hw_property = None
        # Create config instance for android_build_client to query build api.
        self._cfg = config.GetAcloudConfig(args)
        # Reporting args.
        self._serial_log_file = None
        self._logcat_file = None
        # gpu and emulator_build_id is only used for goldfish avd_type.
        self._gpu = None
        self._emulator_build_id = None

        self._ProcessArgs(args)

    def __repr__(self):
        """Let's make it easy to see what this class is holding."""
        # TODO: I'm pretty sure there's a better way to do this, but I'm not
        # quite sure what that would be.
        representation = []
        representation.append("")
        representation.append(" - instance_type: %s" % self._instance_type)
        representation.append(" - avd type: %s" % self._avd_type)
        representation.append(" - flavor: %s" % self._flavor)
        representation.append(" - autoconnect: %s" % self._autoconnect)
        representation.append(" - num of instances requested: %s" %
                              self._num_of_instances)
        representation.append(" - image source type: %s" %
                              self._image_source)
        image_summary = None
        image_details = None
        if self._image_source == constants.IMAGE_SRC_LOCAL:
            image_summary = "local image dir"
            image_details = self._local_image_dir
        elif self._image_source == constants.IMAGE_SRC_REMOTE:
            image_summary = "remote image details"
            image_details = self._remote_image
        representation.append(" - %s: %s" % (image_summary, image_details))
        representation.append(" - hw properties: %s" %
                              self._hw_property)
        return "\n".join(representation)

    def _ProcessArgs(self, args):
        """Main entry point to process args for the different type of args.

        Split up the arg processing into related areas (image, instance type,
        etc) so that we don't have one huge monolilthic method that does
        everything. It makes it easier to review, write tests, and maintain.

        Args:
            args: Namespace object from argparse.parse_args.
        """
        self._ProcessMiscArgs(args)
        self._ProcessImageArgs(args)
        self._ProcessHWPropertyArgs(args)

    def _ProcessImageArgs(self, args):
        """ Process Image Args.

        Args:
            args: Namespace object from argparse.parse_args.
        """
        # If user didn't specify --local-image, infer remote image args
        if args.local_image == "":
            self._image_source = constants.IMAGE_SRC_REMOTE
            self._ProcessRemoteBuildArgs(args)
        else:
            self._image_source = constants.IMAGE_SRC_LOCAL
            self._ProcessLocalImageArgs(args)

        self.image_download_dir = (
            args.image_download_dir if args.image_download_dir
            else tempfile.gettempdir())

    @staticmethod
    def _ParseHWPropertyStr(hw_property_str):
        """Parse string to dict.

        Args:
            hw_property_str: A hw properties string.

        Returns:
            Dict converted from a string.

        Raises:
            error.MalformedHWPropertyError: If hw_property_str is malformed.
        """
        hw_dict = create_common.ParseHWPropertyArgs(hw_property_str)
        arg_hw_properties = {}
        for key, value in hw_dict.items():
            # Parsing HW properties int to avdspec.
            if key == constants.HW_ALIAS_RESOLUTION:
                match = _RE_RES.match(value)
                if match:
                    arg_hw_properties[_X_RES] = match.group("x_res")
                    arg_hw_properties[_Y_RES] = match.group("y_res")
                else:
                    raise errors.InvalidHWPropertyError(
                        "[%s] is an invalid resolution. Example:1280x800" % value)
            elif key in [constants.HW_ALIAS_MEMORY, constants.HW_ALIAS_DISK]:
                match = _RE_GBSIZE.match(value)
                if match:
                    arg_hw_properties[key] = str(
                        int(match.group("gb_size")) * 1024)
                else:
                    raise errors.InvalidHWPropertyError(
                        "Expected gb size.[%s] is not allowed. Example:4g" % value)
            elif key in [constants.HW_ALIAS_CPUS, constants.HW_ALIAS_DPI]:
                if not _RE_INT.match(value):
                    raise errors.InvalidHWPropertyError(
                        "%s value [%s] is not an integer." % (key, value))
                arg_hw_properties[key] = value

        return arg_hw_properties

    def _ProcessHWPropertyArgs(self, args):
        """Get the HW properties from argparse.parse_args.

        This method will initialize _hw_property in the following
        manner:
        1. Get default hw properties from config.
        2. Override by hw_property args.

        Args:
            args: Namespace object from argparse.parse_args.
        """
        self._hw_property = {}
        self._hw_property = self._ParseHWPropertyStr(self._cfg.hw_property)
        logger.debug("Default hw property for [%s] flavor: %s", self._flavor,
                     self._hw_property)

        if args.hw_property:
            arg_hw_property = self._ParseHWPropertyStr(args.hw_property)
            logger.debug("Use custom hw property: %s", arg_hw_property)
            self._hw_property.update(arg_hw_property)

    def _ProcessMiscArgs(self, args):
        """These args we can take as and don't belong to a group of args.

        Args:
            args: Namespace object from argparse.parse_args.
        """
        self._autoconnect = args.autoconnect
        self._report_internal_ip = args.report_internal_ip
        self._avd_type = args.avd_type
        self._flavor = args.flavor or constants.FLAVOR_PHONE
        self._instance_type = (constants.INSTANCE_TYPE_LOCAL
                               if args.local_instance else
                               constants.INSTANCE_TYPE_REMOTE)
        self._num_of_instances = args.num
        self._kernel_build_id = args.kernel_build_id
        self._serial_log_file = args.serial_log_file
        self._logcat_file = args.logcat_file
        self._emulator_build_id = args.emulator_build_id
        self._gpu = args.gpu

    @staticmethod
    def _GetFlavorFromString(flavor_string):
        """Get flavor name from flavor string.

        Flavor string can come from the zipped image name or the lunch target.
        e.g.
        If flavor_string come from zipped name:aosp_cf_x86_phone-img-5455843.zip
        , then "phone" is the flavor.
        If flavor_string come from a lunch'd target:aosp_cf_x86_auto-userdebug,
        then "auto" is the flavor.

        Args:
            flavor_string: String which contains flavor.It can be a
                           build target or filename.

        Returns:
            String of flavor name. None if flavor can't be determined.
        """
        for flavor in constants.ALL_FLAVORS:
            if re.match(r"(.*_)?%s" % flavor, flavor_string):
                return flavor

        logger.debug("Unable to determine flavor from build target: %s",
                     flavor_string)
        return None

    def _ProcessLocalImageArgs(self, args):
        """Get local image path.

        Args:
            args: Namespace object from argparse.parse_args.
        """
        if self._avd_type == constants.TYPE_CF:
            self._ProcessCFLocalImageArgs(args.local_image, args.flavor)
        elif self._avd_type == constants.TYPE_GCE:
            self._local_image_artifact = self._GetGceLocalImagePath(
                args.local_image)
        else:
            raise errors.CreateError(
                "Local image doesn't support the AVD type: %s" % self._avd_type
            )

    @staticmethod
    def _GetGceLocalImagePath(local_image_dir):
        """Get gce local image path.

        Choose image file in local_image_dir over $ANDROID_PRODUCT_OUT.
        There are various img files so we prioritize returning the one we find
        first based in the specified order in _GCE_LOCAL_IMAGE_CANDIDATES.

        Args:
            local_image_dir: A string to specify local image dir.

        Returns:
            String, image file path if exists.

        Raises:
            errors.BootImgDoesNotExist if image doesn't exist.
        """
        # IF the user specified a file, return it
        if local_image_dir and os.path.isfile(local_image_dir):
            return local_image_dir

        # If the user didn't specify a dir, assume $ANDROID_PRODUCT_OUT
        if not local_image_dir:
            local_image_dir = utils.GetBuildEnvironmentVariable(
                _ENV_ANDROID_PRODUCT_OUT)

        for img_name in _GCE_LOCAL_IMAGE_CANDIDATES:
            full_file_path = os.path.join(local_image_dir, img_name)
            if os.path.exists(full_file_path):
                return full_file_path

        raise errors.BootImgDoesNotExist("Could not find any GCE images (%s), "
                                         "you can build them via \"m dist\"" %
                                         ", ".join(_GCE_LOCAL_IMAGE_CANDIDATES))

    def _ProcessCFLocalImageArgs(self, local_image_arg, flavor_arg):
        """Get local built image path for cuttlefish-type AVD.

        Two scenarios of using --local-image:
        - Without a following argument
          Set flavor string if the required images are in $ANDROID_PRODUCT_OUT,
        - With a following filename/dirname
          Set flavor string from the specified image/dir name.

        Args:
            local_image_arg: String of local image args.
            flavor_arg: String of flavor arg

        """
        flavor_from_build_string = None
        local_image_path = local_image_arg or utils.GetBuildEnvironmentVariable(
            _ENV_ANDROID_PRODUCT_OUT)

        if os.path.isfile(local_image_path):
            self._local_image_artifact = local_image_arg
            flavor_from_build_string = self._GetFlavorFromString(
                self._local_image_artifact)
            # Since file is provided and I assume it's a zip, so print the
            # warning message.
            utils.PrintColorString(_LOCAL_ZIP_WARNING_MSG,
                                   utils.TextColors.WARNING)
        else:
            self._local_image_dir = local_image_path
            # Since dir is provided, so checking that any images exist to ensure
            # user didn't forget to 'make' before launch AVD.
            image_list = glob.glob(os.path.join(self.local_image_dir, "*.img"))
            if not image_list:
                raise errors.GetLocalImageError(
                    "No image found(Did you choose a lunch target and run `m`?)"
                    ": %s.\n " % self.local_image_dir)

            flavor_from_build_string = self._GetFlavorFromString(
                utils.GetBuildEnvironmentVariable(constants.ENV_BUILD_TARGET))

        if flavor_from_build_string and not flavor_arg:
            self._flavor = flavor_from_build_string
            self._cfg.OverrideHwPropertyWithFlavor(flavor_from_build_string)

    def _ProcessRemoteBuildArgs(self, args):
        """Get the remote build args.

        Some of the acloud magic happens here, we will infer some of these
        values if the user hasn't specified them.

        Args:
            args: Namespace object from argparse.parse_args.
        """
        self._remote_image = {}
        self._remote_image[_BUILD_BRANCH] = args.branch
        if not self._remote_image[_BUILD_BRANCH]:
            self._remote_image[_BUILD_BRANCH] = self._GetBuildBranch(
                args.build_id, args.build_target)

        self._remote_image[_BUILD_TARGET] = args.build_target
        if not self._remote_image[_BUILD_TARGET]:
            self._remote_image[_BUILD_TARGET] = self._GetBuildTarget(args)
        else:
            # If flavor isn't specified, try to infer it from build target,
            # if we can't, just default to phone flavor.
            self._flavor = args.flavor or self._GetFlavorFromString(
                self._remote_image[_BUILD_TARGET]) or constants.FLAVOR_PHONE
            # infer avd_type from build_target.
            for avd_type, avd_type_abbr in constants.AVD_TYPES_MAPPING.items():
                if re.match(r"(.*_)?%s_" % avd_type_abbr,
                            self._remote_image[_BUILD_TARGET]):
                    self._avd_type = avd_type
                    break

        self._remote_image[_BUILD_ID] = args.build_id
        if not self._remote_image[_BUILD_ID]:
            build_client = android_build_client.AndroidBuildClient(
                auth.CreateCredentials(self._cfg))
            self._remote_image[constants.BUILD_ID] = build_client.GetLKGB(
                self._remote_image[constants.BUILD_TARGET],
                self._remote_image[constants.BUILD_BRANCH])

    @staticmethod
    def _GetGitRemote():
        """Get the remote repo.

        We'll go to a project we know exists (tools/acloud) and grab the git
        remote output from there.

        Returns:
            remote: String, git remote (e.g. "aosp").
        """
        try:
            android_build_top = os.environ[constants.ENV_ANDROID_BUILD_TOP]
        except KeyError:
            raise errors.GetAndroidBuildEnvVarError(
                "Could not get environment var: %s\n"
                "Try to run '#source build/envsetup.sh && lunch <target>'"
                % _ENV_ANDROID_BUILD_TOP
            )

        acloud_project = os.path.join(android_build_top, "tools", "acloud")
        return EscapeAnsi(subprocess.check_output(_COMMAND_GIT_REMOTE,
                                                  cwd=acloud_project).strip())

    def _GetBuildBranch(self, build_id, build_target):
        """Infer build branch if user didn't specify branch name.

        Args:
            build_id: String, Build id, e.g. "2263051", "P2804227"
            build_target: String, the build target, e.g. cf_x86_phone-userdebug

        Returns:
            String, name of build branch.
        """
        # Infer branch from build_target and build_id
        if build_id and build_target:
            build_client = android_build_client.AndroidBuildClient(
                auth.CreateCredentials(self._cfg))
            return build_client.GetBranch(build_target, build_id)

        return self._GetBranchFromRepo()

    def _GetBranchFromRepo(self):
        """Get branch information from command "repo info".

        Returns:
            branch: String, git branch name. e.g. "aosp-master"

        Raises:
            errors.GetBranchFromRepoInfoError: Can't get branch from
            output of "repo info".
        """
        repo_output = subprocess.check_output(_COMMAND_REPO_INFO)
        for line in repo_output.splitlines():
            match = _BRANCH_RE.match(EscapeAnsi(line))
            if match:
                branch_prefix = _BRANCH_PREFIX.get(self._GetGitRemote(),
                                                   _DEFAULT_BRANCH_PREFIX)
                return branch_prefix + match.group("branch")
        raise errors.GetBranchFromRepoInfoError(
            "No branch mentioned in repo info output: %s" % repo_output
        )

    def _GetBuildTarget(self, args):
        """Infer build target if user doesn't specified target name.

        Target = {REPO_PREFIX}{avd_type}_{bitness}_{flavor}-
            {DEFAULT_BUILD_TARGET_TYPE}.
        Example target: aosp_cf_x86_phone-userdebug

        Args:
            args: Namespace object from argparse.parse_args.

        Returns:
            build_target: String, name of build target.
        """
        branch = re.split("-|_", self._remote_image[_BUILD_BRANCH])[0]
        return "%s%s_%s_%s-%s" % (
            _BRANCH_TARGET_PREFIX.get(branch, ""),
            constants.AVD_TYPES_MAPPING[args.avd_type],
            _DEFAULT_BUILD_BITNESS, self._flavor,
            _DEFAULT_BUILD_TYPE)

    @property
    def instance_type(self):
        """Return the instance type."""
        return self._instance_type

    @property
    def image_source(self):
        """Return the image type."""
        return self._image_source

    @property
    def hw_property(self):
        """Return the hw_property."""
        return self._hw_property

    @property
    def local_image_dir(self):
        """Return local image dir."""
        return self._local_image_dir

    @property
    def local_image_artifact(self):
        """Return local image artifact."""
        return self._local_image_artifact

    @property
    def avd_type(self):
        """Return the avd type."""
        return self._avd_type

    @property
    def autoconnect(self):
        """Return autoconnect."""
        return self._autoconnect

    @property
    def remote_image(self):
        """Return the remote image."""
        return self._remote_image

    @property
    def num(self):
        """Return num of instances."""
        return self._num_of_instances

    @property
    def report_internal_ip(self):
        """Return report internal ip."""
        return self._report_internal_ip

    @property
    def kernel_build_id(self):
        """Return kernel build id."""
        return self._kernel_build_id

    @property
    def flavor(self):
        """Return flavor."""
        return self._flavor

    @property
    def cfg(self):
        """Return cfg instance."""
        return self._cfg

    @property
    def image_download_dir(self):
        """Return image download dir."""
        return self._image_download_dir

    @image_download_dir.setter
    def image_download_dir(self, value):
        """Set image download dir."""
        self._image_download_dir = value

    @property
    def serial_log_file(self):
        """Return serial log file path."""
        return self._serial_log_file

    @property
    def logcat_file(self):
        """Return logcat file path."""
        return self._logcat_file

    @property
    def gpu(self):
        """Return gpu."""
        return self._gpu

    @property
    def emulator_build_id(self):
        """Return emulator_build_id."""
        return self._emulator_build_id

    @property
    def client_adb_port(self):
        """Return the client adb port."""
        return self._client_adb_port
