import numpy as np


def write_monte(spec, rslt):
    """ Write out results to table.
    """
    num_evals = rslt['num_evals']
    num_steps = rslt['num_steps']
    points = rslt['points']
    stat = rslt['rmse']

    # Write out information.
    fname = 'table_4.' + str(spec + 1) + '.txt'
    with open(fname, 'w') as f:
        # Write out the heading of the table.
        args = list()
        args += ['Identifier', 'True Value', 'Mean', 'Bias', 't-Stat.', 'Std.']

        fmt_ = ' {:>15}' + ' {:>15}' * 5 + '\n\n'
        line = fmt_.format(*args)
        f.write(line)

        fmt_ = ' {:>15}' + ' {:15.4f}' * 5 + '\n'

        for i in range(26):
            args = list()
            args += [str(i)]
            args += [points['true'][i]]
            args += [points['mean'][i]]
            args += [points['bias'][i]]
            args += [points['stat'][i]]
            args += [points['stan'][i]]

            line = fmt_.format(*args)
            f.write(line)

        string = '\n\n\n {0[0]:>15} {0[1]:>15} {0[2]:>15}\n\n'
        f.write(string.format(['RMSE', 'Evaluations', 'Steps']))
        string = ' {:15.4f} {:>15} {:>15}'
        f.write(string.format(*[stat, int(num_evals), int(num_steps)]))


def process_monte(x_iter, x_true):
    """ Process results from to bootstrap iterations to fill the table with
    the required information.
    """
    # Initialize dictionary as the results container.
    rslt = dict()
    for key_ in ['mean', 'true', 'bias', 'stan', 'stat', 'msta']:
        rslt[key_] = [None] * 26

    # Attach the results from each individual bootstrap run to the dictionary.
    rslt['x_iter'] = np.array(x_iter, ndmin=2)

    # Construct auxiliary objects
    rslt['mean'] = np.mean(rslt['x_iter'], axis=0)
    num_boots = len(rslt['x_iter'])

    # Construct the requested information.
    for i in range(26):
        # true parameter and bias
        rslt['true'][i] = x_true[i]
        rslt['bias'][i] = rslt['mean'][i] - rslt['true'][i]

        # standard deviation
        rslt['stan'][i] = 0.0
        for j in range(num_boots):
            rslt['stan'][i] += (rslt['x_iter'][j, i] - rslt['mean'][i]) ** 2
        try:
            rslt['stan'][i] = np.sqrt((1.0 / (num_boots - 1)) * rslt['stan'][i])
        except ZeroDivisionError:
            rslt['stan'][i] = 0.0

        # t-statistic
        if rslt['stan'][i] == 0.0:
            rslt['stat'][i] = 0.0
        else:
            rslt['stat'][i] = ((rslt['mean'][i] - x_true[i]) / rslt['stan'][i])
            rslt['stat'][i] = rslt['stat'][i] * np.sqrt(num_boots)

    return rslt
