#include "ChipConfig.hpp"
#include "Chip.hpp"
#include "BitDatabase.hpp"
#include "Database.hpp"
#include "Tile.hpp"
#include <sstream>
#include <iostream>

namespace Trellis {

string ChipConfig::to_string() const
{
    stringstream ss;
    ss << ".device " << chip_name << endl << endl;
    for (const auto &meta : metadata)
        ss << ".comment " << meta << endl;
    for (const auto &sc : sysconfig)
        ss << ".sysconfig " << sc.first << " " << sc.second << endl;
    ss << endl;
    for (const auto &tile : tiles) {
        if (!tile.second.empty()) {
            ss << ".tile " << tile.first << endl;
            ss << tile.second;
            ss << endl;
        }
    }
    for (const auto &bram : bram_data) {
        ss << ".bram_init " << bram.first << endl;
        ios_base::fmtflags f( ss.flags() );
        for (size_t i = 0; i < bram.second.size(); i++) {
            ss << setw(3) << setfill('0') << hex << bram.second.at(i);
            if (i % 8 == 7)
                ss << endl;
            else
                ss << " ";
        }
        ss.flags(f);
        ss << endl;
    }
    for (const auto &tg : tilegroups) {
        ss << ".tile_group";
        for (const auto &tile : tg.tiles) {
            ss << " " << tile;
        }
        ss << endl;
        ss << tg.config;
        ss << endl;
    }
    return ss.str();
}

ChipConfig ChipConfig::from_string(const string &config)
{
    stringstream ss(config);
    ChipConfig cc;
    while (!skip_check_eof(ss)) {
        std::string verb;
        ss >> verb;
        if (verb == ".device") {
            ss >> cc.chip_name;
        } else if (verb == ".comment") {
            std::string line;
            ss.get(); //skip space
            getline(ss, line);
            cc.metadata.push_back(line);
        } else if (verb == ".tile") {
            std::string tilename;
            ss >> tilename;
            TileConfig tc;
            ss >> tc;
            cc.tiles[tilename] = tc;
        } else if (verb == ".sysconfig") {
            std::string key, value;
            ss >> key >> value;
            cc.sysconfig[key] = value;
        } else if (verb == ".bram_init") {
            uint16_t bram;
            ss >> bram;
            ios_base::fmtflags f(ss.flags());
            while (!skip_check_eor(ss)) {
                uint16_t value;
                ss >> hex >> value;
                cc.bram_data[bram].push_back(value);
            }
            ss.flags(f);
        } else if (verb == ".tile_group") {
            TileGroup tg;
            std::string line;
            getline(ss, line);
            std::stringstream ss2(line);

            std::string tile;
            while (ss2) {
                ss2 >> tile;
                tg.tiles.push_back(tile);
            }
            ss >> tg.config;
            cc.tilegroups.push_back(tg);
        } else {
            throw runtime_error("unrecognised config entry " + verb);
        }
    }
    return cc;
}

Chip ChipConfig::to_chip() const
{
    Chip c(chip_name);
    c.metadata = metadata;
    c.bram_data = bram_data;
    set<string> processed_tiles;
    for (auto tile_entry : c.tiles) {
        auto tile_db = get_tile_bitdata(TileLocator{c.info.family, c.info.name, tile_entry.second->info.type});
        if (tiles.find(tile_entry.first) != tiles.end()) {
            tile_db->config_to_tile_cram(tiles.at(tile_entry.first), tile_entry.second->cram);
        } else {
            // Empty config sets default values (not always zero, e.g. in IO tiles)
            tile_db->config_to_tile_cram(TileConfig(), tile_entry.second->cram);
        }
        processed_tiles.insert(tile_entry.first);
    }

    for (const auto &tilegroup : tilegroups) {
        set<string> matched;
        for (const auto &tilename : tilegroup.tiles) {
            auto tile = c.tiles.at(tilename);
            auto tile_db = get_tile_bitdata(TileLocator{c.info.family, c.info.name, tile->info.type});
            tile_db->config_to_tile_cram(tilegroup.config, tile->cram, true, &matched);
        }
        for (const auto &word : tilegroup.config.cwords)
            if (!matched.count(word.name))
                throw runtime_error("config word " + word.name + " matched in no tilegroup tiles");
        for (const auto &cenum : tilegroup.config.cenums)
            if (!matched.count(cenum.name))
                throw runtime_error("config enum " + cenum.name + " matched in no tilegroup tiles");
    }

    for (auto &tile : tiles) {
        if (!processed_tiles.count(tile.first)) {
            throw runtime_error("tile " + tile.first + " does not exist in chip " + chip_name);
        }
    }
    return c;
}

ChipConfig ChipConfig::from_chip(const Chip &chip)
{
    ChipConfig cc;
    cc.chip_name = chip.info.name;
    cc.metadata = chip.metadata;
    cc.bram_data = chip.bram_data;
    for (auto tile : chip.tiles) {
        auto tile_db = get_tile_bitdata(TileLocator{chip.info.family, chip.info.name, tile.second->info.type});
        cc.tiles[tile.first] = tile_db->tile_cram_to_config(tile.second->cram);
    }
    return cc;
}

}
