/*=============================================================================
 |
 |       Author:  William Kozma Jr
 |                wkozma@ntia.gov
 |                US Dept of Commerce, NTIA/ITS
 |                June 2021 : Geneva Study Group 3 Meetings
 |
 *===========================================================================*/

#include <ctime>
#include <iostream>
#include <fstream>
#include <string.h>
#include <Windows.h>
#include <string>
#include <algorithm>
#include <vector>

using namespace std;

//
// CONSTANTS
///////////////////////////////////////////////

#define     MODE_POINT                              0
#define     MODE_LINE                               1
#define     TIME_SIZE                               26

//
// GENERAL ERRORS AND RETURN VALUES
///////////////////////////////////////////////

#define     NOT_SET                                 -1
#define     ERROR                                   -1
#define     SUCCESS                                 0
#define     DRVR__RETURN_SUCCESS                    1000

#define     DRVRERR__DLL_LOADING                    1001
#define     DRVRERR__MAJOR_VERSION_MISMATCH         1002
#define     DRVRERR__INVALID_OPTION                 1003
#define     DRVRERR__PARSE_MODE_VALUE               1004
#define     DRVRERR__GET_LFMF_FUNC_LOADING          1005
// Input File Parsing Errors (1100-1199)
#define     DRVRERR__PARSE_HTX                      1101
#define     DRVRERR__PARSE_HRX                      1102
#define     DRVRERR__PARSE_PTX                      1103
#define     DRVRERR__PARSE_NS                       1104
#define     DRVRERR__PARSE_FREQ                     1105
#define     DRVRERR__PARSE_POL                      1106
#define     DRVRERR__PARSE_EPSILON                  1107
#define     DRVRERR__PARSE_SIGMA                    1108
#define     DRVRERR__PARSE_DKM                      1109
// Validation Errors (1200-1299)
#define     DRVRERR__VALIDATION_MODE                1201
#define     DRVRERR__VALIDATION_IN_FILE             1202
#define     DRVRERR__VALIDATION_OUT_FILE            1203
#define     DRVRERR__VALIDATION_HTX                 1204
#define     DRVRERR__VALIDATION_HRX                 1205
#define     DRVRERR__VALIDATION_PTX                 1206
#define     DRVRERR__VALIDATION_NS                  1207
#define     DRVRERR__VALIDATION_FMHZ                1208
#define     DRVRERR__VALIDATION_POL                 1209
#define     DRVRERR__VALIDATION_EPSILON             1210
#define     DRVRERR__VALIDATION_SIGMA               1211
#define     DRVRERR__VALIDATION_DKM                 1212

//
// DATA STRUCTURES
///////////////////////////////////////////////

struct DrvrParams {
    char in_file[256]   = { 0 };    // Input file
    char out_file[256]  = { 0 };    // Output file

    int mode            = NOT_SET;  // Mode (POINT, LINE)
    bool method         = false;    // 
};

struct LFMFParams {
    double h_tx__meter  = NOT_SET;
    double h_rx__meter  = NOT_SET;
    double d__km        = NOT_SET;
    double N_s          = NOT_SET;
    double f__mhz       = NOT_SET;
    int pol             = NOT_SET;
    double epsilon      = NOT_SET;
    double sigma        = NOT_SET;
    double P_tx__watt   = NOT_SET;
};

//
// FUNCTIONS
///////////////////////////////////////////////

int ParseArguments(int argc, char** argv, DrvrParams* params);
void Lowercase(char* argv);
bool Match(const char* opt, char* arg);
void Help();
void Version();
int ParseErrorMsgHelper(const char* opt, int err);
int ValidateDriverInputs(DrvrParams* params);
int ValidateModelInputs(LFMFParams* lfmf_params, int mode);
int LoadDLL();
int Validate_RequiredErrMsgHelper(const char* opt, int err);
void GetDLLVersionInfo();
void GetDrvrVersionInfo();
int ParseInputFile(const char* in_file, LFMFParams* lfmf_params);
int ParseDouble(const string& str, double* value);
int ParseInteger(const string& str, int* value);
int ParsingErrorHelper(int err, const char* msg);
void PrintPolarizationLabel(FILE* fp, int pol);
void PrintErrorMsgLabel(FILE* fp, int err);
void PrintLabel(FILE* fp, const char* lbl);
void PrintMethodLabel(FILE* fp, int method);