#!/usr/local/pypy3-2.4.0/bin/pypy

# pylint: disable=superfluous-parens
# superfluous-parens: Parentheses are good for clarity and portability

'''Do some sorted dictionary performance tests.  We mostly compare trees, but also sosrtedcontainers'''

from __future__ import with_statement

import os
import sys
import copy
import glob

import common


def get_filename(interpreter_path, heap_option, number_pattern, tree_type):
    # pylint: disable=too-many-arguments
    '''Return a filename for storing performance data in'''
    return '%s-%s-%s-%s.dat' % (common.get_interpreter(interpreter_path), heap_option, number_pattern, tree_type)


def cleanup(interpreter_path):
    '''Clean up old timing files from previous runs of this script'''
    for filename in glob.glob('%s-*.dat' % common.get_interpreter(interpreter_path)):
        print('removing %s' % filename)
        os.unlink(filename)


def write_datapoint(interpreter, durations, heap_option, size, number_pattern, description):
    # pylint: disable=too-many-arguments
    '''Write a single datapoint to the relevant output file'''
    # We don't want to write anything for a zero-length durations list
    if durations:
        mean_duration = compute_mean(durations)
        with open(get_filename(interpreter, heap_option, number_pattern, description), 'a') as file_:
            file_.write('%s %s\n' % (size, mean_duration))


def inner_loops(
        max_reps,
        interpreter_path,
        datastructure,
        number_pattern,
        size,
        too_long,
        datastructures_copy1,
):
    # pylint: disable=too-many-arguments
    '''Deal with the inner loop'''
    durations = []
    for repno in range(max_reps):
        duration = common.invoke_test_one(
            interpreter_path,
            datastructure,
            number_pattern,
            size,
            )
        sys.stdout.write('%-12s %-19s %-10s rep: %2d, size: %d ' % (
            common.get_interpreter(interpreter_path),
            datastructure,
            number_pattern,
            repno,
            size,
        ))
        print('%s' % (duration, ))
        if duration > too_long:
            del datastructures_copy1[datastructure]
            return
        durations.append(duration)
    write_datapoint(
        interpreter_path,
        durations,
        size,
        number_pattern,
        datastructure,
        )


def main():
    # pylint: disable=too-many-locals,too-many-branches
    '''Main function'''

    production = False
    if production:
        min_exponent = 10
        max_exponent = 30
        max_reps = 3
        too_long = 20.0 * 60.0
    else:
        min_exponent = 10
        max_exponent = 11
        max_reps = 2
        too_long = 20.0

    for interpreter_path in common.INTERPRETERS:
        cleanup(interpreter_path)

        for number_pattern in common.NUMBER_PATTERN:
            datastructures_copy1 = copy.copy(common.DATASTRUCTURES)
            for exponent in range(min_exponent, max_exponent + 1):
                size = 2 ** exponent
                datastructures_copy2 = sorted(datastructures_copy1)
                for datastructure in datastructures_copy2:
                    inner_loops(
                        max_reps,
                        interpreter_path,
                        datastructure,
                        number_pattern,
                        size,
                        too_long,
                        datastructures_copy1,
                        )


main()