#!/usr/bin/env python
#
# Copyright 2019 The Cobalt Authors. All Rights Reserved.
#
# 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.


"""Tools for creating and extracting a Cobalt Archive."""

import argparse
import fnmatch
import hashlib
import json
import logging
import os
import random
import stat
import sys
import time
import zipfile

import _env  # pylint: disable=relative-import,unused-import
from cobalt.build import cobalt_archive_extract
import starboard.build.filelist as filelist
import starboard.build.port_symlink as port_symlink
from starboard.tools.app_launcher_packager import CopyAppLauncherTools
from starboard.tools.build import GetPlatformConfig
from starboard.tools.config import GetAll as GetAllConfigs
import starboard.tools.paths as paths
from starboard.tools.platform import GetAll as GetAllPlatforms
from starboard.tools.util import SetupDefaultLoggingConfig


################################################################################
#                                  API                                         #
################################################################################


def MakeCobaltArchiveFromFileList(output_archive_path,
                                  input_file_list,  # class FileList
                                  platform_name,
                                  platform_sdk_version,
                                  config,
                                  additional_buildinfo_dict=None):
  if additional_buildinfo_dict is None:
    additional_buildinfo_dict = {}
  archive = CobaltArchive(archive_zip_path=output_archive_path)
  archive.MakeArchive(platform_name=platform_name,
                      platform_sdk_version=platform_sdk_version,
                      config=config,
                      file_list=input_file_list,
                      additional_buildinfo_dict=additional_buildinfo_dict)


def MakeCobaltArchiveFromSource(output_archive_path,
                                platform_name,
                                config,
                                platform_sdk_version,
                                additional_buildinfo_dict=None,
                                include_black_box_tests=False):
  """Returns None, failure is signaled via exception."""
  if additional_buildinfo_dict is None:
    additional_buildinfo_dict = {}
  _MakeCobaltArchiveFromSource(
      output_archive_path=output_archive_path,
      platform_name=platform_name,
      config=config,
      platform_sdk_version=platform_sdk_version,
      additional_buildinfo_dict=additional_buildinfo_dict,
      include_black_box_tests=include_black_box_tests)


def ExtractCobaltArchive(input_zip_path, output_directory_path, outstream=None):
  """Returns True if the extract operation was successfull."""
  archive = CobaltArchive(archive_zip_path=input_zip_path)
  return archive.ExtractTo(output_dir=output_directory_path,
                           outstream=outstream)


def ReadCobaltArchiveInfo(input_zip_path):
  archive = CobaltArchive(archive_zip_path=input_zip_path)
  return archive.ReadMetaData()


################################################################################
#                                 IMPL                                         #
################################################################################


# Source resource paths.
_SELF_DIR = os.path.abspath(os.path.dirname(__file__))
_SRC_CONTENT_PATH = os.path.join(_SELF_DIR, 'cobalt_archive_content')


# Relative paths from the resulting archive root. The path seperator
# is normalized to '/'.
_OUT_ARCHIVE_ROOT = '__cobalt_archive'
_OUT_FINALIZE_DECOMPRESSION_PATH = '%s/%s' % (_OUT_ARCHIVE_ROOT,
                                              'finalize_decompression')
_OUT_METADATA_PATH = '%s/%s' % (_OUT_ARCHIVE_ROOT, 'metadata.json')
_OUT_DECOMP_JSON = '%s/%s' % (_OUT_FINALIZE_DECOMPRESSION_PATH,
                              'decompress.json')


class CobaltArchive(object):
  """CobaltArchive is a utility generating archives."""

  def __init__(self, archive_zip_path):
    self.archive_zip_path = archive_zip_path

  def ExtractTo(self, output_dir, outstream=None):
    """Returns True if all files were extracted, False otherwise."""
    return cobalt_archive_extract.ExtractTo(
        self.archive_zip_path, output_dir, outstream)

  def ReadMetaData(self):
    json_str = self.ReadFile(_OUT_METADATA_PATH)
    return json.loads(json_str)

  def ReadFile(self, file_path):
    with zipfile.ZipFile(self.archive_zip_path, 'r', allowZip64=True) as zf:
      return zf.read(file_path)

  def MakeArchive(self,
                  platform_name,
                  platform_sdk_version,
                  config,
                  file_list,  # class FileList
                  additional_buildinfo_dict=None):
    """Creates an archive for the given platform and config."""
    logging.info('Making cobalt archive...')
    is_windows = port_symlink.IsWindows()
    if additional_buildinfo_dict is None:
      additional_buildinfo_dict = {}
    if config not in GetAllConfigs():
      raise ValueError('Expected %s to be one of %s'
                       % (config, GetAllConfigs()))
    additional_buildinfo_dict = dict(additional_buildinfo_dict)  # Copy
    build_info_str = _GenerateBuildInfoStr(
        platform_name=platform_name,
        platform_sdk_version=platform_sdk_version,
        config=config,
        additional_buildinfo_dict=additional_buildinfo_dict)
    with zipfile.ZipFile(self.archive_zip_path, mode='w',
                         compression=zipfile.ZIP_DEFLATED,
                         allowZip64=True) as zf:
      # Copy the cobalt_archive_content directory into the root of the archive.
      content_file_list = filelist.FileList()
      content_file_list.AddAllFilesInPath(root_dir=_SRC_CONTENT_PATH,
                                          sub_path=_SRC_CONTENT_PATH)
      for file_path, archive_path in content_file_list.file_list:
        # Skip the fake metadata.json file because the real one
        # is a generated in it's place.
        if os.path.basename(file_path) == 'metadata.json':
          continue
        zf.write(file_path, arcname=archive_path)
      # Write out the metadata.
      zf.writestr(_OUT_METADATA_PATH, build_info_str)
      if file_list.file_list:
        logging.info('  Compressing %d files', len(file_list.file_list))

      executable_files = []
      n_file_list = len(file_list.file_list)
      progress_set = set()
      for i in range(n_file_list):
        # Logging every 5% increment during compression step.
        prog = int((float(i)/n_file_list) * 100)
        if prog not in progress_set:
          progress_set.add(prog)
          logging.info('  Compressed %d%%...', prog)
        file_path, archive_path = file_list.file_list[i]
        if not is_windows:
          perms = _GetFilePermissions(file_path)
          if (stat.S_IXUSR) & perms:
            executable_files.append(archive_path)
        # TODO: Use and implement _FoldIdenticalFiles() to reduce
        # duplicate files. This will help platforms like nxswitch which include
        # a lot of duplicate files for the sdk.
        try:
          zf.write(file_path, arcname=archive_path)
        except WindowsError:  # pylint: disable=undefined-variable
          # Happens for long file path names.
          zf.write(cobalt_archive_extract.ToWinUncPath(file_path),
                   arcname=archive_path)

      if file_list.symlink_dir_list:
        logging.info('  Compressing %d symlinks',
                     len(file_list.symlink_dir_list))
      # Generate the decompress.json file used by decompress.py.
      # Removes the first element which is the root directory, which is not
      # important for symlink creation.
      symlink_dir_list = [l[1:] for l in file_list.symlink_dir_list]
      # Replace '\\' with '/'
      symlink_dir_list = [_ToUnixPaths(l) for l in symlink_dir_list]
      decompress_json_str = _JsonDumpPrettyPrint({
          'symlink_dir': symlink_dir_list,
          'symlink_dir_doc': '[link_dir_path, target_dir_path]',
          'executable_files': executable_files,
      })
      zf.writestr(_OUT_DECOMP_JSON, decompress_json_str)
      logging.info('Done...')


def _ToUnixPaths(path_list):
  out = []
  for p in path_list:
    out.append(p.replace('\\', '/'))
  return out


def _GetFilePermissions(path):
  return stat.S_IMODE(os.stat(path).st_mode)


def _JsonDumpPrettyPrint(data):
  return json.dumps(data, sort_keys=True, indent=4, separators=(',', ': '))


def _MakeDirs(path):
  if not os.path.isdir(path):
    os.makedirs(path)


def _FindPossibleDeployPaths(build_root):
  """Searches for folders that are likely required for archiving."""
  out = []
  # Ultimately, this function should not be needed as each platform should
  # implement GetDeployPathPatterns(). This is stop-gap for platforms that do
  # not have GetDeployPathPatterns() implemented yet.
  root_paths = os.listdir(build_root)
  for p in root_paths:
    if p in ('gen', 'gypfiles', 'gyp-win-tool', 'obj', 'obj.host'):
      continue
    if p.endswith('.pdb'):
      continue  # Skip pdb files for size (only applies to Windows).
    p = os.path.join(build_root, p)
    if os.path.isfile(p):
      out.append(p)
      continue
    if port_symlink.IsSymLink(p):
      continue
    out.append(os.path.normpath(p))
  return out


def _PathMatchesPatterns(file_path, patterns):
  for p in patterns:
    if fnmatch.fnmatch(file_path, p):
      logging.debug('pattern %s matched %s', p, file_path)
      return True
  logging.debug('Skipping %s', file_path)
  return False


def _GetDeployPaths(platform_name, config):
  """Returns a list of paths that should be included in the archive."""
  try:
    gyp_config = GetPlatformConfig(platform_name)
    patterns = gyp_config.GetDeployPathPatterns()
    logging.info('Found platform include patterns: [%s]', ', '.join(patterns))
    out_directory = paths.BuildOutputDirectory(platform_name, config)
    out_paths = []
    for root, _, files in port_symlink.OsWalk(out_directory):
      for f in files:
        full_path = os.path.join(root, f)
        file_path = os.path.relpath(full_path, out_directory)
        if _PathMatchesPatterns(file_path, patterns):
          out_paths.append(file_path)
    return out_paths
  except NotImplementedError:  # Abstract class throws NotImplementedError.
    logging.warning('** AUTO INCLUDE: ** Specific deploy paths were not found '
                    'so including known possible deploy paths from the '
                    'platform out directory.')
    build_root = paths.BuildOutputDirectory(platform_name, config)
    deploy_paths = _FindPossibleDeployPaths(build_root)
    return deploy_paths


def _MakeCobaltArchiveFromSource(output_archive_path,
                                 platform_name,
                                 config,
                                 platform_sdk_version,
                                 additional_buildinfo_dict,
                                 include_black_box_tests):
  """Finds necessary files and makes an archive."""
  _MakeDirs(os.path.dirname(output_archive_path))
  out_directory = paths.BuildOutputDirectory(platform_name, config)
  root_dir = os.path.abspath(os.path.join(out_directory, '..', '..'))
  flist = filelist.FileList()
  inc_paths = _GetDeployPaths(platform_name, config)
  logging.info('Adding binary files to bundle...')
  for path in inc_paths:
    path = os.path.join(out_directory, path)
    if not os.path.exists(path):
      logging.info('Skipping deploy path %s because it does not exist.',
                   path)
      continue
    logging.info('  adding %s', os.path.abspath(path))
    flist.AddAllFilesInPath(root_dir=root_dir, sub_path=path)
  logging.info('...done')
  launcher_tools_path = os.path.join(
      os.path.dirname(output_archive_path),
      '____app_launcher')
  if os.path.exists(launcher_tools_path):
    port_symlink.Rmtree(launcher_tools_path)
  logging.info('Adding app_launcher_files to bundle in %s',
               os.path.abspath(launcher_tools_path))

  try:
    CopyAppLauncherTools(repo_root=paths.REPOSITORY_ROOT,
                         dest_root=launcher_tools_path,
                         additional_glob_patterns=[],
                         include_black_box_tests=include_black_box_tests)
    flist.AddAllFilesInPath(root_dir=launcher_tools_path,
                            sub_path=launcher_tools_path)
    logging.info('...done')

    MakeCobaltArchiveFromFileList(
        output_archive_path,
        input_file_list=flist,
        platform_name=platform_name,
        platform_sdk_version=platform_sdk_version,
        config=config,
        additional_buildinfo_dict=additional_buildinfo_dict)
    logging.info('...done')
  finally:
    port_symlink.Rmtree(launcher_tools_path)


def _FoldIdenticalFiles(file_path_list):
  """Takes input files and determines which are md5 identical and folds them.

  TODO: Implement into Cobalt Archive.

  Example:
    files, copy_list = _FoldIdenticalFiles(['in0/test.txt', 'in1/test.txt'])
    Output:
      files => ['in0/test.txt']
      copy_list => ['in0/test.txt', 'in1/test.txt']

  Args:
    file_path_list: A list of files that will be processed.

  Returns:
    A 2-tuple (files, copy_list) where files is a list of physical files and
    copy_list is the list of files that are identical.
  """
  # Remove duplicates.
  file_path_list = list(set(file_path_list))
  file_path_list.sort()
  def Md5File(fpath):
    hash_md5 = hashlib.md5()
    with open(fpath, 'rb') as f:
      for chunk in iter(lambda: f.read(4096), b''):
        hash_md5.update(chunk)
    return hash_md5.hexdigest()
  # Output
  phy_file_list = []
  copy_list = []
  # Temp data structure.
  file_map = {}
  for file_path in file_path_list:
    name = os.path.basename(file_path)
    fsize = os.stat(file_path).st_size
    entry = (name, fsize)
    files = file_map.get(entry, [])
    files.append(file_path)
    file_map[entry] = files
  for (fname, fsize), path_list in file_map.iteritems():  # pylint: disable=unused-variable
    assert path_list
    phy_file_list.append(path_list[0])
    if len(path_list) == 1:
      continue
    else:
      md5_dict = {Md5File(path_list[0]): path_list[0]}
      for tail_file in path_list[1:]:
        new_md5 = Md5File(tail_file)
        matching_file = md5_dict.get(new_md5, None)
        if matching_file is not None:
          # Match found.
          copy_list.append((matching_file, tail_file))
        else:
          phy_file_list.append(tail_file)
          md5_dict[new_md5] = tail_file
  return phy_file_list, copy_list


def _GenerateBuildInfoStr(platform_name, platform_sdk_version,
                          config, additional_buildinfo_dict):
  """Generates a build info string (for the metadata file)."""
  build_info = dict(additional_buildinfo_dict)  # Copy dict.
  build_info['archive_time_RFC_2822'] = (
      time.strftime('%a, %d %b %Y %H:%M:%S +0000', time.gmtime()))
  build_info['archive_time_local'] = time.asctime()
  build_info['platform'] = platform_name
  build_info['config'] = config
  build_info['sdk_version'] = platform_sdk_version
  # Can be used by clients for caching reasons.
  build_info['nonce'] = random.randint(0, 0xffffffffffffffff)
  build_info_str = _JsonDumpPrettyPrint(build_info)
  return build_info_str


################################################################################
#                                CMD LINE                                      #
################################################################################


def _MakeCobaltPlatformArchive(platform, config, output_zip,
                               include_black_box_tests):
  """Makes a Cobalt Archive, prompting for missing platform/config."""
  if not platform:
    platform = raw_input('platform: ')
  if platform not in GetAllPlatforms():
    raise ValueError('Platform "%s" not recognized, expected one of: \n%s'
                     % (platform, GetAllPlatforms()))
  if not config:
    config = raw_input('config: ')
  if not output_zip:
    output_zip = raw_input('output_zip: ')
  if not output_zip.endswith('.zip'):
    output_zip += '.zip'
  start_time = time.time()
  MakeCobaltArchiveFromSource(
      output_zip,
      platform,
      config,
      platform_sdk_version='TEST',
      additional_buildinfo_dict=None,
      include_black_box_tests=include_black_box_tests)
  time_delta = time.time() - start_time
  if not os.path.isfile(output_zip):
    raise ValueError('Expected zip file at ' + output_zip)
  logging.info('\nGenerated: %s in %d seconds', output_zip, int(time_delta))


# Returns True/False
def _DecompressArchive(in_zip, out_path):
  if not in_zip:
    in_zip = raw_input('cobalt archive path: ')
  if not out_path:
    out_path = raw_input('output path: ')
  return ExtractCobaltArchive(input_zip_path=in_zip,
                              output_directory_path=out_path)


def _CreateArgumentParser():
  """Creates a parser that will print the full help on failure to parse."""

  class MyParser(argparse.ArgumentParser):

    def error(self, message):
      sys.stderr.write('error: %s\n' % message)
      self.print_help()
      sys.exit(2)
  help_msg = (
      'Example 1:\n'
      '  python cobalt_archive.py --create --platform nxswitch'
      ' --config devel --out_path <OUT_ZIP>\n\n'
      'Example 2:\n'
      '  python cobalt_archive.py --extract --in_path <ARCHIVE_PATH.ZIP>'
      ' --out_path <OUT_DIR>')
  # Enables new lines in the description and epilog.
  formatter_class = argparse.RawDescriptionHelpFormatter
  parser = MyParser(epilog=help_msg, formatter_class=formatter_class)
  group = parser.add_mutually_exclusive_group(required=True)
  group.add_argument(
      '-c',
      '--create',
      help='Creates an archive from source directory, optional arguments'
           ' include --platform --config and --out_path',
      action='store_true')
  group.add_argument(
      '-x',
      '--extract',
      help='Extract archive from IN_PATH to OUT_PATH, optional arguments '
           'include --in_path and --out_path',
      action='store_true')
  parser.add_argument('--platform', type=str,
                      help='Optional, used for --create',
                      default=None)
  parser.add_argument('--config', type=str,
                      help='Optional, used for --create',
                      choices=GetAllConfigs(),
                      default=None)
  parser.add_argument('--out_path', type=str,
                      help='Optional, used for --create and --decompress',
                      default=None)
  parser.add_argument('--in_path', type=str,
                      help='Optional, used for decompress',
                      default=None)
  parser.add_argument('--include_black_box_tests',
                      help='Optional, used for --create to add blackbox tests',
                      action='store_true')
  return parser


def main():
  SetupDefaultLoggingConfig()
  parser = _CreateArgumentParser()
  args, unknown_args = parser.parse_known_args()
  if unknown_args:
    logging.warning('Unknown (ignored) args: %s', unknown_args)
  if args.create:
    _MakeCobaltPlatformArchive(
        platform=args.platform,
        config=args.config,
        output_zip=args.out_path,
        include_black_box_tests=args.include_black_box_tests)
    sys.exit(0)
  elif args.extract:
    ok = _DecompressArchive(args.in_path, args.out_path)
    rc = 0 if ok else 1
    sys.exit(rc)
  else:
    parser.print_help()


if __name__ == '__main__':
  main()
