import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from sklearn.datasets import make_blobs
from sklearn.metrics import accuracy_score
import plotly.graph_objects as go


def check_list_sizes(interfaces, amplitudes, profondeur, position_debut, position_fin):
    sizes = [len(interfaces), len(amplitudes), len(profondeur), len(position_debut), len(position_fin)]
    if len(set(sizes)) > 1:
        raise ValueError("Toutes les listes doivent avoir la même taille")

def check_positions(position_debut, position_fin):
    for debut, fin in zip(position_debut, position_fin):
        if debut > fin:
            raise ValueError("Un élément de position_debut est plus grand que son élément associé dans position_fin")

def demi_sinusoidal(liste :list[int],debut, fin, amplitude):
    liste_copy = liste.copy()
    x = np.linspace(0, np.pi, fin-debut)
    y = amplitude * np.sin(x)**12
    y = y.astype(int)
    liste_copy[debut:fin] = y
    return liste_copy

def bruit_blanc_gaussien(liste,moyenne, ecart_type):
    liste_copy = liste.copy()
    bruit = np.random.normal(moyenne, ecart_type, len(liste))
    bruit = bruit.astype(int)
    bruit = np.abs(bruit)
    liste_bruitee = liste_copy + bruit
    return liste_bruitee

def Ascan (liste, interfaces, amplitudes, profondeur):
    for interface, amplitude, profondeur in zip(interfaces, amplitudes, profondeur):
        liste = demi_sinusoidal(liste, interface, interface + profondeur, amplitude)
    liste = bruit_blanc_gaussien(liste, 0, 20)
    return liste

def Bscan (liste, interfaces, amplitudes, profondeur, position_debut, position_fin, trainee):
    Bscan = []
    initial_amplitudes = amplitudes.copy()
    for i in range(0, 1000):
        for j in range(0, len(interfaces)):
            if i < position_debut[j]:
                if i > position_debut[j] - trainee:
                    amplitudes[j] = int((amplitudes[j] / trainee) * (i - position_debut[j] + trainee))
                else:
                    amplitudes[j] = 0
            if i > position_fin[j]:
                if i < position_fin[j] + trainee:
                    amplitudes[j] = int((amplitudes[j] / trainee) * (position_fin[j] + trainee - i))
                else:
                    amplitudes[j] = 0
        # Générer le Ascan avec les amplitudes modifiées
        liste = Ascan(liste, interfaces, amplitudes, profondeur)
        Bscan.append(liste)
        # Réinitialiser les amplitudes pour le prochain Ascan
        liste = np.zeros(1000)
        amplitudes = initial_amplitudes.copy()

    return Bscan

def Cscan(nombre_de_scans, interfaces, amplitudes,profondeur, position_debut, position_fin, trainee):
    Cscan_liste = []  # Liste pour stocker chaque Bscan

    # Générer des Bscans pour différents instants/conditions
    for _ in range(nombre_de_scans):
        Bscan_result = Bscan(np.zeros(1000), interfaces, amplitudes, profondeur, position_debut, position_fin, trainee)
        Cscan_liste.append(np.array(Bscan_result))

    # Convertir la liste des Bscans en un array 3D
    Cscan_array = np.stack(Cscan_liste, axis=0)
    return Cscan_array

def main_func(liste,interfaces,amplitudes,profondeur,position_debut,position_fin,trainee) -> None:
    check_list_sizes(interfaces, amplitudes, profondeur, position_debut, position_fin)

    check_positions(position_debut, position_fin)

    # Appeler la fonction Cscan pour générer le tableau 3D
    nombre_de_scans = 5  # Par exemple, générer 5 Bscans
    Cscan_3D = Cscan(nombre_de_scans, interfaces, amplitudes, profondeur, position_debut, position_fin, trainee)

    print("Forme du tableau 3D Cscan:", Cscan_3D.shape)
    print(Cscan_3D[:,0])
    # image CSCAN
    fig = plt.figure()
    ax = fig.add_subplot(111, projection='3d')
    # Affichage de l'image 3D
    image = ax.plot_surface(Cscan_3D[:,0],Cscan_3D[:,1], Cscan_3D[:,2], cmap='viridis')
    # Ajout de la barre de couleur
    fig.colorbar(image)

    # Affichage du graphique
    plt.show()

    #fig = go.Figure(data=[go.Scatter3d(x=Cscan_3D[:, 0].flatten(),y=Cscan_3D[:, 1].flatten(),z=Cscan_3D[:,2].flatten(),mode='markers')])
    #fig.update_layout(template= "plotly_dark", margin=dict(l=0, r=0, b=0, t=0))
    #fig.layout.scene.camera.projection.type = "orthographic"
    
    #fig.colorbar()
    #fig.show()



    Bscan_result = Bscan(liste, interfaces, amplitudes,profondeur, position_debut, position_fin, trainee)

    Bscan_array = np.array(Bscan_result)

    df_bscan = pd.DataFrame(Bscan_array)

  


    print(df_bscan.head())

    # Sauvegarder le DataFrame en CSV
    df_bscan.to_csv("Bscan_data.csv", index=False)
    
    # Utiliser imshow pour afficher Bscan sous forme de heatmap
    plt.imshow(Bscan_array, aspect='auto', origin='lower', cmap='jet')
    plt.colorbar()  # Ajouter une barre de couleur pour représenter l'échelle des intensités
    plt.title("Bscan Heatmap")
    plt.xlabel("Profondeur scan")
    plt.ylabel("Numéro de Ascan")
    plt.show()
