#include "Wind2ERANc.h"
#include "WindDataFileOperator.h"
 


DataFileInfo get_data_file_info(const std::string& filepath) {
    DataFileInfo info;
    // 这里需要实现从二进制文件读取头信息的逻辑
    std::ifstream file(filepath, std::ios::binary);
    if (file) {
        file.read(reinterpret_cast<char*>(&info), sizeof(DataFileInfo));
        file.close();
    }
    return info;
}

std::vector<int64_t> get_wind_data_file_time_arr(const std::string& filepath, const DataFileInfo& info) {
    std::vector<int64_t> time_arr(info.Num);
    if (get_WindDataFileTimeArr(filepath.c_str(), info, time_arr.data()) == 0) {
        return time_arr;
    }
    else {
        std::vector<int64_t> time_arra(0);
        return  time_arra;
    }


    
}

bool read_wind_data_file(const std::string& filepath, const DataFileInfo& info,
    int64_t time_id, std::vector<double>& u_arr, std::vector<double>& v_arr) {
    if (Read_WindDataFile(filepath.c_str(),
        info, 
        time_id, u_arr.data(), v_arr.data()) == 0) {
        return true;
    }

    return false;
}


    // 处理NetCDF错误
    void ERA5NetCDFConverter::handle_netcdf_error(int status, const std::string& operation) {
        if (status != NC_NOERR) {
            std::cerr << "NetCDF错误 " << operation << ": " << nc_strerror(status) << std::endl;
            throw std::runtime_error("NetCDF操作失败");
        }
    }

    // 将Unix时间戳转换为ERA5使用的时间格式
    std::vector<double> ERA5NetCDFConverter::convert_to_era5_time(const std::vector<int64_t>& unix_timestamps) {
        std::vector<double> era5_times;
        era5_times.reserve(unix_timestamps.size());

        // ERA5时间通常是从1900-01-01开始的小时数
        const auto era5_epoch = std::chrono::system_clock::from_time_t(-2208988800); // 1900-01-01

        for (auto timestamp : unix_timestamps) {
            auto time_point = std::chrono::system_clock::from_time_t(timestamp);
            auto duration = std::chrono::duration_cast<std::chrono::hours>(time_point - era5_epoch);
            era5_times.push_back(static_cast<double>(duration.count()));
        }

        return era5_times;
    }

    // 创建经纬度坐标数组
    std::vector<double> ERA5NetCDFConverter::create_coordinate_array(double min, double max, size_t size) {
        std::vector<double> coord(size);
        double step = (max - min) / (size - 1);
        for (size_t i = 0; i < size; ++i) {
            coord[i] = min + i * step;
        }
        return coord;
    }

    bool ERA5NetCDFConverter::convert_to_era5_netcdf(const std::string& input_bin_file, const std::string& output_nc_file) {
        try {
            // 1. 读取二进制文件信息
            DataFileInfo info = getDataFileInfo(input_bin_file.c_str());
            std::cout << "文件信息: " << info.Height << "x" << info.Width
                << " 网格, " << info.Num << " 个时间步" << std::endl;

            // 2. 获取时间数组
            std::vector<int64_t> time_arr = get_wind_data_file_time_arr(input_bin_file.c_str(), info);
            if (time_arr.empty()) {
                std::cerr << "无法读取时间数组" << std::endl;
                return false;
            }

            // 3. 创建NetCDF文件
            int ncid, status;
            status = nc_create(output_nc_file.c_str(), NC_NETCDF4, &ncid);
            handle_netcdf_error(status, "创建文件");

            // 4. 定义维度
            int lon_dim, lat_dim, time_dim;
            status = nc_def_dim(ncid, "longitude", info.Width, &lon_dim);
            handle_netcdf_error(status, "定义经度维度");
            status = nc_def_dim(ncid, "latitude", info.Height, &lat_dim);
            handle_netcdf_error(status, "定义纬度维度");
            status = nc_def_dim(ncid, "time", NC_UNLIMITED, &time_dim);
            handle_netcdf_error(status, "定义时间维度");

            // 5. 定义坐标变量
            int lon_var, lat_var, time_var;
            int dims_coord[1] = { lon_dim };
            status = nc_def_var(ncid, "longitude", NC_DOUBLE, 1, dims_coord, &lon_var);
            handle_netcdf_error(status, "定义经度变量");

            dims_coord[0] = lat_dim;
            status = nc_def_var(ncid, "latitude", NC_DOUBLE, 1, dims_coord, &lat_var);
            handle_netcdf_error(status, "定义纬度变量");

            dims_coord[0] = time_dim;
            status = nc_def_var(ncid, "time", NC_DOUBLE, 1, dims_coord, &time_var);
            handle_netcdf_error(status, "定义时间变量");

            // 6. 定义数据变量（U和V分量）
            int u10_var, v10_var;
            int dims_data[3] = { time_dim, lat_dim, lon_dim };
            status = nc_def_var(ncid, "u10", NC_DOUBLE, 3, dims_data, &u10_var);
            handle_netcdf_error(status, "定义u10变量");
            status = nc_def_var(ncid, "v10", NC_DOUBLE, 3, dims_data, &v10_var);
            handle_netcdf_error(status, "定义v10变量");

            // 7. 添加属性
            std::string time_units = "hours since 1900-01-01 00:00:00.0";
            status = nc_put_att_text(ncid, time_var, "units", time_units.length(), time_units.c_str());
            handle_netcdf_error(status, "添加时间单位属性");

            status = nc_put_att_text(ncid, lon_var, "units", 12, "degrees_east");
            status = nc_put_att_text(ncid, lat_var, "units", 13, "degrees_north");
            status = nc_put_att_text(ncid, u10_var, "units", 6, "m s**-1");
            status = nc_put_att_text(ncid, v10_var, "units", 6, "m s**-1");
            status = nc_put_att_text(ncid, u10_var, "long_name", 25, "10 metre U wind component");
            status = nc_put_att_text(ncid, v10_var, "long_name", 25, "10 metre V wind component");

            // 8. 结束定义模式
            status = nc_enddef(ncid);
            handle_netcdf_error(status, "结束定义模式");

            // 9. 写入坐标数据
            std::vector<double> lon_data = create_coordinate_array(info.minLon, info.maxLon, info.Width);
            std::vector<double> lat_data = create_coordinate_array(info.minLat, info.maxLat, info.Height);
            std::reverse(lat_data.begin(), lat_data.end());
            std::vector<double> era5_time = convert_to_era5_time(time_arr);

            status = nc_put_var_double(ncid, lon_var, lon_data.data());
            handle_netcdf_error(status, "写入经度数据");
            status = nc_put_var_double(ncid, lat_var, lat_data.data());
            handle_netcdf_error(status, "写入纬度数据");
            status = nc_put_var_double(ncid, time_var, era5_time.data());
            handle_netcdf_error(status, "写入时间数据");

            // 10. 写入风场数据
            std::vector<double> u_data(info.Height * info.Width);
            std::vector<double> v_data(info.Height * info.Width);

            size_t start[3] = { 0, 0, 0 };
            size_t count[3] = { 1, info.Height, info.Width };

            for (int64_t t = 0; t < info.Num; ++t) {
                if (read_wind_data_file(input_bin_file, info, t, u_data, v_data)) {
                    start[0] = t;
                    status = nc_put_vara_double(ncid, u10_var, start, count, u_data.data());
                    handle_netcdf_error(status, "写入u10数据");
                    status = nc_put_vara_double(ncid, v10_var, start, count, v_data.data());
                    handle_netcdf_error(status, "写入v10数据");

                    if (t % 10 == 0) {
                        std::cout << "已处理 " << t + 1 << "/" << info.Num << " 个时间步" << std::endl;
                    }
                }
            }

            // 11. 关闭文件
            status = nc_close(ncid);
            handle_netcdf_error(status, "关闭文件");

            std::cout << "转换完成！输出文件: " << output_nc_file << std::endl;
            return true;

        }
        catch (const std::exception& e) {
            std::cerr << "转换过程出错: " << e.what() << std::endl;
            return false;
        }
    }

    bool ERA5NetCDFConverter::convert_to_era5_netcdf(const std::string& input_bin_file, const std::string& output_nc_file, int64_t tid)
    {
        try {
            // 1. 读取二进制文件信息
            DataFileInfo info = getDataFileInfo(input_bin_file.c_str());
            std::cout << "文件信息: " << info.Height << "x" << info.Width
                << " 网格, " << info.Num << " 个时间步" << std::endl;

            // 2. 获取时间数组
            std::vector<int64_t> time_arr = get_wind_data_file_time_arr(input_bin_file.c_str(), info);
            if (time_arr.empty()) {
                std::cerr << "无法读取时间数组" << std::endl;
                return false;
            }

            // 3. 创建NetCDF文件
            int ncid, status;
            status = nc_create(output_nc_file.c_str(), NC_NETCDF4, &ncid);
            handle_netcdf_error(status, "创建文件");

            // 4. 定义维度
            int lon_dim, lat_dim, time_dim;
            status = nc_def_dim(ncid, "longitude", info.Width, &lon_dim);
            handle_netcdf_error(status, "定义经度维度");
            status = nc_def_dim(ncid, "latitude", info.Height, &lat_dim);
            handle_netcdf_error(status, "定义纬度维度");
            status = nc_def_dim(ncid, "time", NC_UNLIMITED, &time_dim);
            handle_netcdf_error(status, "定义时间维度");

            // 5. 定义坐标变量
            int lon_var, lat_var, time_var;
            int dims_coord[1] = { lon_dim };
            status = nc_def_var(ncid, "longitude", NC_DOUBLE, 1, dims_coord, &lon_var);
            handle_netcdf_error(status, "定义经度变量");

            dims_coord[0] = lat_dim;
            status = nc_def_var(ncid, "latitude", NC_DOUBLE, 1, dims_coord, &lat_var);
            handle_netcdf_error(status, "定义纬度变量");

            dims_coord[0] = time_dim;
            status = nc_def_var(ncid, "time", NC_DOUBLE, 1, dims_coord, &time_var);
            handle_netcdf_error(status, "定义时间变量");

            // 6. 定义数据变量（U和V分量）
            int u10_var, v10_var;
            int dims_data[3] = { time_dim, lat_dim, lon_dim };
            status = nc_def_var(ncid, "u10", NC_DOUBLE, 3, dims_data, &u10_var);
            handle_netcdf_error(status, "定义u10变量");
            status = nc_def_var(ncid, "v10", NC_DOUBLE, 3, dims_data, &v10_var);
            handle_netcdf_error(status, "定义v10变量");

            // 7. 添加属性
            std::string time_units = "hours since 1900-01-01 00:00:00.0";
            status = nc_put_att_text(ncid, time_var, "units", time_units.length(), time_units.c_str());
            handle_netcdf_error(status, "添加时间单位属性");

            status = nc_put_att_text(ncid, lon_var, "units", 12, "degrees_east");
            status = nc_put_att_text(ncid, lat_var, "units", 13, "degrees_north");
            status = nc_put_att_text(ncid, u10_var, "units", 6, "m s**-1");
            status = nc_put_att_text(ncid, v10_var, "units", 6, "m s**-1");
            status = nc_put_att_text(ncid, u10_var, "long_name", 25, "10 metre U wind component");
            status = nc_put_att_text(ncid, v10_var, "long_name", 25, "10 metre V wind component");

            // 8. 结束定义模式
            status = nc_enddef(ncid);
            handle_netcdf_error(status, "结束定义模式");

            // 9. 写入坐标数据
            std::vector<double> lon_data = create_coordinate_array(info.minLon, info.maxLon, info.Width);
            std::vector<double> lat_data = create_coordinate_array(info.minLat, info.maxLat, info.Height);
            std::vector<double> era5_time = convert_to_era5_time(time_arr);
            std::reverse(lat_data.begin(), lat_data.end());
            status = nc_put_var_double(ncid, lon_var, lon_data.data());
            handle_netcdf_error(status, "写入经度数据");
            status = nc_put_var_double(ncid, lat_var, lat_data.data());
            handle_netcdf_error(status, "写入纬度数据");
            status = nc_put_var_double(ncid, time_var, era5_time.data());
            handle_netcdf_error(status, "写入时间数据");

            // 10. 写入风场数据
            std::vector<double> u_data(info.Height * info.Width);
            std::vector<double> v_data(info.Height * info.Width);

            size_t start[3] = { 0, 0, 0 };
            size_t count[3] = { 1, info.Height, info.Width };

            for (int64_t t = 0; t < info.Num; ++t) {
                if (t != tid) { continue; }
                if (read_wind_data_file(input_bin_file, info, t, u_data, v_data)) {
                    start[0] = t;
                    status = nc_put_vara_double(ncid, u10_var, start, count, u_data.data());
                    handle_netcdf_error(status, "写入u10数据");
                    status = nc_put_vara_double(ncid, v10_var, start, count, v_data.data());
                    handle_netcdf_error(status, "写入v10数据");

                    if (t % 10 == 0) {
                        std::cout << "已处理 " << t + 1 << "/" << info.Num << " 个时间步" << std::endl;
                    }
                }
            }

            // 11. 关闭文件
            status = nc_close(ncid);
            handle_netcdf_error(status, "关闭文件");

            std::cout << "转换完成！输出文件: " << output_nc_file << std::endl;
            return true;

        }
        catch (const std::exception& e) {
            std::cerr << "转换过程出错: " << e.what() << std::endl;
            return false;
        }
    }
