/**
 * @file chirp_wave.c
 * @brief Example: generate linear and logarithmic chirps and compare their
 *        magnitude spectra.
 *
 * This program demonstrates MD_chirp_linear() and MD_chirp_log() by:
 *   1. Generating a linear chirp sweeping 200 Hz to 4000 Hz.
 *   2. Generating a logarithmic chirp over the same frequency range.
 *   3. Computing the magnitude spectrum of each.
 *   4. Writing results to CSV and to an interactive HTML visualisation
 *      (Plotly.js, no server required).
 *
 * Build and run (from the repository root):
 *   make                          # build libminidsp.a first
 *   make -C examples plot         # build example, run it, generate HTML
 *   open examples/chirp_wave.html # interactive spectrum plots
 */

#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include "minidsp.h"
#include "plot_html.h"

/* -----------------------------------------------------------------------
 * Write the interactive HTML visualisation.
 *
 * Shows two stacked magnitude-spectrum plots (linear chirp on top,
 * logarithmic chirp below) so the reader can compare how the two
 * sweep types distribute energy across frequency.
 * -----------------------------------------------------------------------*/
static int write_html(const char *path,
                      const double *freqs,
                      const double *mag_lin, const double *mag_log,
                      unsigned num_bins,
                      double sample_rate, unsigned N,
                      double f_start, double f_end)
{
    FILE *fp = fopen(path, "w");
    if (!fp) {
        fprintf(stderr, "cannot open %s for writing\n", path);
        return -1;
    }

    char subtitle[256];
    snprintf(subtitle, sizeof(subtitle),
        "%.0f &rarr; %.0f Hz chirps &nbsp;|&nbsp;\n"
        "    sample rate %.0f Hz &nbsp;|&nbsp;\n"
        "    FFT size %u",
        f_start, f_end, sample_rate, N);

    plot_html_begin(fp, "Chirp Wave Spectra", subtitle, 0);

    fprintf(fp,
        "  <div id=\"plot-linear\" class=\"plot-container\"></div>\n"
        "  <div id=\"plot-log\" class=\"plot-container\"></div>\n"
        "  <div class=\"info\">\n"
        "    <strong>What you are seeing:</strong><br>\n"
        "    A <em>linear chirp</em> sweeps frequency at a constant rate (Hz per\n"
        "    second), so every frequency in the range receives roughly equal\n"
        "    energy &mdash; the spectrum is relatively flat.<br>\n"
        "    A <em>logarithmic chirp</em> spends equal time per octave, so it\n"
        "    concentrates more energy at lower frequencies.  Compare the two\n"
        "    plots to see the difference.\n"
        "  </div>\n\n");

    /* ---- Embed spectrum data as JS arrays ---- */
    fprintf(fp, "  <script>\n");
    fprintf(fp, "    // Spectrum data generated by chirp_wave.c\n");
    plot_html_js_array(fp, "freqs",   freqs,   num_bins, "%.4f");
    plot_html_js_array(fp, "magLin",  mag_lin, num_bins, "%.8f");
    plot_html_js_array(fp, "magLog",  mag_log, num_bins, "%.8f");
    fprintf(fp, "\n");

    /* ---- Linear chirp plot ---- */
    fprintf(fp,
        "    Plotly.newPlot('plot-linear', [{\n"
        "      x: freqs, y: magLin,\n"
        "      type: 'scatter', mode: 'lines',\n"
        "      line: { color: '#2563eb', width: 1.2 },\n"
        "      name: 'Amplitude',\n"
        "      hovertemplate: '%%{x:.1f} Hz<br>Amplitude: %%{y:.6f}<extra></extra>'\n"
        "    }], {\n"
        "      title: { text: 'Linear Chirp &mdash; Magnitude Spectrum', font: { size: 15 } },\n"
        "      xaxis: { title: 'Frequency (Hz)', range: [0, %.1f] },\n"
        "      yaxis: { title: 'Amplitude' },\n"
        "      margin: { t: 55, r: 30, b: 55, l: 65 },\n"
        "      height: 340\n"
        "    }, { responsive: true });\n\n",
        sample_rate / 2.0);

    /* ---- Log chirp plot ---- */
    fprintf(fp,
        "    Plotly.newPlot('plot-log', [{\n"
        "      x: freqs, y: magLog,\n"
        "      type: 'scatter', mode: 'lines',\n"
        "      line: { color: '#dc2626', width: 1.2 },\n"
        "      name: 'Amplitude',\n"
        "      hovertemplate: '%%{x:.1f} Hz<br>Amplitude: %%{y:.6f}<extra></extra>'\n"
        "    }], {\n"
        "      title: { text: 'Logarithmic Chirp &mdash; Magnitude Spectrum', font: { size: 15 } },\n"
        "      xaxis: { title: 'Frequency (Hz)', range: [0, %.1f] },\n"
        "      yaxis: { title: 'Amplitude' },\n"
        "      margin: { t: 55, r: 30, b: 55, l: 65 },\n"
        "      height: 340\n"
        "    }, { responsive: true });\n"
        "  </script>\n",
        sample_rate / 2.0);

    plot_html_end(fp);
    fclose(fp);
    return 0;
}

int main(void)
{
    /* ------------------------------------------------------------------
     * Signal parameters
     * ----------------------------------------------------------------*/
    const unsigned N           = 4096;       /* FFT size (samples)    */
    const double   sample_rate = 16000.0;    /* Hz                    */
    const double   f_start     = 200.0;      /* sweep start (Hz)      */
    const double   f_end       = 4000.0;     /* sweep end (Hz)        */
    const double   amplitude   = 1.0;
    const unsigned num_bins    = N / 2 + 1;

    /* ------------------------------------------------------------------
     * Allocate buffers
     * ----------------------------------------------------------------*/
    double *sig_lin = malloc(N * sizeof(double));
    double *sig_log = malloc(N * sizeof(double));
    double *mag_lin = malloc(num_bins * sizeof(double));
    double *mag_log = malloc(num_bins * sizeof(double));
    double *freqs   = malloc(num_bins * sizeof(double));

    if (!sig_lin || !sig_log || !mag_lin || !mag_log || !freqs) {
        fprintf(stderr, "allocation failed\n");
        return 1;
    }

    /* ------------------------------------------------------------------
     * Generate both chirp types
     * ----------------------------------------------------------------*/
    //! [generate-chirps]
    MD_chirp_linear(sig_lin, N, amplitude, f_start, f_end, sample_rate);
    MD_chirp_log(sig_log, N, amplitude, f_start, f_end, sample_rate);
    //! [generate-chirps]

    /* ------------------------------------------------------------------
     * Compute magnitude spectra
     * ----------------------------------------------------------------*/
    MD_magnitude_spectrum(sig_lin, N, mag_lin);
    MD_magnitude_spectrum(sig_log, N, mag_log);

    /* Convert to single-sided amplitude spectra */
    for (unsigned k = 0; k < num_bins; k++) {
        freqs[k] = (double)k * sample_rate / (double)N;
        mag_lin[k] /= (double)N;
        mag_log[k] /= (double)N;
        if (k > 0 && k < N / 2) {
            mag_lin[k] *= 2.0;
            mag_log[k] *= 2.0;
        }
    }

    /* ------------------------------------------------------------------
     * Write results to CSV
     * ----------------------------------------------------------------*/
    const char *csv_file = "chirp_wave.csv";
    FILE *fp = fopen(csv_file, "w");
    if (!fp) {
        fprintf(stderr, "cannot open %s for writing\n", csv_file);
        return 1;
    }

    fprintf(fp, "bin,frequency_hz,mag_linear,mag_log\n");
    for (unsigned k = 0; k < num_bins; k++)
        fprintf(fp, "%u,%.4f,%.8f,%.8f\n", k, freqs[k], mag_lin[k], mag_log[k]);
    fclose(fp);

    printf("Wrote %u frequency bins to %s\n", num_bins, csv_file);

    /* ------------------------------------------------------------------
     * Write interactive HTML visualisation
     * ----------------------------------------------------------------*/
    const char *html_file = "chirp_wave.html";
    if (write_html(html_file, freqs, mag_lin, mag_log, num_bins,
                   sample_rate, N, f_start, f_end) == 0) {
        printf("Wrote interactive plot to %s\n", html_file);
    }

    printf("Linear chirp: %.0f -> %.0f Hz, amplitude %.1f\n",
           f_start, f_end, amplitude);
    printf("Log chirp:    %.0f -> %.0f Hz, amplitude %.1f\n",
           f_start, f_end, amplitude);
    printf("Sample rate: %.0f Hz, FFT size: %u\n", sample_rate, N);

    /* ------------------------------------------------------------------
     * Cleanup
     * ----------------------------------------------------------------*/
    free(freqs);
    free(mag_log);
    free(mag_lin);
    free(sig_log);
    free(sig_lin);
    MD_shutdown();

    return 0;
}
