# Copyright 2016 Google Inc.
#
# 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.

from past.builtins import basestring

import base64
import concurrent.futures
import datetime
import io
import logging
import os
import pipes
import platform
import portpicker
import random
import re
import signal
import string
import subprocess
import threading
import time
import traceback

# File name length is limited to 255 chars on some OS, so we need to make sure
# the file names we output fits within the limit.
MAX_FILENAME_LEN = 255
# Number of times to retry to get available port
MAX_PORT_ALLOCATION_RETRY = 50

ascii_letters_and_digits = string.ascii_letters + string.digits
valid_filename_chars = "-_." + ascii_letters_and_digits

GMT_to_olson = {
    "GMT-9": "America/Anchorage",
    "GMT-8": "US/Pacific",
    "GMT-7": "US/Mountain",
    "GMT-6": "US/Central",
    "GMT-5": "US/Eastern",
    "GMT-4": "America/Barbados",
    "GMT-3": "America/Buenos_Aires",
    "GMT-2": "Atlantic/South_Georgia",
    "GMT-1": "Atlantic/Azores",
    "GMT+0": "Africa/Casablanca",
    "GMT+1": "Europe/Amsterdam",
    "GMT+2": "Europe/Athens",
    "GMT+3": "Europe/Moscow",
    "GMT+4": "Asia/Baku",
    "GMT+5": "Asia/Oral",
    "GMT+6": "Asia/Almaty",
    "GMT+7": "Asia/Bangkok",
    "GMT+8": "Asia/Hong_Kong",
    "GMT+9": "Asia/Tokyo",
    "GMT+10": "Pacific/Guam",
    "GMT+11": "Pacific/Noumea",
    "GMT+12": "Pacific/Fiji",
    "GMT+13": "Pacific/Tongatapu",
    "GMT-11": "Pacific/Midway",
    "GMT-10": "Pacific/Honolulu"
}


class Error(Exception):
    """Raised when an error occurs in a util"""


def abs_path(path):
    """Resolve the '.' and '~' in a path to get the absolute path.

    Args:
        path: The path to expand.

    Returns:
        The absolute path of the input path.
    """
    return os.path.abspath(os.path.expanduser(path))


def create_dir(path):
    """Creates a directory if it does not exist already.

    Args:
        path: The path of the directory to create.
    """
    full_path = abs_path(path)
    if not os.path.exists(full_path):
        try:
            os.makedirs(full_path)
        except OSError as e:
            # ignore the error for dir already exist.
            if e.errno != os.errno.EEXIST:
                raise


def create_alias(target_path, alias_path):
    """Creates an alias at 'alias_path' pointing to the file 'target_path'.

    On Unix, this is implemented via symlink. On Windows, this is done by
    creating a Windows shortcut file.

    Args:
        target_path: Destination path that the alias should point to.
        alias_path: Path at which to create the new alias.
    """
    if platform.system() == 'Windows' and not alias_path.endswith('.lnk'):
        alias_path += '.lnk'
    if os.path.lexists(alias_path):
        os.remove(alias_path)
    if platform.system() == 'Windows':
        from win32com import client
        shell = client.Dispatch('WScript.Shell')
        shortcut = shell.CreateShortCut(alias_path)
        shortcut.Targetpath = target_path
        shortcut.save()
    else:
        os.symlink(target_path, alias_path)


def get_current_epoch_time():
    """Current epoch time in milliseconds.

    Returns:
        An integer representing the current epoch time in milliseconds.
    """
    return int(round(time.time() * 1000))


def get_current_human_time():
    """Returns the current time in human readable format.

    Returns:
        The current time stamp in Month-Day-Year Hour:Min:Sec format.
    """
    return time.strftime("%m-%d-%Y %H:%M:%S ")


def epoch_to_human_time(epoch_time):
    """Converts an epoch timestamp to human readable time.

    This essentially converts an output of get_current_epoch_time to an output
    of get_current_human_time

    Args:
        epoch_time: An integer representing an epoch timestamp in milliseconds.

    Returns:
        A time string representing the input time.
        None if input param is invalid.
    """
    if isinstance(epoch_time, int):
        try:
            d = datetime.datetime.fromtimestamp(epoch_time / 1000)
            return d.strftime("%m-%d-%Y %H:%M:%S ")
        except ValueError:
            return None


def get_timezone_olson_id():
    """Return the Olson ID of the local (non-DST) timezone.

    Returns:
        A string representing one of the Olson IDs of the local (non-DST)
        timezone.
    """
    tzoffset = int(time.timezone / 3600)
    gmt = None
    if tzoffset <= 0:
        gmt = "GMT+{}".format(-tzoffset)
    else:
        gmt = "GMT-{}".format(tzoffset)
    return GMT_to_olson[gmt]


def find_files(paths, file_predicate):
    """Locate files whose names and extensions match the given predicate in
    the specified directories.

    Args:
        paths: A list of directory paths where to find the files.
        file_predicate: A function that returns True if the file name and
            extension are desired.

    Returns:
        A list of files that match the predicate.
    """
    file_list = []
    for path in paths:
        p = abs_path(path)
        for dirPath, _, fileList in os.walk(p):
            for fname in fileList:
                name, ext = os.path.splitext(fname)
                if file_predicate(name, ext):
                    file_list.append((dirPath, name, ext))
    return file_list


def load_file_to_base64_str(f_path):
    """Loads the content of a file into a base64 string.

    Args:
        f_path: full path to the file including the file name.

    Returns:
        A base64 string representing the content of the file in utf-8 encoding.
    """
    path = abs_path(f_path)
    with io.open(path, 'rb') as f:
        f_bytes = f.read()
        base64_str = base64.b64encode(f_bytes).decode("utf-8")
        return base64_str


def find_field(item_list, cond, comparator, target_field):
    """Finds the value of a field in a dict object that satisfies certain
    conditions.

    Args:
        item_list: A list of dict objects.
        cond: A param that defines the condition.
        comparator: A function that checks if an dict satisfies the condition.
        target_field: Name of the field whose value to be returned if an item
            satisfies the condition.

    Returns:
        Target value or None if no item satisfies the condition.
    """
    for item in item_list:
        if comparator(item, cond) and target_field in item:
            return item[target_field]
    return None


def rand_ascii_str(length):
    """Generates a random string of specified length, composed of ascii letters
    and digits.

    Args:
        length: The number of characters in the string.

    Returns:
        The random string generated.
    """
    letters = [random.choice(ascii_letters_and_digits) for _ in range(length)]
    return ''.join(letters)


# Thead/Process related functions.
def concurrent_exec(func, param_list):
    """Executes a function with different parameters pseudo-concurrently.

    This is basically a map function. Each element (should be an iterable) in
    the param_list is unpacked and passed into the function. Due to Python's
    GIL, there's no true concurrency. This is suited for IO-bound tasks.

    Args:
        func: The function that parforms a task.
        param_list: A list of iterables, each being a set of params to be
            passed into the function.

    Returns:
        A list of return values from each function execution. If an execution
        caused an exception, the exception object will be the corresponding
        result.
    """
    with concurrent.futures.ThreadPoolExecutor(max_workers=30) as executor:
        # Start the load operations and mark each future with its params
        future_to_params = {executor.submit(func, *p): p for p in param_list}
        return_vals = []
        for future in concurrent.futures.as_completed(future_to_params):
            params = future_to_params[future]
            try:
                return_vals.append(future.result())
            except Exception as exc:
                logging.exception("{} generated an exception: {}".format(
                    params, traceback.format_exc()))
                return_vals.append(exc)
        return return_vals


def run_command(cmd,
                stdout=None,
                stderr=None,
                shell=False,
                timeout=None,
                cwd=None,
                env=None):
    """Runs a command in a subprocess.

    This function is very similar to subprocess.check_output. The main
    difference is that it returns the return code and std error output as well
    as supporting a timeout parameter.

    Args:
        cmd: string or list of strings, the command to run.
            See subprocess.Popen() documentation.
        stdout: file handle, the file handle to write std out to. If None is
            given, then subprocess.PIPE is used. See subprocess.Popen()
            documentation.
        stdee: file handle, the file handle to write std err to. If None is
            given, then subprocess.PIPE is used. See subprocess.Popen()
            documentation.
        shell: bool, True to run this command through the system shell,
            False to invoke it directly. See subprocess.Popen() docs.
        timeout: float, the number of seconds to wait before timing out.
            If not specified, no timeout takes effect.
        cwd: string, the path to change the child's current directory to before
            it is executed. Note that this directory is not considered when
            searching the executable, so you can't specify the program's path
            relative to cwd.
        env: dict, a mapping that defines the environment variables for the
            new process. Default behavior is inheriting the current process'
            environment.

    Returns:
        A 3-tuple of the consisting of the return code, the std output, and the
            std error.

    Raises:
        psutil.TimeoutExpired: The command timed out.
    """
    # Only import psutil when actually needed.
    # psutil may cause import error in certain env. This way the utils module
    # doesn't crash upon import.
    import psutil
    if stdout is None:
        stdout = subprocess.PIPE
    if stderr is None:
        stderr = subprocess.PIPE
    process = psutil.Popen(cmd,
                           stdout=stdout,
                           stderr=stderr,
                           shell=shell,
                           cwd=cwd,
                           env=env)
    timer = None
    timer_triggered = threading.Event()
    if timeout and timeout > 0:
        # The wait method on process will hang when used with PIPEs with large
        # outputs, so use a timer thread instead.

        def timeout_expired():
            timer_triggered.set()
            process.terminate()

        timer = threading.Timer(timeout, timeout_expired)
        timer.start()
    # If the command takes longer than the timeout, then the timer thread
    # will kill the subprocess, which will make it terminate.
    (out, err) = process.communicate()
    if timer is not None:
        timer.cancel()
    if timer_triggered.is_set():
        raise psutil.TimeoutExpired(timeout, pid=process.pid)
    return (process.returncode, out, err)


def start_standing_subprocess(cmd, shell=False, env=None):
    """Starts a long-running subprocess.

    This is not a blocking call and the subprocess started by it should be
    explicitly terminated with stop_standing_subprocess.

    For short-running commands, you should use subprocess.check_call, which
    blocks.

    Args:
        cmd: string, the command to start the subprocess with.
        shell: bool, True to run this command through the system shell,
            False to invoke it directly. See subprocess.Proc() docs.
        env: dict, a custom environment to run the standing subprocess. If not
            specified, inherits the current environment. See subprocess.Popen()
            docs.

    Returns:
        The subprocess that was started.
    """
    logging.debug('Starting standing subprocess with: %s', cmd)
    proc = subprocess.Popen(cmd,
                            stdin=subprocess.PIPE,
                            stdout=subprocess.PIPE,
                            stderr=subprocess.PIPE,
                            shell=shell,
                            env=env)
    # Leaving stdin open causes problems for input, e.g. breaking the
    # code.inspect() shell (http://stackoverflow.com/a/25512460/1612937), so
    # explicitly close it assuming it is not needed for standing subprocesses.
    proc.stdin.close()
    proc.stdin = None
    logging.debug('Started standing subprocess %d', proc.pid)
    return proc


def stop_standing_subprocess(proc):
    """Stops a subprocess started by start_standing_subprocess.

    Before killing the process, we check if the process is running, if it has
    terminated, Error is raised.

    Catches and ignores the PermissionError which only happens on Macs.

    Args:
        proc: Subprocess to terminate.

    Raises:
        Error: if the subprocess could not be stopped.
    """
    # Only import psutil when actually needed.
    # psutil may cause import error in certain env. This way the utils module
    # doesn't crash upon import.
    import psutil
    pid = proc.pid
    logging.debug('Stopping standing subprocess %d', pid)
    process = psutil.Process(pid)
    failed = []
    try:
        children = process.children(recursive=True)
    except AttributeError:
        # Handle versions <3.0.0 of psutil.
        children = process.get_children(recursive=True)
    for child in children:
        try:
            child.kill()
            child.wait(timeout=10)
        except psutil.NoSuchProcess:
            # Ignore if the child process has already terminated.
            pass
        except:
            failed.append(child.pid)
            logging.exception('Failed to kill standing subprocess %d',
                              child.pid)
    try:
        process.kill()
        process.wait(timeout=10)
    except psutil.NoSuchProcess:
        # Ignore if the process has already terminated.
        pass
    except:
        failed.append(pid)
        logging.exception('Failed to kill standing subprocess %d', pid)
    if failed:
        raise Error('Failed to kill standing subprocesses: %s' % failed)
    # Call wait and close pipes on the original Python object so we don't get
    # runtime warnings.
    if proc.stdout:
        proc.stdout.close()
    if proc.stderr:
        proc.stderr.close()
    proc.wait()
    logging.debug('Stopped standing subprocess %d', pid)


def wait_for_standing_subprocess(proc, timeout=None):
    """Waits for a subprocess started by start_standing_subprocess to finish
    or times out.

    Propagates the exception raised by the subprocess.wait(.) function.
    The subprocess.TimeoutExpired exception is raised if the process timed-out
    rather than terminating.

    If no exception is raised: the subprocess terminated on its own. No need
    to call stop_standing_subprocess() to kill it.

    If an exception is raised: the subprocess is still alive - it did not
    terminate. Either call stop_standing_subprocess() to kill it, or call
    wait_for_standing_subprocess() to keep waiting for it to terminate on its
    own.

    If the corresponding subprocess command generates a large amount of output
    and this method is called with a timeout value, then the command can hang
    indefinitely. See http://go/pylib/subprocess.html#subprocess.Popen.wait

    This function does not support Python 2.

    Args:
        p: Subprocess to wait for.
        timeout: An integer number of seconds to wait before timing out.
    """
    proc.wait(timeout)


def get_available_host_port():
    """Gets a host port number available for adb forward.

    Returns:
        An integer representing a port number on the host available for adb
        forward.

    Raises:
        Error: when no port is found after MAX_PORT_ALLOCATION_RETRY times.
    """
    # Only import adb module if needed.
    from mobly.controllers.android_device_lib import adb
    for _ in range(MAX_PORT_ALLOCATION_RETRY):
        port = portpicker.PickUnusedPort()
        # Make sure adb is not using this port so we don't accidentally
        # interrupt ongoing runs by trying to bind to the port.
        if port not in adb.list_occupied_adb_ports():
            return port
    raise Error('Failed to find available port after {} retries'.format(
        MAX_PORT_ALLOCATION_RETRY))


def grep(regex, output):
    """Similar to linux's `grep`, this returns the line in an output stream
    that matches a given regex pattern.

    It does not rely on the `grep` binary and is not sensitive to line endings,
    so it can be used cross-platform.

    Args:
        regex: string, a regex that matches the expected pattern.
        output: byte string, the raw output of the adb cmd.

    Returns:
        A list of strings, all of which are output lines that matches the
        regex pattern.
    """
    lines = output.decode('utf-8').strip().splitlines()
    results = []
    for line in lines:
        if re.search(regex, line):
            results.append(line.strip())
    return results


def cli_cmd_to_string(args):
    """Converts a cmd arg list to string.

    Args:
        args: list of strings, the arguments of a command.

    Returns:
        String representation of the command.
    """
    if isinstance(args, basestring):
        # Return directly if it's already a string.
        return args
    return ' '.join([pipes.quote(arg) for arg in args])
