# Hier der Schnitt so angepasst, dass die Daten zunächst einer linearen Regression unterzogen werden.
# Anschließend wird die Gesamtkraft auf basis der angepassten Kräfte neu berechnet
# und der Kraftverlauf in Abhängigkeit der Messpositionen gesetzt, um sie für die spätere Auswertung nutzbar zu machen

# Die Logik ist wie folgt:
# 8 Messstellen aber im Achsverlauf insgesamt 9 Punkte.
# Punkt 9 entspricht jedoch wieder Punkt 1, an welchen sich von links angenähert wird.
#
# |------------|------------|------------|------------|------------|------------|------------|------------|
# 1            2            3            4            5            6            7            8            9

import os
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt

folder_name = fr"Winkelversatz_4_V1_gekürzt"  # Namen an entsprechenden Ordner anpassen

input_folder = fr"C:\Users\simon\Desktop\Uni\Master\Master_Thesis\Versuchsdaten\Versuchsauswertung\extracted_data_for_single_drilling\{folder_name}"


# Set the font to "Charter"
plt.rcParams['font.family'] = 'Charter'
plt.rcParams['axes.titlesize'] = 30
plt.rcParams['axes.labelsize'] = 30
plt.rcParams['xtick.labelsize'] = 30
plt.rcParams['ytick.labelsize'] = 30
plt.rcParams['legend.fontsize'] = 30

# Funktion zum Sicherstellen, dass ein Ordner existiert
def ensure_folder_exists(folder_path):
    """Stellt sicher, dass der angegebene Ordner existiert."""
    if not os.path.exists(folder_path):
        os.makedirs(folder_path)

# Funktion zum Finden des ersten Index, an dem Position für 100 Zeilen konstant bleibt
def find_constant_position_index(position_series, window=100, tolerance=1e-6):
    """
    Findet den ersten Index, bei dem der Wert in der Spalte 'Position' für eine bestimmte Anzahl von Zeilen konstant bleibt.
    """
    for i in range(len(position_series) - window + 1):
        if np.all(np.abs(np.diff(position_series.iloc[i:i + window])) < tolerance):
            return i
    return None

def add_annotations_column(data, x_scale, num_points=9):
    """Fügt der DataFrame-Spalte Annotationen hinzu."""
    annotations = np.zeros(len(data))
    annotation_values = np.linspace(1, 9, num_points)
    for value in annotation_values:
        closest_index = (np.abs(x_scale - value)).idxmin()  # Nächster Wert
        array_index = data.index.get_loc(closest_index)  # Zu Array-Index konvertieren
        annotations[array_index] = value
    return annotations


# Funktion zur Berechnung und Korrektur mit einer einzigen Regressionslinie
def correct_force_with_regression(data, column_name):
    """
    Erstellt eine Regressionslinie basierend auf dem Mittelwert der ersten und letzten 100 Werte.
    """
    n_points = 100
    if len(data) < 2 * n_points:
        raise ValueError(f"Nicht genügend Daten für die Regression in Spalte '{column_name}'.")

    # Berechne den Mittelwert der ersten und letzten 100 Punkte
    start_mean = data[column_name].iloc[:n_points].mean()
    end_mean = data[column_name].iloc[-n_points:].mean()

    # Erstelle eine Regressionslinie zwischen Start- und Endmittelwert
    x_full = np.arange(len(data))
    regression_line = np.linspace(start_mean, end_mean, len(data))

    # Daten korrigieren
    corrected_data = data[column_name].values - regression_line
    return corrected_data

# Hauptfunktion zur Verarbeitung der CSV-Dateien
def process_csv_files(folder_path, output_folder):
    ensure_folder_exists(output_folder)
    csv_files = [f for f in os.listdir(folder_path) if f.endswith('.csv')]

    for csv_file in csv_files:
        input_file_path = os.path.join(folder_path, csv_file)
        output_file_name = f"processed_{csv_file}"
        output_file_path = os.path.join(output_folder, output_file_name)
        plot_file_name = f"processed_plot_{os.path.splitext(csv_file)[0]}.svg"
        plot_file_path = os.path.join(output_folder, plot_file_name)

        # CSV-Datei laden
        data = pd.read_csv(input_file_path)

        # Schritt 1.1: Filtere nach Total Force > 5
        start_index = data[data['Total Force (N)'] > 5].index.min()

        # Schritt 1.2: Endindex finden, bei dem "Position" für 100 Zeilen konstant ist
        if start_index is not None:
            constant_position_index = find_constant_position_index(data['Position'].iloc[start_index:])
            if constant_position_index is not None:
                end_index = start_index + constant_position_index
            else:
                # Fallback: Wenn kein konstantes Fenster gefunden wird, letzten Index verwenden
                end_index = len(data) - 1
        else:
            # Wenn kein Startindex gefunden wird, Datei überspringen
            continue

        # Schritt 1.3: Daten filtern
        force_filtered_data = data.loc[start_index:end_index + 1]

        # Schritt 2: Filtere nach Position (30 <= Position <= 120)
        # → Anpassen an die jeweilige Auflösung und Punkte bei Ein- und Auslauf!!!!!!!!!!
        # hier Auflösung von 90 Punkten über Umfang mit 5 Punkten Vor und Nachlauf
        # Startpunkt bei 90 Grad
        first_position_70_index = force_filtered_data[force_filtered_data['Position'] >= 70].index.min()
        last_position_106_index = force_filtered_data[force_filtered_data['Position'] <= 106].index.max()
        final_filtered_data = force_filtered_data.loc[first_position_70_index:last_position_106_index]
        final_filtered_data = final_filtered_data.copy()

        # Schritt 3: Regressionskorrektur für Kräfte
        for column in ['Axial Force (N)', 'Radial Force 1 (N)', 'Radial Force 2 (N)']:
            final_filtered_data[column] = correct_force_with_regression(final_filtered_data, column)

        # Schritt 4: Neu berechnete Total Force hinzufügen
        final_filtered_data['Total Force (N)'] = np.sqrt(
            final_filtered_data['Axial Force (N)']**2 +
            final_filtered_data['Radial Force 1 (N)']**2 +
            final_filtered_data['Radial Force 2 (N)']**2
        )


        # Schritt 5: Anpassen auf Entgratzyklus
        start_deburring = final_filtered_data[final_filtered_data['Position'] >= 90].index.min()
        end_deburring = final_filtered_data[final_filtered_data['Position'] <= 90].index.max()
        total_filtered_data = final_filtered_data.loc[start_deburring:end_deburring]

        # Schritt 6: X-Scale hinzufügen
        total_length = len(total_filtered_data)
        total_filtered_data = total_filtered_data.copy()
        total_filtered_data['X-Scale'] = np.linspace(1, 9, total_length)
        total_filtered_data['Annotations'] = add_annotations_column(total_filtered_data, total_filtered_data['X-Scale'])
        x_labels = [1, 2, 3, 4, 5, 6, 7, 8, 1]


        # Schritt 7: Gefilterte Daten speichern
        total_filtered_data.to_csv(output_file_path, index=False)
        print(f"Gefilterte Daten gespeichert in: {output_file_path}")

        # Plotte die gefilterten Daten
        columns_to_plot = [
            "Spindle Speed (RPM)", "Position", "Axial Force (N)",
            "Radial Force 1 (N)", "Radial Force 2 (N)", "Total Force (N)"
        ]
        valid_columns = [col for col in columns_to_plot if col in total_filtered_data.columns]
        fig, axs = plt.subplots(len(valid_columns), 1, figsize=(12, len(valid_columns) * 4), sharex=True)
        for i, column in enumerate(valid_columns):
            axs[i].plot(total_filtered_data['X-Scale'], total_filtered_data[column], label=column)
            axs[i].set_title(f"{column}")
            axs[i].set_ylabel(column)
            axs[i].grid(True)
        axs[-1].set_xticks(range(1, 10))
        axs[-1].set_xticklabels(x_labels)
        axs[-1].set_xlabel("Messpositionen")
        plt.tight_layout()
        plt.savefig(plot_file_path, format="svg")
        plt.close()
        print(f"Plot gespeichert in: {plot_file_path}")

# Eingabe- und Ausgabeordner
input_directory = fr"{input_folder}\vorgereinigt"
output_directory = fr"{input_folder}\final"

# CSV-Dateien verarbeiten
process_csv_files(input_directory, output_directory)
