import matplotlib.pyplot as plt
import numpy as np

plt.rcParams['font.family'] = 'serif'
plt.rcParams['font.size'] = 12

def generate_measurement_stats_pie_chart(show: bool, save: bool):
    fig, ax = plt.subplots()

    size_outer = 0.3
    size_inner = 0.2

    vals_outer = np.array([28., 7.])  # Measurements vs Measurement failures
    vals_middle = np.array([17., 11., 7., 0.])  # MEWS calculations, Measurement only, P2 failures, P1 failures
    vals_inner = np.array([16., 1., 8., 3., 2., 5., 0., 0.])  # Innermost ring values

    cmap = plt.get_cmap("tab20b")
    outer_colors = cmap(np.array([6, 13]))
    middle_colors = cmap(np.array([5, 15, 14, 14]))
    inner_colors = cmap(np.array([11, 10, 11, 10, 11, 10, 11, 10]))

    # Outer ring
    ax.pie(vals_outer, radius=1, colors=outer_colors,
           wedgeprops=dict(width=size_outer, edgecolor='w'))

    # Middle ring
    ax.pie(vals_middle, radius=1-size_outer, colors=middle_colors,
           wedgeprops=dict(width=size_inner, edgecolor='w'))

    # Innermost ring
    inner_pie = ax.pie(vals_inner, radius=1-size_outer-size_inner, colors=inner_colors,
           wedgeprops=dict(width=size_inner, edgecolor='w'))
    #labels_inner = ["home", "on the go"]
    #ax.legend(inner_pie[0], labels_inner, loc="center right")

    ax.set(aspect="equal")

    if save:
        plt.savefig(
            "chart-measurement-stats.png",
            dpi=900,
            bbox_inches='tight',
            transparent=True
        )

    if show:
        plt.show()


def generate_measurement_repeats_histogram(show: bool, save: bool):
    device_names = ["Scanwatch", "BPM Core", "Thermo"]
    labels_attempts = [f"{name} measurement attempts" for name in device_names]
    labels_failures = ["S\u2081 failures", "B\u2081 failures", "T\u2081 failures"]
    values_attempts = [43, 33, 28]
    values_failures = [15, 5, 0]

    # Define a list of colors for the bars
    cmap = plt.get_cmap("tab20b")
    colors_attempts = cmap(np.array([15, 11, 7]))
    colors_failures = cmap(np.array([13, 9, 5]))

    # Plot the bars with the specified colors and labels for the legend
    bars_attempts = plt.bar(device_names, values_attempts, color=colors_attempts)
    bars_failures = plt.bar(device_names, values_failures, color=colors_failures)

    # Add individual labels for each bar in the legend
    for i in range(3):
        bars_attempts[i].set_label(labels_attempts[i])
        bars_failures[i].set_label(labels_failures[i])

    plt.ylabel("Count")

    plt.ylim(0, 55)
    plt.yticks(range(0, 56, 5))

    plt.legend(loc="upper right", prop={"size":8})

    if save:
        plt.savefig(
            "chart-measurement-repeats.png",
            dpi=900,
            bbox_inches="tight",
            transparent=True
        )

    if show:
        plt.show()


def generate_connection_boxplots(show: bool, save: bool):
    data_downlink = [
        [50.42, 46.29, 39.94, 39.44, 50.21, 44.34, 41.03, 47.88, 50.34, 41.72, 43.93, 49.34, 50.49, 52.47, 47.04, 45.86, 51.17, 50.12, 52.16, 50.55, 50.69, 53.43, 42.21, 46.81],
        [15.3, 25.47, 33.91, 12.27]
    ]
    data_uplink = [
        [11.38, 11.24, 8.46, 9.33, 11.39, 9.33, 9.03, 10.65, 11.59, 8.81, 8.91, 10.56, 10.98, 10.04, 9.11, 8.62, 11.08, 10.62, 11.24, 11.29, 10.86, 10.46, 9.16, 9.15],
        [5.33, 5.46, 3.38, 4.23]
    ]
    data_rtt = [
        [14, 16, 15, 15, 15, 15, 16, 12, 15, 14, 18, 14, 19, 16, 23, 12, 16, 14, 12, 13, 13, 13, 17, 15],
        [145, 127, 104, 108]
    ]

    fig, axes = plt.subplots(nrows=1, ncols=3, sharex=True, figsize=(15,5))
    #plt.subplots_adjust(wspace=0.4)

    cmap = plt.get_cmap("tab20b")

    medianprops= {
        "color": cmap(1),
        "linewidth": 2,
    }

    # Downlink Boxplot
    axes[1].boxplot(data_downlink, medianprops=medianprops)
    axes[1].set_ylabel("Datarate [Mbps]")
    axes[1].set_title("Downlink")
    axes[1].set_xticks([1, 2])
    axes[1].set_xticklabels(["At home", "On the go"])

    # Uplink Boxplot
    axes[0].boxplot(data_uplink, medianprops=medianprops)
    axes[0].set_ylabel("Datarate [Mbps]")
    axes[0].set_title("Uplink")
    axes[0].set_xticks([1, 2])
    axes[0].set_xticklabels(["At home", "On the go"])

    # RTT Boxplot
    axes[2].boxplot(data_rtt, medianprops=medianprops)
    axes[2].set_ylabel("RTT [ms]")
    axes[2].set_title("RTT")
    axes[2].set_xticks([1, 2])
    axes[2].set_xticklabels(["At home", "On the go"])

    # Function to add jitter
    def jitter(x, width=0.1):
        """Return the given x coordinate plus a small random offset."""
        np.random.seed = 0
        return x + np.random.uniform(-width, width)

    # Sample points to plot on the boxplots
    points_uplink = [
        (1, 11.38),
        (2, 5.33),
        (1, 9.33),
        (2, 5.46),
        (1, 11.59),
        (1, 10.56),
        (1, 10.98),
        (1, 11.24),
        (2, 4.23),
        (1, 10.86),
        (1, 10.46),
    ]
    points_downlink = [
        (1, 50.42),
        (2, 15.3),
        (1, 39.44),
        (2, 25.47),
        (1, 50.34),
        (1, 49.34),
        (1, 50.49),
        (1, 52.16),
        (2, 12.27),
        (1, 50.69),
        (1, 53.43),
    ]
    points_rtt = [
        (1, 14),
        (2, 145),
        (1, 15),
        (2, 127),
        (1, 15),
        (1, 14),
        (1, 19),
        (1, 12),
        (2, 108),
        (1, 13),
        (1, 13),
    ]

    # Plotting points on Uplink Boxplot
    for x, y in points_uplink:
        axes[0].scatter(jitter(x), y, marker='x', color=cmap(14), linewidth=0.5)

    # Plotting points on Downlink Boxplot
    for x, y in points_downlink:
        axes[1].scatter(jitter(x), y, marker='x', color=cmap(14), linewidth=0.5)

    # Plotting points on RTT Boxplot
    for x, y in points_rtt:
        axes[2].scatter(jitter(x), y, marker='x', color=cmap(14), linewidth=0.5)

    # Plot a dummy point for the legend (outside the visible range)
    #axes[0].scatter([-100], [-100], marker='x', color=cmap(14), linewidth=0.5, label='synchronization failure')
    #fig.legend(loc='upper center', bbox_to_anchor=(0.5, 1.1))

    if save:
        plt.savefig(
            "chart-connection-boxplot.png",
            dpi=900,
            bbox_inches="tight",
            transparent=True
        )

    if show:
        plt.show()


def main():
    #generate_measurement_stats_pie_chart(False, True)
    #generate_measurement_repeats_histogram(False, True)
    generate_connection_boxplots(False, True)


if __name__ == "__main__":
    main()
