#include <cstdio>
#include <cstring>
#include <fstream>

#include "vtr_assert.h"
#include "vtr_util.h"
#include "vtr_log.h"
#include "vtr_digest.h"

#include "vpr_types.h"
#include "vpr_error.h"

#include "globals.h"
#include "hash.h"
#include "read_place.h"
#include "read_xml_arch_file.h"

void read_place(const char* net_file,
                const char* place_file,
                bool verify_file_digests,
                const DeviceGrid& grid) {
    std::ifstream fstream(place_file);
    if (!fstream) {
        VPR_FATAL_ERROR(VPR_ERROR_PLACE_F,
                        "'%s' - Cannot open place file.\n",
                        place_file);
    }

    auto& cluster_ctx = g_vpr_ctx.clustering();
    auto& place_ctx = g_vpr_ctx.mutable_placement();

    std::string line;
    int lineno = 0;
    bool seen_netlist_id = false;
    bool seen_grid_dimensions = false;
    while (std::getline(fstream, line)) { //Parse line-by-line
        ++lineno;

        std::vector<std::string> tokens = vtr::split(line);

        if (tokens.empty()) {
            continue; //Skip blank lines

        } else if (tokens[0][0] == '#') {
            continue; //Skip commented lines

        } else if (tokens.size() == 4
                   && tokens[0] == "Netlist_File:"
                   && tokens[2] == "Netlist_ID:") {
            //Check that the netlist used to generate this placement matches the one loaded
            //
            //NOTE: this is an optional check which causes no errors if this line is missing.
            //      This ensures other tools can still generate placement files which can be loaded
            //      by VPR.

            if (seen_netlist_id) {
                vpr_throw(VPR_ERROR_PLACE_F, place_file, lineno,
                          "Duplicate Netlist_File/Netlist_ID specification");
            }

            std::string place_netlist_id = tokens[3];
            std::string place_netlist_file = tokens[1];

            if (place_netlist_id != cluster_ctx.clb_nlist.netlist_id().c_str()) {
                auto msg = vtr::string_fmt(
                    "The packed netlist file that generated placement (File: '%s' ID: '%s')"
                    " does not match current netlist (File: '%s' ID: '%s')",
                    place_netlist_file.c_str(), place_netlist_id.c_str(),
                    net_file, cluster_ctx.clb_nlist.netlist_id().c_str());
                if (verify_file_digests) {
                    vpr_throw(VPR_ERROR_PLACE_F, place_file, lineno, msg.c_str());
                } else {
                    VTR_LOGF_WARN(place_file, lineno, "%s\n", msg.c_str());
                }
            }

            seen_netlist_id = true;

        } else if (tokens.size() == 7
                   && tokens[0] == "Array"
                   && tokens[1] == "size:"
                   && tokens[3] == "x"
                   && tokens[5] == "logic"
                   && tokens[6] == "blocks") {
            //Load the device grid dimensions

            if (seen_grid_dimensions) {
                vpr_throw(VPR_ERROR_PLACE_F, place_file, lineno,
                          "Duplicate device grid dimensions specification");
            }

            size_t place_file_width = vtr::atou(tokens[2]);
            size_t place_file_height = vtr::atou(tokens[4]);
            if (grid.width() != place_file_width || grid.height() != place_file_height) {
                vpr_throw(VPR_ERROR_PLACE_F, place_file, lineno,
                          "Current FPGA size (%d x %d) is different from size when placement generated (%d x %d)",
                          grid.width(), grid.height(), place_file_width, place_file_height);
            }

            seen_grid_dimensions = true;

        } else if (tokens.size() == 4 || (tokens.size() == 5 && tokens[4][0] == '#')) {
            //Load the block location
            //
            //We should have 4 tokens of actual data, with an optional 5th (commented) token indicating VPR's
            //internal block number

            //Grid dimensions are required by this point
            if (!seen_grid_dimensions) {
                vpr_throw(VPR_ERROR_PLACE_F, place_file, lineno,
                          "Missing device grid size specification");
            }

            std::string block_name = tokens[0];
            int block_x = vtr::atoi(tokens[1]);
            int block_y = vtr::atoi(tokens[2]);
            int block_z = vtr::atoi(tokens[3]);

            ClusterBlockId blk_id = cluster_ctx.clb_nlist.find_block(block_name);

            if (place_ctx.block_locs.size() != cluster_ctx.clb_nlist.blocks().size()) {
                //Resize if needed
                place_ctx.block_locs.resize(cluster_ctx.clb_nlist.blocks().size());
            }

            //Set the location
            place_ctx.block_locs[blk_id].loc.x = block_x;
            place_ctx.block_locs[blk_id].loc.y = block_y;
            place_ctx.block_locs[blk_id].loc.z = block_z;

        } else {
            //Unrecognized
            vpr_throw(VPR_ERROR_PLACE_F, place_file, lineno,
                      "Invalid line '%s' in placement file",
                      line.c_str());
        }
    }

    place_ctx.placement_id = vtr::secure_digest_file(place_file);
}

void read_user_pad_loc(const char* pad_loc_file) {
    /* Reads in the locations of the IO pads from a file. */

    t_hash **hash_table, *h_ptr;
    int xtmp, ytmp;
    FILE* fp;
    char buf[vtr::bufsize], bname[vtr::bufsize], *ptr;

    auto& cluster_ctx = g_vpr_ctx.clustering();
    auto& device_ctx = g_vpr_ctx.device();
    auto& place_ctx = g_vpr_ctx.mutable_placement();

    VTR_LOG("\n");
    VTR_LOG("Reading locations of IO pads from '%s'.\n", pad_loc_file);
    fp = fopen(pad_loc_file, "r");
    if (!fp) VPR_FATAL_ERROR(VPR_ERROR_PLACE_F,
                             "'%s' - Cannot find IO pads location file.\n",
                             pad_loc_file);

    hash_table = alloc_hash_table();
    for (auto blk_id : cluster_ctx.clb_nlist.blocks()) {
        if (is_io_type(physical_tile_type(blk_id))) {
            insert_in_hash_table(hash_table, cluster_ctx.clb_nlist.block_name(blk_id).c_str(), size_t(blk_id));
            place_ctx.block_locs[blk_id].loc.x = OPEN; /* Mark as not seen yet. */
        }
    }

    for (size_t i = 0; i < device_ctx.grid.width(); i++) {
        for (size_t j = 0; j < device_ctx.grid.height(); j++) {
            auto type = device_ctx.grid[i][j].type;
            if (is_io_type(type)) {
                for (int k = 0; k < type->capacity; k++) {
                    if (place_ctx.grid_blocks[i][j].blocks[k] != INVALID_BLOCK_ID) {
                        place_ctx.grid_blocks[i][j].blocks[k] = EMPTY_BLOCK_ID; /* Flag for err. check */
                    }
                }
            }
        }
    }

    ptr = vtr::fgets(buf, vtr::bufsize, fp);

    while (ptr != nullptr) {
        ptr = vtr::strtok(buf, TOKENS, fp, buf);
        if (ptr == nullptr) {
            ptr = vtr::fgets(buf, vtr::bufsize, fp);
            continue; /* Skip blank or comment lines. */
        }

        if (strlen(ptr) + 1 < vtr::bufsize) {
            strcpy(bname, ptr);
        } else {
            vpr_throw(VPR_ERROR_PLACE_F, pad_loc_file, vtr::get_file_line_number_of_last_opened_file(),
                      "Block name exceeded buffer size of %zu characters", vtr::bufsize);
        }

        ptr = vtr::strtok(nullptr, TOKENS, fp, buf);
        if (ptr == nullptr) {
            vpr_throw(VPR_ERROR_PLACE_F, pad_loc_file, vtr::get_file_line_number_of_last_opened_file(),
                      "Incomplete.\n");
        }
        sscanf(ptr, "%d", &xtmp);

        ptr = vtr::strtok(nullptr, TOKENS, fp, buf);
        if (ptr == nullptr) {
            vpr_throw(VPR_ERROR_PLACE_F, pad_loc_file, vtr::get_file_line_number_of_last_opened_file(),
                      "Incomplete.\n");
        }
        sscanf(ptr, "%d", &ytmp);

        ptr = vtr::strtok(nullptr, TOKENS, fp, buf);
        if (ptr == nullptr) {
            vpr_throw(VPR_ERROR_PLACE_F, pad_loc_file, vtr::get_file_line_number_of_last_opened_file(),
                      "Incomplete.\n");
        }
        int k;
        sscanf(ptr, "%d", &k);

        ptr = vtr::strtok(nullptr, TOKENS, fp, buf);
        if (ptr != nullptr) {
            vpr_throw(VPR_ERROR_PLACE_F, pad_loc_file, vtr::get_file_line_number_of_last_opened_file(),
                      "Extra characters at end of line.\n");
        }

        h_ptr = get_hash_entry(hash_table, bname);
        if (h_ptr == nullptr) {
            VTR_LOG_WARN("[Line %d] Block %s invalid, no such IO pad.\n",
                         vtr::get_file_line_number_of_last_opened_file(), bname);
            ptr = vtr::fgets(buf, vtr::bufsize, fp);
            continue;
        }
        ClusterBlockId bnum(h_ptr->index);
        int i = xtmp;
        int j = ytmp;

        if (place_ctx.block_locs[bnum].loc.x != OPEN) {
            vpr_throw(VPR_ERROR_PLACE_F, pad_loc_file, vtr::get_file_line_number_of_last_opened_file(),
                      "Block %s is listed twice in pad file.\n", bname);
        }

        if (i < 0 || i > int(device_ctx.grid.width() - 1) || j < 0 || j > int(device_ctx.grid.height() - 1)) {
            vpr_throw(VPR_ERROR_PLACE_F, pad_loc_file, 0,
                      "Block #%zu (%s) location, (%d,%d) is out of range.\n", size_t(bnum), bname, i, j);
        }

        place_ctx.block_locs[bnum].loc.x = i; /* Will be reloaded by initial_placement anyway. */
        place_ctx.block_locs[bnum].loc.y = j; /* We need to set .x only as a done flag.         */
        place_ctx.block_locs[bnum].loc.z = k;
        place_ctx.block_locs[bnum].is_fixed = true;

        auto type = device_ctx.grid[i][j].type;
        if (!is_io_type(type)) {
            vpr_throw(VPR_ERROR_PLACE_F, pad_loc_file, 0,
                      "Attempt to place IO block %s at illegal location (%d, %d).\n", bname, i, j);
        }

        if (k >= type->capacity || k < 0) {
            vpr_throw(VPR_ERROR_PLACE_F, pad_loc_file, vtr::get_file_line_number_of_last_opened_file(),
                      "Block %s subblock number (%d) is out of range.\n", bname, k);
        }
        place_ctx.grid_blocks[i][j].blocks[k] = bnum;
        place_ctx.grid_blocks[i][j].usage++;

        ptr = vtr::fgets(buf, vtr::bufsize, fp);
    }

    for (auto blk_id : cluster_ctx.clb_nlist.blocks()) {
        auto type = physical_tile_type(blk_id);
        if (is_io_type(type) && place_ctx.block_locs[blk_id].loc.x == OPEN) {
            vpr_throw(VPR_ERROR_PLACE_F, pad_loc_file, 0,
                      "IO block %s location was not specified in the pad file.\n", cluster_ctx.clb_nlist.block_name(blk_id).c_str());
        }
    }

    fclose(fp);
    free_hash_table(hash_table);
    VTR_LOG("Successfully read %s.\n", pad_loc_file);
    VTR_LOG("\n");
}

/* Prints out the placement of the circuit. The architecture and    *
 * netlist files used to generate this placement are recorded in the *
 * file to avoid loading a placement with the wrong support files    *
 * later.                                                            */
void print_place(const char* net_file,
                 const char* net_id,
                 const char* place_file) {
    FILE* fp;

    auto& device_ctx = g_vpr_ctx.device();
    auto& cluster_ctx = g_vpr_ctx.clustering();
    auto& place_ctx = g_vpr_ctx.mutable_placement();

    fp = fopen(place_file, "w");

    fprintf(fp, "Netlist_File: %s Netlist_ID: %s\n",
            net_file,
            net_id);
    fprintf(fp, "Array size: %zu x %zu logic blocks\n\n", device_ctx.grid.width(), device_ctx.grid.height());
    fprintf(fp, "#block name\tx\ty\tsubblk\tblock number\n");
    fprintf(fp, "#----------\t--\t--\t------\t------------\n");

    if (!place_ctx.block_locs.empty()) { //Only if placement exists
        for (auto blk_id : cluster_ctx.clb_nlist.blocks()) {
            fprintf(fp, "%s\t", cluster_ctx.clb_nlist.block_name(blk_id).c_str());
            if (strlen(cluster_ctx.clb_nlist.block_name(blk_id).c_str()) < 8)
                fprintf(fp, "\t");

            fprintf(fp, "%d\t%d\t%d", place_ctx.block_locs[blk_id].loc.x, place_ctx.block_locs[blk_id].loc.y, place_ctx.block_locs[blk_id].loc.z);
            fprintf(fp, "\t#%zu\n", size_t(blk_id));
        }
    }
    fclose(fp);

    //Calculate the ID of the placement
    place_ctx.placement_id = vtr::secure_digest_file(place_file);
}
