// dllmain.cpp : Definisce il punto di ingresso per l'applicazione DLL.
#include "pch.h"

BOOL APIENTRY DllMain(HMODULE hModule,
    DWORD  ul_reason_for_call,
    LPVOID lpReserved
)
{
    switch (ul_reason_for_call)
    {
    case DLL_PROCESS_ATTACH:
    case DLL_THREAD_ATTACH:
    case DLL_THREAD_DETACH:
    case DLL_PROCESS_DETACH:
        break;
    }
    return TRUE;
}

#define EXPORTING_DLL
#include "Intestazione.h"
#include <stdio.h>
#include <stdlib.h>


void delay(double* input, double* output, int N, int M) {
    // Implementazione della funzione delay (esempio)
    for (int i = 0; i < N; i++) {
        output[i] = (i >= M) ? input[i - M] : 0;
    }
}

void STDCALL differentiator(double x[], double y[], int N, int M)
{
    double* d = (double*)malloc(N * sizeof(double));
    if (d == NULL) {
        // Gestione del fallimento dell'allocazione
        printf("Memory allocation failed\n");
        return;
    }

    // Debug prima di chiamare delay
    printf("Before delay: N=%d, M=%d\n", N, M);
    for (int i = 0; i < N; i++) {
        printf("x[%d]=%f\n", i, x[i]);
    }

    delay(x, d, N, M);

    // Debug dopo aver chiamato delay
    for (int i = 0; i < N; i++) {
        printf("d[%d]=%f\n", i, d[i]);
    }

    for (int i = 0; i < N; i++) {
        y[i] = x[i] - d[i];
    }

    free(d);
}

void STDCALL iir_1st(double x[], double y[], int N, double b0, double b1, double a1)
{
    y[0] = x[0];
    for (int i = 1; i < N; i++)
    {
        y[i] = b0 * x[i] + b1 * x[i - 1] - a1 * y[i - 1];
    }
}

void STDCALL iir_2nd(double x[], double y[], int N, double b0, double b1, double b2, double a1, double a2)
{
    y[0] = x[0];
    y[1] = x[1];
    for (int i = 2; i < N; i++)
    {
        y[i] = b0 * x[i] + b1 * x[i - 1] + b2 * x[i - 2] - a1 * y[i - 1] - a2 * y[i - 2];
    }
}

void STDCALL trapz(double x[], double y[], int N, double beta, int R, int M)
{
    double* p1 = (double*)malloc(N * sizeof(double));
    double* p2 = (double*)malloc(N * sizeof(double));
    double* p3 = (double*)malloc(N * sizeof(double));
    double* p4 = (double*)malloc(N * sizeof(double));

    if (p1 == NULL || p2 == NULL || p3 == NULL || p4 == NULL) {
        // handle allocation failure
        free(p1);
        free(p2);
        free(p3);
        free(p4);
        return;
    }

    differentiator(x, p1, N, R);
    differentiator(p1, p2, N, R + M);

    double b0_1 = 0.;
    double b1_1 = -1.;
    double b0_2 = 1.;
    double b1_2 = -beta;
    double a1 = -1.;

    iir_1st(p2, p3, N, b0_1, b1_1, a1);
    iir_1st(p3, p4, N, b0_2, b1_2, a1);

    for (int i = 0; i < N; i++)
    {
        y[i] = -p4[i] / ((double)R);
    }

    free(p1);
    free(p2);
    free(p3);
    free(p4);
}

void STDCALL timing_flt(double x[], double y[], int N, int C, int F)
{
    double* p1 = (double*)malloc(N * sizeof(double));
    double* p2 = (double*)malloc(N * sizeof(double));

    if (p1 == NULL || p2 == NULL) {
        // handle allocation failure
        free(p1);
        free(p2);
        return;
    }

    double b0 = 0.;
    double b1 = 1.;
    double a1 = -1.;

    iir_1st(x, p1, N, b0, b1, a1);
    differentiator(p1, p2, N, C);
    differentiator(p2, y, N, F);

    free(p1);
    free(p2);
}
