// stdafx.h is a header that almost every class in the project will include
//
#pragma once
#include <limits>
#include <vector>
#include <fstream>
#include <iostream>
#include <string>
#include <stdlib.h>
#include <ctype.h>
#include <math.h>
#include <stdio.h>
#include "time.h"
#include "Filename.h"
//#ifdef WIN32
#include "chdir.h"
//#else
//#include "errno.h"
//#endif
using namespace std;

// unmark the line for DEBUG
// #define DEBUG true

// Change the log level to see different level of information.
#define LOG_LEVEL 3
#define ERROR_LOG 5
#define WARNING_LOG 4
#define INFO_LOG 3
#define CONFIG_LOG 2
#define FINE_LOG 1

#ifdef _WIN32
#ifndef WIN32
#define WIN32 _WIN32
#endif
#endif

#ifdef _WIN32
#define _CRT_SECURE_NO_WARNINGS true
#endif

#ifdef LOG_LEVEL
#ifdef WIN32
#define LOG_INFO printf
#else
#ifdef _WIN64
#define LOG_INFO printf
#else
#define LOG_INFO(format, level, args...) {\
    if(level >= LOG_LEVEL) {\
        if(level >= LOG_LEVEL) {\
            if (level >= WARNING_LOG) {\
                    fprintf(stderr, "%s, %d (%s)", __FILE__, __LINE__, __FUNCTION__);\
                    fprintf(stderr, format, level, ##args);\
                    fflush(stderr);\
            } else {\
                fprintf(stdout, format, level, ##args);\
                fflush(stdout);\
            }\
        }\
    }\
}
#endif
#endif
#endif

#ifndef BLANK_LINE
#define BLANK_LINE "                                         "
#endif

#define ERR printf("ERR --- %s:%d\n", __FILE__, __LINE__);

#define TIME_INFORMATION(a) {\
        time_t startt, endt;\
        time(&startt);\
        a;\
        time(&endt);\
        printf("%u seconds consumed.%s\r", (unsigned int)(endt - startt), BLANK_LINE);\
        fflush(stdout);\
    }

#define TIME_INFO(a, msg) {\
        time_t startt, endt;\
        time(&startt);\
        a;\
        time(&endt);\
        printf("%s in %u seconds.%s\r", msg, (unsigned int)(endt - startt), BLANK_LINE);\
        fflush(stdout);\
    }

#define ASSERT_TRUE(expression, message)\
    do {\
        if (!(expression))\
        { \
            printf("ERROR: %s.  Press ENTER to continue", message);\
            fflush(stdout);\
            char crap[256];\
            cin.getline(crap, 256);\
        }\
    } while(0)

#define ASSERT_EQUAL(expectation, real_value, message)\
    do {\
        if (expectation != real_value)\
        { \
			cout << '\n' << expectation << " is not equal to " << real_value << << endl;\
            printf("ERROR: %s.  Press ENTER to continue", message);\
            fflush(stdout);\
            char crap[256];\
            cin.getline(crap, 256);\
        }\
    } while(0)

#ifndef WIN32
#define MEMORY_INFO(b)\
    do {\
        FILE *xfp = fopen("/proc/self/statm", "r");\
        unsigned int l1, l2, l3, l4, l5, l6, l7;\
        int PageSize = getpagesize();\
        if(xfp == NULL) {\
            LOG_INFO("Info %d: We cannot open /proc/self/statm file (%d:%s)\n", CONFIG_LOG\
                      errno, strerror(errno));\
        } else{\
            fscanf(xfp, "%u %u %u %u %u %u %u", &l1, &l2, &l3, &l4, &l5, &l6, &l7);\
            printf("%s: %u MB memory (%u MB in stack) consumed.\n",\
                   (b), /*(unsigned int)(end - start),*/ \
                   (unsigned int)(l2*PageSize/1024/1024), (unsigned int)(l6*PageSize/1024/1024));\
        }\
        fclose(xfp);\
    } while(0)
#endif

#define STRIKE_KEY2CONTINUE\
    do {\
        cout << "Strike a key to continue" << endl;\
        char c;\
        if(scanf("%c", &c) == 0) {\
            break;\
        }\
    } while(0)

inline bool myFwrite(const void* a, size_t b, size_t c, FILE* fp)
{
    size_t stWriteByte = fwrite(a, b, c, fp);
    if (stWriteByte != c) {
        return (false);
    } else {
        return (true);
    }
}

inline bool myFread(void* a, size_t b, size_t c, FILE* fp)
{
    size_t stReadByte = fread(a, b, c, fp);
    if (stReadByte != c) {
        return (false);
    } else {
        return (true);
    }
}

inline bool assertFile(FILE* fp, const char* expCheckSum)
{
    char CheckSum[FILENAME_MAX];
    if (fscanf(fp, "\n%s\n", CheckSum) <= 0) {
        ERR;
        return(false);
    }
    if (strcmp(CheckSum, expCheckSum) != 0) {
        ERR;
        return(false);
    }
    return(true);
}

inline char* myStrCpy(char* caBuf, const char* str, int iBufSize)
{
    if (caBuf == NULL) {
        ERR;
        return(NULL);
    }
    int iBufSizeMinus1 = iBufSize - 1;
    char* returnV = strncpy(caBuf, str, iBufSizeMinus1);
    if (iBufSizeMinus1 >= 0) {
        caBuf[iBufSizeMinus1] = '\0';
    } else {
        caBuf[0] = '\0';
    }
    return(returnV);
}
const int MAX_LINE = 2048;
const unsigned int MAXTOLERATSUBMIS = 20;
const unsigned int MIN_READ_LENGTH = 13;
const unsigned int MAX_READ_LENGTH = 64;
const unsigned int MAX_LONG_READ_LENGTH = 128;
