/********************************************************
 *  ██████╗  ██████╗████████╗██╗
 * ██╔════╝ ██╔════╝╚══██╔══╝██║
 * ██║  ███╗██║        ██║   ██║
 * ██║   ██║██║        ██║   ██║
 * ╚██████╔╝╚██████╗   ██║   ███████╗
 *  ╚═════╝  ╚═════╝   ╚═╝   ╚══════╝
 * Geophysical Computational Tools & Library (GCTL)
 *
 * Copyright (c) 2023  Yi Zhang (yizhang-geo@zju.edu.cn)
 *
 * GCTL is distributed under a dual licensing scheme. You can redistribute 
 * it and/or modify it under the terms of the GNU Lesser General Public 
 * License as published by the Free Software Foundation, either version 2 
 * of the License, or (at your option) any later version. You should have 
 * received a copy of the GNU Lesser General Public License along with this 
 * program. If not, see <http://www.gnu.org/licenses/>.
 * 
 * If the terms and conditions of the LGPL v.2. would prevent you from using 
 * the GCTL, please consider the option to obtain a commercial license for a 
 * fee. These licenses are offered by the GCTL's original author. As a rule, 
 * licenses are provided "as-is", unlimited in time for a one time fee. Please 
 * send corresponding requests to: yizhang-geo@zju.edu.cn. Please do not forget 
 * to include some description of your company and the realm of its activities. 
 * Also add information on how to contact you by electronic and paper mail.
 ******************************************************/

#ifndef GCTL_GRIDMANAGER_POTENTIAL_H
#define GCTL_GRIDMANAGER_POTENTIAL_H

#include "../../lib/potential/gm_regular_grid.h"

using namespace gctl;

// Function pointer for commands
typedef void (*cmd_func_ptr)(const std::vector<std::string> &cmd_units);

struct cmd_pair
{
    std::string name;
    cmd_func_ptr func_p;
    std::string brief;
};

void quit(const std::vector<std::string> &cmd_units);
void mesh_info(const std::vector<std::string> &cmd_units);
void new_grid(const std::vector<std::string> &cmd_units);
void data_cloud(const std::vector<std::string> &cmd_units);
void gradient(const std::vector<std::string> &cmd_units);
void wavelet(const std::vector<std::string> &cmd_units);
void sum_data(const std::vector<std::string> &cmd_units);
void diff_data(const std::vector<std::string> &cmd_units);
void bool_data(const std::vector<std::string> &cmd_units);
void func_data(const std::vector<std::string> &cmd_units);
void calculator(const std::vector<std::string> &cmd_units);
void data_output(const std::vector<std::string> &cmd_units);
void data_rename(const std::vector<std::string> &cmd_units);
void data_view(const std::vector<std::string> &cmd_units);
void data_plot(const std::vector<std::string> &cmd_units);
void get_stats(const std::vector<std::string> &cmd_units);
void get_profile(const std::vector<std::string> &cmd_units);

void open_grid(const std::vector<std::string> &cmd_units);
void save_grid(const std::vector<std::string> &cmd_units);
void open_binary(const std::vector<std::string> &cmd_units);
void save_binary(const std::vector<std::string> &cmd_units);
void open_netcdf(const std::vector<std::string> &cmd_units);
void save_netcdf(const std::vector<std::string> &cmd_units);
void save_gmsh(const std::vector<std::string> &cmd_units);
void open_surfer(const std::vector<std::string> &cmd_units);
void save_surfer(const std::vector<std::string> &cmd_units);
void save_text(const std::vector<std::string> &cmd_units);

void potential_gradient(const std::vector<std::string> &cmd_units);
void rtp(const std::vector<std::string> &cmd_units);
void drtp(const std::vector<std::string> &cmd_units);
void continuation(const std::vector<std::string> &cmd_units);
void trend(const std::vector<std::string> &cmd_units);

#define CMD_NUM 25
const cmd_pair commands[CMD_NUM] = {
    {"info", mesh_info, "Show mesh's information."},
    {"init", new_grid, "Initialize a new grid framework."},
    {"open", open_grid, "Open a grid file."},
    {"save", save_grid, "Save grid data to a file."},
    {"cloud", data_cloud, "Import grid data from data cloud."},
    {"gradient", gradient, "Calculate directional gradients."},
    {"wavelet", wavelet, "Decompose grid data using the wavelet algorithm."},
    {"sum", sum_data, "Calculate the sum of two grid data."},
    {"diff", diff_data, "Calculate the difference of two grid data."},
    {"bool", bool_data, "Preform the boolean operation of grid data."},
    {"function", func_data, "Generate grid data from a mathematic expression."},
    {"calculator", calculator, "Preform the mathematic operation of grid data."},
    {"output", data_output, "Set output properites of grid data."},
    {"rename", data_rename, "Rename a grid data."},
    {"view", data_view, "Display a grid data using the exprtk library."},
    {"plot", data_plot, "Plot a grid data using the GMT library."},
    {"statistic", get_stats, "Show statistics of grid data."},
    {"profile", get_profile, "Extract profile data of a grid data."},
    {"gravgradient", potential_gradient, "Calculate gravitational gradients."},
    {"rtp", rtp, "Preform the Reduce to Pole (RTP) process."},
    {"drtp", drtp, "Preform the Differential Reduce to Pole (DRTP) process"},
    {"continuation", continuation, "Preform the upward or downward continuation process."},
    {"trend", trend, "Preform the separation process for the potential field data."},
    {"quit", quit, "Quit the program."},
    {"null", nullptr, "null"}
};

#define KEY_NUM 6
const cmd_pair keywords[KEY_NUM] = {
    {"netcdf", nullptr, "netCDF format."},
    {"surfer", nullptr, "Surfer format."},
    {"binary", nullptr, "GCTL native format."},
    {"gmsh", nullptr, "Gmsh format."},
    {"node", nullptr, "Node registered data."},
    {"cell", nullptr, "Cell registered data."}
};

#endif // GCTL_GRIDMANAGER_POTENTIAL_H