#!/usr/bin/env python
# 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('--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):
  if os.path.exists(output):
    shutil.rmtree(output)
  os.makedirs(output)
  args = ['--file-per-class',
          '--output', output]
  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)
    extract_classes(app2_input, app2_classes_dir)
    compare(app1_classes_dir, app2_classes_dir, app1, app2, options)

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