#!/usr/bin/env python
#
# Copyright 2014  Lars Wirzenius
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.


import json
import os

import cliapp


MiB = 2**20
GiB = 2**30


class ObnamBenchmarkSummary(cliapp.Application):

    columns = (
        ('version', 'version'),
        ('ef-speed', 'EF files/s'),
        ('ef-repo-size', 'EF repo (MiB)'),
        ('lf-speed', 'LF MiB/s'),
        ('lf-repo-size', 'LF repo (MiB)'),
        )

    def process_args(self, args):
        summaries = []
        for dirname in args:
            summary = self.summarise_directory(dirname)
            summaries.append(summary)
        self.show_summaries(summaries)

    def summarise_directory(self, dirname):
        filename = os.path.join(dirname, 'benchmark.json')
        with open(filename) as f:
            obj = json.load(f)

        return {
            'version':
                self.get_obnam_version(obj),
            'ef-speed':
                '%.0f' % self.get_empty_files_speed(obj),
            'ef-files':
                self.get_empty_files_count(obj),
            'ef-repo-size':
                self.format_size(self.get_empty_files_repo_size(obj), MiB),
            'lf-speed':
                self.format_size(self.get_large_file_speed(obj), MiB),
            'lf-size':
                self.format_size(self.get_large_file_size(obj), GiB),
            'lf-repo-size':
                self.format_size(self.get_large_file_repo_size(obj), MiB),
            }

    def get_obnam_version(self, obj):
        return obj['versions']['obnam-version']

    def get_empty_files_speed(self, obj):
        count = self.get_empty_files_count(obj)
        step = self.find_step(obj, 'EmptyFiles', 'initial-backup')
        return count / step['duration']

    def get_empty_files_count(self, obj):
        step = self.find_step(obj, 'EmptyFiles', 'create-live-data')
        return step['empty-files-count']

    def get_empty_files_repo_size(self, obj):
        step = self.find_step(obj, 'EmptyFiles', 'initial-backup')
        return step['repo-size']

    def get_large_file_speed(self, obj):
        file_size = self.get_large_file_size(obj)
        step = self.find_step(obj, 'SingleLargeFile', 'initial-backup')
        return file_size / step['duration']

    def get_large_file_size(self, obj):
        step = self.find_step(obj, 'SingleLargeFile', 'create-live-data')
        return step['single-large-file-size']

    def get_large_file_repo_size(self, obj):
        step = self.find_step(obj, 'SingleLargeFile', 'initial-backup')
        return step['repo-size']

    def find_step(self, obj, benchmark_name, step_name):
        for step in obj['benchmarks'][benchmark_name]['steps']:
            if step['step'] == step_name:
                return step
        raise Exception('step %s not found' % step)

    def format_size(self, size, unit):
        return '%.0f' % (size / unit)

    def show_summaries(self, summaries):
        lines = [[title for key, title in self.columns]]

        for s in summaries:
            line = [str(s[key]) for key, title in self.columns]
            lines.append(line)

        widths = self.compute_column_widths(lines)

        titles = lines[0]
        results = sorted(lines[1:])
        for line in [titles] + results:
            cells = []
            for i, cell in enumerate(line):
                cells.append('%*s' % (widths[i], cell))
            self.output.write(' | '.join(cells))
            self.output.write('\n')

    def compute_column_widths(self, lines):
        widths = []
        n = len(lines[0])
        for col in range(n):
            width = 0
            for line in lines:
                width = max(width, len(line[col]))
            widths.append(width)
        return widths


if __name__ == '__main__':
    ObnamBenchmarkSummary().run()
