#pragma once

#include <memory>
#include <vector>
#include "source_lcao/module_hcontainer/hcontainer.h"
#include "gint.h"
#include "gint_info.h"
#include "source_lcao/module_gint/temp_gint/kernel/cuda_mem_wrapper.h"

namespace ModuleGint
{

class Gint_vl_metagga_nspin4_gpu : public Gint
{
    public:
    Gint_vl_metagga_nspin4_gpu(
        std::vector<const double*> vr_eff,
        std::vector<const double*> vofk,
        HContainer<std::complex<double>>* hR)
        : vr_eff_(vr_eff), vofk_(vofk), hR_(hR), dr3_(gint_info_->get_mgrid_volume()) {}
    
    void cal_gint();

    private:
    void init_hr_gint_();

    void transfer_cpu_to_gpu_();

    void transfer_gpu_to_cpu_();
    
    void cal_hr_gint_();

    // input
    std::vector<const double*> vr_eff_;
    std::vector<const double*> vofk_;
    // output
    HContainer<std::complex<double>>* hR_;

    // Intermediate variables
    const double dr3_;

    const int nspin_ = 4;

    std::vector<HContainer<double>> hr_gint_part_;
    HContainer<std::complex<double>> hr_gint_full_;
    
    std::vector<CudaMemWrapper<double>> vr_eff_d_;
    std::vector<CudaMemWrapper<double>> vofk_d_;
    std::vector<CudaMemWrapper<double>> hr_gint_part_d_;
};

}