#!/usr/bin/env python3
# Copyright (c) 2018, the R8 project authors. Please see the AUTHORS file
# for details. All rights reserved. Use of this source code is governed by a
# BSD-style license that can be found in the LICENSE file.

# Script for checking impact of a change by comparing the sizes of generated
# classes in an apk.

import glob
import optparse
import os
import shutil
import sys
import threading
import time
import zipfile

import toolhelper
import utils

USAGE = """%prog [options] app1 app2
  NOTE: This only makes sense if minification is disabled"""

MAX_THREADS=40

def parse_options():
  result = optparse.OptionParser(usage=USAGE)
  result.add_option('--no-build',
                    help='Run without building first',
                    default=False,
                    action='store_true')
  result.add_option('--temp',
                    help='Temporary directory to store extracted classes in')
  result.add_option('--use_code_size',
      help='Use the size of code segments instead of the full size of the dex.',
      default=False, action='store_true')
  result.add_option('--report',
                    help='Print comparison to this location instead of stdout')
  return result.parse_args()

def extract_apk(apk, output):
  if os.path.exists(output):
    shutil.rmtree(output)
  zipfile.ZipFile(apk).extractall(output)
  with utils.ChangedWorkingDirectory(output):
    dex = glob.glob('*.dex')
    return [os.path.join(output, dexfile) for dexfile in dex]

def ensure_exists(files):
  for f in files:
    if not os.path.exists(f):
      raise Exception('%s does not exist' % f)

def extract_classes(input, output, options):
  if os.path.exists(output):
    shutil.rmtree(output)
  os.makedirs(output)
  args = ['--file-per-class',
          '--output', output]
  if options.no_build:
    args.extend(['--no-build'])
  args.extend(input)
  if toolhelper.run('d8', args) is not 0:
    raise Exception('Failed running d8')

def get_code_size(path):
  segments = toolhelper.run('dexsegments',
                            [path],
                            build=False,
                            return_stdout=True)
  for line in segments.splitlines():
    if 'Code' in line:
      # The code size line looks like:
      #  - Code: 264 / 4
      splits = line.split(' ')
      return int(splits[3])
  # Some classes has no code.
  return 0

class FileInfo:
  def __init__(self, path, root):
    self.path = path
    self.full_path = os.path.join(root, path)

  def __eq__(self, other):
    return self.full_path == other.full_path

  def set_size(self, use_code_size):
    if use_code_size:
      self.size = get_code_size(self.full_path)
    else:
      self.size = os.path.getsize(self.full_path)

def generate_file_info(path, options):
  file_info_map = {}
  with utils.ChangedWorkingDirectory(path):
    for root, dirs, files in os.walk('.'):
      for f in files:
        assert f.endswith('dex')
        file_path = os.path.join(root, f)
        entry = FileInfo(file_path, path)
        if not options.use_code_size:
          entry.set_size(False)
        file_info_map[file_path] = entry
  threads = []
  file_infos = file_info_map.values() if options.use_code_size else []
  while len(file_infos) > 0 or len(threads)> 0:
    for t in threads:
      if not t.is_alive():
        threads.remove(t)
    # sleep
    if len(threads) == MAX_THREADS or len(file_infos) == 0:
      time.sleep(0.5)
    while len(threads) < MAX_THREADS and len(file_infos) > 0:
      info = file_infos.pop()
      print('Added %s for size calculation' % info.full_path)
      t = threading.Thread(target=info.set_size, args=(options.use_code_size,))
      threads.append(t)
      t.start()
    print('Missing %s files, threads=%s ' % (len(file_infos), len(threads)))

  return file_info_map

def print_info(app, app_files, only_in_app, bigger_in_app, output):
  output.write('Only in %s\n' % app)
  only_app_sorted = sorted(only_in_app,
                           key=lambda a: app_files[a].size,
                           reverse=True)
  output.write('\n'.join(['  %s %s bytes' %
                          (x, app_files[x].size) for x in only_app_sorted]))
  output.write('\n\n')
  output.write('Bigger in %s\n' % app)
  # Sort by the percentage diff compared to size
  percent = lambda a: (0.0 + bigger_in_app.get(a))/app_files.get(a).size * 100
  for bigger in sorted(bigger_in_app, key=percent, reverse=True):
    output.write('  {0:.3f}% {1} bytes {2}\n'.format(percent(bigger),
                                                     bigger_in_app[bigger],
                                                     bigger))
  output.write('\n\n')


def compare(app1_classes_dir, app2_classes_dir, app1, app2, options):
  app1_files = generate_file_info(app1_classes_dir, options)
  app2_files = generate_file_info(app2_classes_dir, options)
  only_in_app1 = [k for k in app1_files if k not in app2_files]
  only_in_app2 = [k for k in app2_files if k not in app1_files]
  in_both = [k for k in app2_files if k in app1_files]
  assert len(app1_files) == len(only_in_app1) + len(in_both)
  assert len(app2_files) == len(only_in_app2) + len(in_both)
  bigger_in_app1 = {}
  bigger_in_app2 = {}
  same_size = []
  for f in in_both:
    app1_entry = app1_files[f]
    app2_entry = app2_files[f]
    if app1_entry.size > app2_entry.size:
      bigger_in_app1[f] = app1_entry.size - app2_entry.size
    elif app2_entry.size > app1_entry.size:
      bigger_in_app2[f] = app2_entry.size - app1_entry.size
    else:
      same_size.append(f)
  output = open(options.report, 'w') if options.report else sys.stdout
  print_info(app1, app1_files, only_in_app1, bigger_in_app1, output)
  print_info(app2, app2_files, only_in_app2, bigger_in_app2, output)
  output.write('Same size\n')
  output.write('\n'.join(['  %s' % x for x in same_size]))
  if options.report:
    output.close()

def Main():
  (options, args) = parse_options()
  if len(args) is not 2:
    print(args)
    print('Takes exactly two arguments, the two apps to compare')
    return 1
  app1 = args[0]
  app2 = args[1]
  ensure_exists([app1, app2])
  with utils.TempDir() as temporary:
    # If a temp dir is passed in, use that instead of the generated temporary
    output = options.temp if options.temp else temporary
    ensure_exists([output])
    app1_input = [app1]
    app2_input = [app2]
    if app1.endswith('apk'):
      app1_input = extract_apk(app1, os.path.join(output, 'app1'))
    if app2.endswith('apk'):
      app2_input = extract_apk(app2, os.path.join(output, 'app2'))
    app1_classes_dir = os.path.join(output, 'app1_classes')
    app2_classes_dir = os.path.join(output, 'app2_classes')

    extract_classes(app1_input, app1_classes_dir, options)
    extract_classes(app2_input, app2_classes_dir, options)
    compare(app1_classes_dir, app2_classes_dir, app1, app2, options)

if __name__ == '__main__':
  sys.exit(Main())
