#!/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())
