#!/usr/bin/env python2
#
#   Copyright 2020 - 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.

"""Tool to save logs files for use by gen_smoke_tests.py."""

from __future__ import print_function

import glob
import os
import shutil
import sys

import util

ANDROID_REPOSITORY_ROOT = util.android_repository_root()
LOGS_ROOT = os.path.join(ANDROID_REPOSITORY_ROOT, 'out', 'host', 'linux-x86',
                         'cts', 'android-cts', 'logs')
CTS_LOGS_PATTERN = os.path.join(LOGS_ROOT, '*', '*',
                                'device_logcat_test_*.txt.gz')
LIBCORE_DIR = os.path.join(ANDROID_REPOSITORY_ROOT, 'libcore')
DESTINATION_DIR = os.path.join(LIBCORE_DIR, 'smoketest')


def check_destination():
  """Ensures the destination directory to copy the files to exists."""
  if not os.path.isdir(LIBCORE_DIR):
    raise Exception('Could not find directory ' + LIBCORE_DIR)
  if not os.path.isdir(DESTINATION_DIR):
    print('Making destination directory ' +
          util.printable_path(DESTINATION_DIR))
    os.mkdir(DESTINATION_DIR, 0o755)
  else:
    print('Found destination directory ' + util.printable_path(DESTINATION_DIR))


def is_real_log_file(filename):
  """Returns whether the filename is one we should use or not."""
  return 'latest' not in filename


def find_all_log_files():
  """Finds all CTS log files in the expected directory.

  Returns:
    A list of filenames, sorted by mtime, most recent first.
  Raises:
    Exception: Not enough log files found.
  """
  print('Looking for logs in %s' % util.printable_path(LOGS_ROOT))
  print('+++ ' + CTS_LOGS_PATTERN)
  for f in glob.glob(CTS_LOGS_PATTERN):
    print('*** ' + f)
  sources = [f for f in glob.glob(CTS_LOGS_PATTERN) if is_real_log_file(f)]
  if not sources:
    raise Exception('Found no logs files!')
  return sorted(sources, key=os.path.getmtime, reverse=True)


def relative_source_name(source):
  """Returns the name of a source file, relative to the logs root."""
  return os.path.relpath(source, LOGS_ROOT)


def flatten_name(name):
  """Returns a flattened version of a path, using _ to separate."""
  parts = []
  while name:
    (head, tail) = os.path.split(name)
    parts.insert(0, tail)
    name = head
  return '_'.join(parts)


def destination_path(name):
  """Returns the destination path for a given name (which must be flattened)."""
  assert not os.path.dirname(name)
  return os.path.join(DESTINATION_DIR, name)


def get_indexes_from_user(prompt, options):
  """Gets a sequence of indexes between 1 and max from the user.

  Args:
    prompt: A prompt to show to the user.
    options: The options to show to the user.

  Yields:
    The indexes.
  """
  for (index, option) in enumerate(options):
    print('%d: %s' % (index + 1, option))
  while True:
    print(prompt)
    instr = sys.stdin.readline().strip()
    if instr.lower() == 'q':
      break
    try:
      index = int(instr)
    except ValueError:
      print('Not a valid index! Please try again')
      continue
    if index < 1 or index > len(options):
      print('Not a valid index! Please try again')
      continue
    yield index - 1


def do_copy(source):
  """Copies the given source into the destination directory."""
  destination = destination_path(flatten_name(relative_source_name(source)))
  if os.path.exists(destination):
    print('File already exists: ' + util.printable_path(destination))
  else:
    print('Copying %s to %s' %
          (util.printable_path(source), util.printable_path(destination)))
    shutil.copyfile(source, destination)


def main():
  check_destination()
  sources = find_all_log_files()
  for index in get_indexes_from_user(
      'Enter the number of the file to save, or Q to quit',
      map(relative_source_name, sources)):
    do_copy(sources[index])
  print('Bye!')


main()