/// @file output.cpp
/// @brief Implementation of the Touchstone export code and output data via
/// terminal console
/// @author Andrés Martínez Mera - andresmmera@protonmail.com
/// @date Jan 3, 2026
/// @copyright Copyright (C) 2026 Andrés Martínez Mera
/// @license GPL-3.0-or-later

#include "SParameterCalculator.h"

void SParameterCalculator::exportTouchstone(const QString &filename,
                                            const vector<vector<Complex>> &S) {
  QFile file(filename);
  if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) {
    cerr << "Error: Cannot create output file " << filename.toStdString()
         << endl;
    return;
  }

  QTextStream out(&file);

  // Write header
  out << "! Touchstone file generated by SParameterCalculator\n";
  out << "# GHz S MA R " << ports[0].impedance << "\n";

  // Write S-parameters
  double freqGHz = frequency / 1e9;
  out << freqGHz;

  for (size_t i = 0; i < S.size(); i++) {
    for (size_t j = 0; j < S[i].size(); j++) {
      double mag = abs(S[i][j]);
      double phase = arg(S[i][j]) * 180.0 / M_PI;
      out << " " << mag << " " << phase;
    }
  }

  out << "\n";

  file.close();
  cout << "S-parameters exported to " << filename.toStdString() << endl;
}

void SParameterCalculator::exportSweepTouchstone(
    const QString &filename) const {
  QFile file(filename);
  if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) {
    cerr << "Error: Cannot create output file " << filename.toStdString()
         << endl;
    return;
  }

  QTextStream out(&file);

  // Write header
  out << "! Touchstone file generated by SParameterCalculator\n";
  out << "# GHz S MA R " << (ports.empty() ? 50.0 : ports[0].impedance) << "\n";

  // Write S-parameters for each frequency
  double step = (n_points == 1) ? 0 : (f_stop - f_start) / (n_points - 1);

  for (int i = 0; i < n_points; ++i) {
    double freq = f_start + i * step;
    double freqGHz = freq / 1e9;
    const auto &S = sweepResults[i];

    out << freqGHz;

    for (const auto &rowVec : S) {
      for (const auto &value : rowVec) {
        double mag = abs(value);
        double phase = arg(value) * 180.0 / M_PI;
        out << " " << mag << " " << phase;
      }
    }

    out << "\n";
  }

  file.close();
  cout << "Frequency sweep exported to " << filename.toStdString() << endl;
}

void SParameterCalculator::printSParameters(const vector<vector<Complex>> &S) {
  int numPorts = S.size();

  cout << "S-Parameters at frequency " << frequency / 1e9 << " GHz:" << endl;
  cout << "----------------------------------------" << endl;

  for (int i = 0; i < numPorts; i++) {
    for (int j = 0; j < numPorts; j++) {
      double mag = abs(S[i][j]);
      double phase = arg(S[i][j]) * 180.0 / M_PI;
      double magDB = 20 * log10(mag);

      cout << "S(" << i + 1 << "," << j + 1 << "): " << mag << " ∠" << phase
           << "° " << "(" << magDB << " dB)" << endl;
    }
  }
}

void SParameterCalculator::printSParameterSweep() const {
  double step = (n_points == 1) ? 0 : (f_stop - f_start) / (n_points - 1);

  for (int i = 0; i < n_points; ++i) {
    double freq = f_start + i * step;
    const auto &S = sweepResults[i];
    int numPorts = S.size();

    std::cout << "S-Parameters at frequency " << freq / 1e9 << " GHz (" << freq
              << " Hz):\n";
    std::cout << "----------------------------------------\n";

    for (int i = 0; i < numPorts; ++i) {
      for (int j = 0; j < numPorts; ++j) {
        double mag = abs(S[i][j]);
        double phase = arg(S[i][j]) * 180.0 / M_PI;
        double magDB = 20 * log10(mag);
        std::cout << "S(" << i + 1 << "," << j + 1 << "): " << mag << " ∠"
                  << phase << "° " << "(" << magDB << " dB)\n";
      }
    }
    std::cout << std::endl;
  }
}
