#include <cstdarg>
#include <cstdlib>
#include <cerrno> //For errno
#include <cstring>
#include <memory>
#include <sstream>

#include "vtr_util.h"
#include "vtr_assert.h"
#include "vtr_memory.h"
#include "vtr_error.h"


namespace vtr {


std::string out_file_prefix; /* used by fopen */
static int file_line_number = 0; /* file in line number being parsed (used by fgets) */
static int cont; /* line continued? (used by strtok)*/


//Splits the string 'text' along the specified delimiter characters in 'delims'
//The split strings (excluding the delimiters) are returned
std::vector<std::string> split(const char* text, const std::string delims) {
    if(text) {
        std::string text_str(text);
        return split(text_str, delims);
    }
    return std::vector<std::string>();
}

std::vector<std::string> split(const std::string& text, const std::string delims) {
    std::vector<std::string> tokens;

    std::string curr_tok;
    for(char c : text) {
        if(delims.find(c) != std::string::npos) {
            //Delimeter character
            if(!curr_tok.empty()) {
                //At the end of the token

                //Save it
                tokens.push_back(curr_tok);

                //Reset token
                curr_tok.clear();
            } else {
                //Pass
            }
        } else {
            //Non-delimeter append to token
            curr_tok += c;
        }
    }
    
    //Add last token
    if(!curr_tok.empty()) {
        //Save it
        tokens.push_back(curr_tok);
    } 
    return tokens;
}

//Splits off the name and extension (including ".") of the specified filename
std::array<std::string,2> split_ext(const std::string& filename) {
    std::array<std::string,2> name_ext;
    auto pos = filename.find_last_of('.');

    if (pos == std::string::npos) {
        //No extension
        pos = filename.size();
    }

    name_ext[0] = std::string(filename, 0, pos);
    name_ext[1] = std::string(filename, pos, filename.size() - pos);

    return name_ext;
}

std::string replace_first(const std::string& input, const std::string& search, const std::string& replace) {
    auto pos = input.find(search);

    std::string output(input, 0, pos);
    output += replace;
    output += std::string(input, pos + search.size());

    return output;
}

std::string replace_all(const std::string& input, const std::string& search, const std::string& replace) {

    std::string output;

    size_t last = 0;
    size_t pos = input.find(search, last); //Find the first instance of 'search' starting at or after 'last'
    while(pos != std::string::npos) {
        output += input.substr(last, pos - last); //Append anything in the input string between last and current match
        output += replace; //Add the replacement

        last = pos + search.size(); //Advance past the current match

        pos = input.find(search, last); //Look for the next match
    }
    output += input.substr(last, pos - last); //Append anything in 'input' after the last match

    return output;
}

//Returns a std::string formatted using a printf-style format string
std::string string_fmt(const char* fmt, ...) {
    // Make a variable argument list
    va_list va_args;

    // Initialize variable argument list
    va_start(va_args, fmt);

    //Format string
    std::string str = vstring_fmt(fmt, va_args);

    // Reset variable argument list
    va_end(va_args);

    return str;
}

//Returns a std::string formatted using a printf-style format string taking
//an explicit va_list
std::string vstring_fmt(const char* fmt, va_list args) {
    
    // We need to copy the args so we don't change them before the true formating
    va_list va_args_copy;
    va_copy(va_args_copy, args);

    //Determine the formatted length using a copy of the args
    int len = std::vsnprintf(nullptr, 0, fmt, va_args_copy); 

    va_end(va_args_copy); //Clean-up

    //Negative if there is a problem with the format string
    VTR_ASSERT_MSG(len >= 0, "Problem decoding format string");

    size_t buf_size = len + 1; //For terminator

    //Allocate a buffer
    //  unique_ptr will free buffer automatically
    std::unique_ptr<char[]> buf(new char[buf_size]);

    //Format into the buffer using the original args
    len = std::vsnprintf(buf.get(), buf_size, fmt, args);

    VTR_ASSERT_MSG(len >= 0, "Problem decoding format string");
    VTR_ASSERT(static_cast<size_t>(len) == buf_size - 1);

    //Build the string from the buffer
    return std::string(buf.get(), len);
}

std::string basename(const std::string& path) {
    auto elements = split(path, "/");

    std::string str;
    if(elements.size() > 0) {
        //Return the last path element
        str = elements[elements.size() - 1];
    }

    return str;
}

std::string dirname(const std::string& path) {
    auto elements = split(path, "/");

    std::string str;
    if(elements.size() > 0) {
        //We need to start the dirname with a "/" if path started with one
        if(path[0] == '/') {
            str += "/";
        }
            
        //Join all except the last path element
        str += join(elements.begin(), elements.end() - 1, "/");

        //We append a final "/" to allow clients to just append directly to the
        //returned value
        str += "/";
    }

    return str;
}

/* An alternate for strncpy since strncpy doesn't work as most
 * people would expect. This ensures null termination */
char* strncpy(char *dest, const char *src, size_t size) {
    /* Find string's length */
    size_t len = std::strlen(src);

    /* Cap length at (num - 1) to leave room for \0 */
    if (size <= len)
        len = (size - 1);

    /* Copy as much of string as we can fit */
    std::memcpy(dest, src, len);

    /* explicit null termination */
    dest[len] = '\0';

    return dest;
}

char* strdup(const char *str) {
    
    if (str == nullptr ) {
        return nullptr ;
    }

    size_t Len = std::strlen(str);
    //use calloc to already make the last char '\0'
    return (char *)std::memcpy(vtr::calloc(Len+1, sizeof(char)), str, Len);;
}

template<class T>
T atoT(const std::string& value, const std::string& type_name) {
    //The c version of atof doesn't catch errors.
    //
    //This version uses stringstream to detect conversion errors
    std::istringstream ss(value);

    T val;
    ss >> val;

    if(ss.fail() || !ss.eof()) {
        //Failed to convert, or did not consume all input
        std::stringstream msg;
        msg << "Failed to convert string '" << value << "' to " << type_name;
        throw VtrError(msg.str(), __FILE__, __LINE__);
    }

    return val;
}

int atoi(const std::string& value) {
    return atoT<int>(value, "int");
}

double atod(const std::string& value) {
    return atoT<double>(value, "double");
}

float atof(const std::string& value) {
    return atoT<float>(value, "float");
}

unsigned atou(const std::string& value) {
    return atoT<unsigned>(value, "unsigned int");
}

char* strtok(char *ptr, const char *tokens, FILE * fp, char *buf) {

    /* Get next token, and wrap to next line if \ at end of line.    *
     * There is a bit of a "gotcha" in strtok.  It does not make a   *
     * copy of the character array which you pass by pointer on the  *
     * first call.  Thus, you must make sure this array exists for   *
     * as long as you are using strtok to parse that line.  Don't    *
     * use local buffers in a bunch of subroutines calling each      *
     * other; the local buffer may be overwritten when the stack is  *
     * restored after return from the subroutine.                    */

    char *val;

    val = std::strtok(ptr, tokens);
    for (;;) {
        if (val != nullptr || cont == 0)
            return (val);

        /* return unless we have a null value and a continuation line */
        if (vtr::fgets(buf, bufsize, fp) == nullptr )
            return (nullptr );

        val = std::strtok(buf, tokens);
    }
}

FILE* fopen(const char *fname, const char *flag) {
    FILE *fp;
    size_t Len;
    char *new_fname = nullptr;
    file_line_number = 0;

    /* Appends a prefix string for output files */
    if (!out_file_prefix.empty()) {
        if (std::strchr(flag, 'w')) {
            Len = 1; /* NULL char */
            Len += std::strlen(out_file_prefix.c_str());
            Len += std::strlen(fname);
            new_fname = (char *) vtr::malloc(Len * sizeof(char));
            strcpy(new_fname, out_file_prefix.c_str());
            strcat(new_fname, fname);
            fname = new_fname;
        }
    }

    if (nullptr == (fp = std::fopen(fname, flag))) {
        throw VtrError(string_fmt("Error opening file %s for %s access: %s.\n", fname, flag, strerror(errno)), __FILE__, __LINE__);        
    }

    if (new_fname)
        std::free(new_fname);

    return (fp);
}

int fclose(FILE* f) {
    return std::fclose(f);
}

char* fgets(char *buf, int max_size, FILE * fp) {
    /* Get an input line, update the line number and cut off *
     * any comment part.  A \ at the end of a line with no   *
     * comment part (#) means continue. vtr::fgets should give * 
     * identical results for Windows (\r\n) and Linux (\n)   *
     * newlines, since it replaces each carriage return \r   *
     * by a newline character \n.  Returns NULL after EOF.     */

    int ch;
    int i;

    cont = 0; /* line continued? */
    file_line_number++; /* global variable */

    for (i = 0; i < max_size - 1; i++) { /* Keep going until the line finishes or the buffer is full */

        ch = std::fgetc(fp);

        if (std::feof(fp)) { /* end of file */
            if (i == 0) {
                return nullptr ; /* required so we can write while (vtr::fgets(...) != NULL) */
            } else { /* no newline before end of file - last line must be returned */
                buf[i] = '\0';
                return buf;
            }
        }

        if (ch == '#') { /* comment */
            buf[i] = '\0';
            while ((ch = std::fgetc(fp)) != '\n' && !std::feof(fp))
                ; /* skip the rest of the line */
            return buf;
        }

        if (ch == '\r' || ch == '\n') { /* newline (cross-platform) */
            if (i != 0 && buf[i - 1] == '\\') { /* if \ at end of line, line continued */
                cont = 1;
                buf[i - 1] = '\n'; /* May need this for tokens */
                buf[i] = '\0';
            } else {
                buf[i] = '\n';
                buf[i + 1] = '\0';
            }
            return buf;
        }

        buf[i] = ch; /* copy character into the buffer */

    }

    /* Buffer is full but line has not terminated, so error */
    throw VtrError(string_fmt("Error on line %d -- line is too long for input buffer.\n"
                              "All lines must be at most %d characters long.\n", bufsize - 2),
                    __FILE__, __LINE__);
    return nullptr;
}

/*
 * Returns line number of last opened and read file
 */
int get_file_line_number_of_last_opened_file() {
    return file_line_number;
}


bool file_exists(const char* filename) {
    FILE * file;

    if (filename == nullptr ) {
        return false;
    }

    file = std::fopen(filename, "r");
    if (file) {
        std::fclose(file);
        return true;
    }
    return false;
}

/* Date:July 17th, 2013                                
 * Author: Daniel Chen                                
 * Purpose: Checks the file extension of an file to ensure 
 *            correct file format. Returns true if format is 
 *            correct, and false otherwise.
 * Note:    This is probably a fragile check, but at least 
 *            should prevent common problems such as swapping
 *            architecture file and blif file on the VPR 
 *            command line. 
 */

bool check_file_name_extension(const char* file_name, 
                               const char* file_extension){
    const char* str;
    int len_extension;

    len_extension = std::strlen(file_extension);
    str = std::strstr(file_name, file_extension);
    if(str == nullptr || (*(str + len_extension) != '\0')){
        return false;
    }

    return true;
}

std::vector<std::string> ReadLineTokens(FILE * InFile, int *LineNum) {
    std::unique_ptr<char[]> buf(new char[vtr::bufsize]);

    const char* line = vtr::fgets(buf.get(), vtr::bufsize, InFile);

    ++(*LineNum);

    return vtr::split(line);
}

} //namespace
