#include <iomanip>
#include <fstream>
#include <cstring>

#include "include/solvers.hpp"
#include "include/helpers.hpp"

using namespace std;

int main(int argc, char* argv[]){
    const int decimal_places = 14;
    int N; // !! Number of steps between the discretization points (= N_points - 1)
    if (argc > 1) { // Get number of steps from command line argument
        N = atoi(argv[1]);
    } else {
        N = 1000;
    }

    bool output_to_file = true;
    if (argc > 2) { // Get output preference from command line argument (use "true" or "false", default is true)
        output_to_file = (strcmp(argv[2], "true") == 0);
    }

    const double delta_x = 1.0 / N;
    vector<double> a(N-1, -1.0);
    vector<double> b(N-1, 2.0);
    vector<double> c(N-1, -1.0);
    vector<double> g(N-1, 0.0);

    cout << "Running Poisson solver with N = " << N << endl;
    for (int i = 1; i < N; i++) {
        double x = i * delta_x;
        g[i-1] = delta_x * delta_x * f(x);
    }

    vector<double> solution = add_boundaries(general_algorithm(a, b, c, g));
    vector<double> x = get_x(N);
    vector<double> u = analytical_solution(x);
    double max_rel_error = relative_error(solution, u);
    cout << "Max relative error: " << max_rel_error << endl;

    if (output_to_file) {
        // Output the solution
        string filename = "numerical_solution_" + to_string(N) + ".csv";
        ofstream ofs(filename);
        ofs << "x,v(x),u(x)" << endl;
        for (int i = 0; i <= N; i++) {
            ofs << fixed << setprecision(decimal_places) << scientific << x[i] << "," << solution[i] << "," << u[i] << endl;
        }
        ofs.close();

    }

    return 0;
}

