from acsploit.options import Options


options = Options()
options.add_option('function', 'search', 'The tree function', ['search', 'min', 'max', 'insert', 'delete'])
options.add_option('n_inputs', 10, 'Number of nodes in tree')

DESCRIPTION = 'Produces a worst-case set of inputs for various operations on a Binary Search Tree.' \
              '\n\n  ' \
              'Worst cases for the various operations of a Binary Search Tree all involve ' \
              'sorted lists, which maximize the depth of the tree.'


def run(generator, output):
    f = options['function']
    ret = []
    if f == 'search' or f == 'min' or f == 'delete':
        ret.append('Tree insertion order:')
        sorted = sorted_list(generator, options['n_inputs'])
        for s in sorted:
            ret.append(s)
        if f == 'search':
            ret.append('Search for : %s' % sorted[options['n_inputs']-1])
        elif f == 'delete':
            ret.append('Delete : %s' % sorted[options['n_inputs']-1])
    elif f == 'insert':
        ret.append('Tree insertion order:')
        sorted = sorted_list(generator, options['n_inputs']+1)
        for i in sorted[:-1]:
            ret.append(i)
        ret.append('Insert : %s' % sorted[-1])
    elif f == 'max':
        ret.append('Tree insertion order:')
        sorted = list(reversed(sorted_list(generator, options['n_inputs'])))
        for i in sorted:
            ret.append(i)
    else:
        raise ValueError('Not a valid function for binary search trees')
    output.output(ret)


def sorted_list(generator, n_inputs):
    output = [generator.get_max_value()]
    for i in range(1, n_inputs):
        output.append(generator.get_less_than(output[i - 1]))
    return output
