from global_types.parametric.ParametricGlobalTypes import ParametricKinds
import numpy as np
import matplotlib.pyplot as plt

CUTOFF_X = 1000
CUTOFF_Y = 20
SMALL_SIZE = 12
FONT_SIZE = 16
LEGEND_SIZE = 14
LINE_WIDTH = 4
ALPHA = 1


def output_plot(num_size, all_eval_folder_path, where_to_save=None):
    set_up_plot(num_size)
    add_plots_from_folder(all_eval_folder_path, True)
    add_plots_from_folder(all_eval_folder_path, False)
    finish_plot(where_to_save)


def set_up_plot(cutoff_x):
    plt.rc('font', size=FONT_SIZE)  # controls default text sizes
    plt.rc('axes', titlesize=FONT_SIZE)  # fontsize of the axes title
    plt.rc('axes', labelsize=FONT_SIZE)  # fontsize of the x and y labels
    plt.rc('xtick', labelsize=SMALL_SIZE)  # fontsize of the tick labels
    plt.rc('ytick', labelsize=SMALL_SIZE)  # fontsize of the tick labels
    plt.rc('legend', fontsize=LEGEND_SIZE)  # legend fontsize
    plt.xlim([0, cutoff_x])
    plt.plot([], [], 'yellow', label="mem_cache", linewidth=LINE_WIDTH)
    plt.plot([], [], 'green', label="tree_broadcast", linewidth=LINE_WIDTH)
    plt.plot([], [], 'purple', label="p2p_broadcast", linewidth=LINE_WIDTH)
    plt.plot([], [], 'orange', label="map_reduce", linewidth=LINE_WIDTH)
    plt.plot([], [], 'black', linestyle='--', label="lazy evaluation_data", linewidth=LINE_WIDTH)
    plt.plot([], [], 'black', linestyle=':', label="no avail. check", linewidth=LINE_WIDTH)


def add_plots_from_folder(folder_path, avail_check):  # folder_path contains "evaluation_*_timestamp/"
    folder_name_avail = "/optional_avail/" if avail_check else "/no_avail/"
    map_reduce_mapping = folder_path + "map_reduce" + folder_name_avail + "/a_mapping_map_reduce.txt"
    mem_cache_mapping = folder_path + "mem_cache" + folder_name_avail + "/a_mapping_mem_cache.txt"
    p2p_broadcast_mapping = folder_path + "p2p_broadcast" + folder_name_avail + "/a_mapping_p2p_broadcast.txt"
    tree_broadcast_mapping = folder_path + "tree_broadcast" + folder_name_avail + "/a_mapping_tree_broadcast.txt"
    # 1
    line_option = 2 if avail_check else 1
    add_to_plot(folder_path + "map_reduce" + folder_name_avail + "/a_summary_map_reduce.txt", line_option, 12, 5, map_reduce_mapping)
    add_to_plot(folder_path + "mem_cache" + folder_name_avail + "/a_summary_mem_cache.txt", line_option, 12, 3, mem_cache_mapping)
    add_to_plot(folder_path + "p2p_broadcast" + folder_name_avail + "/a_summary_p2p_broadcast.txt", line_option, 12, 4, p2p_broadcast_mapping)
    add_to_plot(folder_path + "tree_broadcast" + folder_name_avail + "/a_summary_tree_broadcast.txt", line_option, 12, 6, tree_broadcast_mapping)


def finish_plot(where_to_save):
    plt.ylabel("time in s")
    plt.xlabel("size")
    plt.legend(loc='best')
    if where_to_save is not None:
        plt.savefig(where_to_save, format='pdf', bbox_inches='tight')
    else:
        plt.show()
    plt.clf()


def add_to_plot(filename, line_option, line_period, color_option, size_mapping_file):
    data = np.loadtxt(filename)
    param = data[:, 0]
    time = [x/1000 for x in data[:, 1]]
    time = list(filter(lambda x: x <= 60 * 10, time))
    size_mapping = np.loadtxt(size_mapping_file)
    param = size_mapping[:, 1] # we assume that the param are the same
    # we limit the axis now
    # param = list(filter(lambda x: x <= CUTOFF_SIZE, param))
    min_dim = min(len(time), len(param))
    param = param[:min_dim]
    time = time[:min_dim]
    if color_option == 1:
        param_color = 'red'
        line_offset = 0
    elif color_option == 2:
        param_color = 'blue'
        line_offset = line_period / 3
    elif color_option == 3:
        param_color = 'yellow'
        line_offset = 2 * line_period / 3
    elif color_option == 4:
        param_color = 'purple'
        line_offset = 0
    elif color_option == 5:
        param_color = 'orange'
        line_offset = line_period / 3
    elif color_option == 6:
        param_color = 'green'
        line_offset = 2 * line_period / 3
    if line_option == 1:
        plt.plot(param, time, linestyle=':', color=param_color, linewidth=LINE_WIDTH, alpha=ALPHA)
    elif line_option == 2:
        plt.plot(param, time, linestyle=(line_offset, (line_period/3, 2*line_period/3)), color=param_color, linewidth=LINE_WIDTH, alpha=ALPHA)
    elif line_option == 3:
        plt.plot(param, time, linestyle='-', color=param_color, linewidth=LINE_WIDTH, alpha=ALPHA)
        # plt.plot(param, time, linestyle=(0, (2.5, 0.5)), color=param_color, linewidth=LINE_WIDTH, alpha=ALPHA)


# helper functions
def get_prefix_from_kind(kind):
    return "../evaluation_data/" + kind.value + "/"


def get_pattern_for_parameter(num):
    return "evaluation_" + str(num) + "_*.txt"