#include "include/fft.h"

#include <fftw3.h>
#include <utility>
#include <memory>
#include <stdexcept>
#include <iostream>
#include <cmath>

class DctCalculator::Impl {
public:
    Impl(size_t width, std::vector<double> *input, std::vector<double> *output) : width_(width), input_(input), output_(output) {
        if (input_->empty()) {
            throw std::invalid_argument("input is empty");
        }
        if (output_->size() != input_->size()) {
            throw std::invalid_argument("incorrect output place");
        }
        if (input_->size() != width_ * width_) {
            throw std::invalid_argument("incorrect dimension");
        }
        scale = (1.0 / (2 * width_));
//        plan_ = fftw_plan_r2r_2d(width_, width_, input_->data(), output_->data(), FFTW_REDFT01, FFTW_REDFT01, FFTW_MEASURE);
    }
    void Inverse(){

//        std::vector<double> temp;
//        temp.resize(width_ * width_);

//        for (size_t i = 0; i < input_->size(); ++i) {
//            (*input_)[i] /= scale;
//            std::cout << (*output_)[i] << ' ';
//        }

        plan_ = fftw_plan_r2r_2d(width_, width_, input_->data(), output_->data(), FFTW_REDFT01, FFTW_REDFT01, FFTW_EXHAUSTIVE);
        fftw_execute_r2r(plan_, input_->data(), output_->data());
        fftw_destroy_plan(plan_);

//        plan_ = fftw_plan_r2r_2d(width_, width_, temp.data(), output_->data(), FFTW_REDFT01, FFTW_REDFT01, FFTW_MEASURE);
//        fftw_execute(plan_);
//        plan_ = fftw_plan_r2r_2d(width_, width_, output_->data(), output_->data(), FFTW_REDFT01, FFTW_REDFT01, FFTW_MEASURE);
//        fftw_execute(plan_);
//        for(size_t i = 0; i < output_->size(); ++i) {
//            (*output_)[i] /= scale;
//            std::cout << (*output_)[i] << ' ';
//        }
        std::cout << "Input: ";
        for (size_t i = 0; i < input_->size(); ++i) {
            if ((*input_)[i] > 256.0) {
                (*input_)[i] -= 256;
            }
            std::cout << (*input_)[i] << ' ';
        }

        std::cout << "\nOutput before scaling: ";
        for (size_t i = 0; i < output_->size(); ++i) {
            std::cout << (*output_)[i] << ' ';
        }

        std::cout << "\nOutput after scaling: ";
        for (size_t i = 0; i < width_; ++i) {
            for (size_t j = 0; j < width_; ++j) {
//                if (i == 0) (*output_)[i * width_ + j] *= M_SQRT1_2; // 1 / sqrt(2)
//                if (j == 0) (*output_)[i * width_ + j] *= M_SQRT1_2; // 1 / sqrt(2)

                (*output_)[i * width_ + j] *= Alpha(i) * Alpha(j) * 2.0 * scale;
                std::cout << (*output_)[i * width_ + j] << ' ';
            }
        }
//        for (size_t i = 0; i < output_->size(); ++i) {
//            (*output_)[i] *= scale;
//            std::cout << (*output_)[i] << ' ';
//        }
    }

private:
    size_t width_;
    double scale;
    std::vector<double> *input_;
    std::vector<double> *output_;
    fftw_plan plan_;

    double Alpha(size_t index) {
        if (index == 0) {
            return M_SQRT1_2;
        }
        return 1;
    }

};

DctCalculator::DctCalculator(size_t width, std::vector<double> *input, std::vector<double> *output)
    : impl_(std::make_unique<Impl>(width, input, output)) {
}

void DctCalculator::Inverse() {
    impl_->Inverse();
}

DctCalculator::~DctCalculator() = default;


что делать, если этот код не заходит