#include "BitDatabase.hpp"
#include "CRAM.hpp"
#include "TileConfig.hpp"

#include <algorithm>
#include <fstream>
#include <boost/thread/shared_lock_guard.hpp>
#include <boost/thread/lock_guard.hpp>
#include <boost/range/algorithm/copy.hpp>
#include <boost/range/adaptors.hpp>


namespace Trellis {

ConfigBit cbit_from_str(const string &s) {
    size_t idx = 0;
    ConfigBit b;
    if (s[idx] == '!') {
        b.inv = true;
        ++idx;
    } else {
        b.inv = false;
    }
    assert(s[idx] == 'F');
    ++idx;
    size_t b_pos = s.find('B');
    assert(b_pos != string::npos);
    b.frame = stoi(s.substr(idx, b_pos - idx));
    b.bit = stoi(s.substr(b_pos + 1));
    return b;
}

BitGroup::BitGroup() {}

BitGroup::BitGroup(const CRAMDelta &delta) {
    for (const auto &bit: delta) {
        if (bit.delta != 0)
            bits.push_back(ConfigBit{bit.frame, bit.bit, (bit.delta < 0)});
    }
}


bool BitGroup::match(const CRAMView &tile) const {
    return all_of(bits.begin(), bits.end(), [tile](const ConfigBit &b) {
        return tile.bit(b.frame, b.bit) != b.inv;
    });
}

void BitGroup::set_group(CRAMView &tile) const {
    for (auto bit : bits)
        tile.bit(bit.frame, bit.bit) = !bit.inv;
}

void BitGroup::clear_group(Trellis::CRAMView &tile) const {
    for (auto bit : bits)
        tile.bit(bit.frame, bit.bit) = bit.inv;
}

void BitGroup::add_coverage(Trellis::BitSet &known_bits, bool value) const {
    for (const auto &b : bits) {
        if (b.inv != value)
            known_bits.insert(ConfigBit{b.frame, b.bit});
    }
}

ostream &operator<<(ostream &out, const BitGroup &bits) {
    bool first = true;
    for (auto bit : bits.bits) {
        if (!first)
            out << " ";
        out << to_string(bit);
        first = false;
    }
    return out;
}

istream &operator>>(istream &in, BitGroup &bits) {
    bits.bits.clear();
    while (!skip_check_eol(in)) {
        string s;
        in >> s;
        bits.bits.push_back(cbit_from_str(s));
    }
    return in;
}

boost::optional<string> MuxBits::get_driver(const CRAMView &tile, boost::optional<BitSet &> coverage) const {
    auto drv = find_if(arcs.begin(), arcs.end(), [tile](const ArcData &a) {
        return a.bits.match(tile);
    });
    if (drv == arcs.end()) {
        return boost::optional<string>();
    } else {
        if (coverage)
            drv->bits.add_coverage(*coverage);
        return boost::optional<string>(drv->source);
    }
}

void MuxBits::set_driver(Trellis::CRAMView &tile, const string &driver) const {
    auto drv = find_if(arcs.begin(), arcs.end(), [driver](const ArcData &a) {
        return a.source == driver;
    });
    if (drv == arcs.end()) {
        throw runtime_error("sink " + sink + " has no driver named " + driver);
    }
    drv->bits.set_group(tile);
}

ostream &operator<<(ostream &out, const MuxBits &mux) {
    out << ".mux " << mux.sink << endl;
    for (const auto &arc : mux.arcs) {
        out << arc.source << " " << arc.bits << endl;
    }
    return out;
}

istream &operator>>(istream &in, MuxBits &mux) {
    in >> mux.sink;
    mux.arcs.clear();
    // Read arc source-bits pairs until end of record
    while (!skip_check_eor(in)) {
        ArcData a;
        a.sink = mux.sink;
        in >> a.source >> a.bits;
        mux.arcs.push_back(a);
    }
    return in;
}

boost::optional<vector<bool>>
WordSettingBits::get_value(const CRAMView &tile, boost::optional<BitSet &> coverage) const {
    vector<bool> val;
    transform(bits.begin(), bits.end(), back_inserter(val), [tile, coverage](const BitGroup &b) {
        bool m = b.match(tile);
        if (coverage)
            b.add_coverage(*coverage, m);
        return m;
    });
    if (val == defval)
        return boost::optional<vector<bool>>();
    else
        return boost::optional<vector<bool>>(val);
}

void WordSettingBits::set_value(Trellis::CRAMView &tile, const vector<bool> &value) const {
    assert(value.size() == bits.size());
    for (size_t i = 0; i < bits.size(); i++) {
        if (value.at(i))
            bits.at(i).set_group(tile);
        else
            bits.at(i).clear_group(tile);
    }
}

ostream &operator<<(ostream &out, const WordSettingBits &ws) {
    out << ".config " << ws.name << " " << to_string(ws.defval) << endl;
    for (const auto &bit : ws.bits) {
        out << bit << endl;
    }
    return out;
}

istream &operator>>(istream &in, WordSettingBits &ws) {
    in >> ws.name;
    bool have_default = false;
    if (!skip_check_eol(in)) {
        in >> ws.defval;
        have_default = true;
    }
    ws.bits.clear();
    while (!skip_check_eor(in)) {
        BitGroup bg;
        in >> bg;
        ws.bits.push_back(bg);
    }
    if (!have_default) {
        ws.defval.clear();
        ws.defval.resize(ws.bits.size(), false);
    }
    return in;
}

void EnumSettingBits::set_defval(string val) {
    defval = val;
}


string EnumSettingBits::get_defval() const {
    if (defval)
        return *defval;
    else
        return "";
}


boost::optional<string> EnumSettingBits::get_value(const CRAMView &tile, boost::optional<BitSet &> coverage) const {
    auto found = find_if(options.begin(), options.end(), [tile](const pair<string, BitGroup> &kv) {
        return kv.second.match(tile);
    });
    if (found == options.end()) {
        return boost::optional<string>();
    } else {
        if (coverage)
            found->second.add_coverage(*coverage);
        if (defval && *defval == found->first) {
            return boost::optional<string>();
        } else {
            return boost::optional<string>(found->first);
        }
    }
}

void EnumSettingBits::set_value(Trellis::CRAMView &tile, const string &value) const {
    auto grp = options.at(value);
    grp.set_group(tile);
}

ostream &operator<<(ostream &out, const EnumSettingBits &es) {
    out << ".config_enum " << es.name;
    if (es.defval)
        out << " " << *(es.defval);
    out << endl;
    for (const auto &opt : es.options) {
        out << opt.first << " " << opt.second << endl;
    }
    return out;
}

istream &operator>>(istream &in, EnumSettingBits &es) {
    in >> es.name;
    if (!skip_check_eol(in)) {
        string s;
        in >> s;
        es.defval = boost::make_optional(s);
    } else {
        es.defval = boost::optional<string>();
    }
    es.options.clear();
    while (!skip_check_eor(in)) {
        string opt;
        BitGroup bg;
        in >> opt >> bg;
        es.options[opt] = bg;
    }
    return in;
}

ostream &operator<<(ostream &out, const FixedConnection &es) {
    out << ".fixed_conn " << es.sink << " " << es.source << endl;
    return out;
}

istream &operator>>(istream &in, FixedConnection &es) {
    in >> es.sink >> es.source;
    return in;
}


TileBitDatabase::TileBitDatabase(const string &filename) : filename(filename) {
#ifdef FUZZ_SAFETY_CHECK
    ip_db_lock = boost::interprocess::file_lock(filename.c_str());
    bool lck = ip_db_lock.try_lock();
    if (!lck)
        throw runtime_error("database file " + filename + " is locked");
#endif
    load();
}

void TileBitDatabase::config_to_tile_cram(const TileConfig &cfg, CRAMView &tile) const {
    boost::shared_lock_guard<boost::shared_mutex> guard(db_mutex);
    for (auto arc : cfg.carcs)
        muxes.at(arc.sink).set_driver(tile, arc.source);
    set<string> found_words, found_enums;
    for (auto cw : cfg.cwords) {
        words.at(cw.name).set_value(tile, cw.value);
        found_words.insert(cw.name);
    }
    for (auto ce : cfg.cenums) {
        enums.at(ce.name).set_value(tile, ce.value);
        found_enums.insert(ce.name);
    }
    for (auto unk : cfg.cunknowns) {
        tile.bit(unk.frame, unk.bit) = 1;
    }
    // Apply default values if not overriden in cfg
    for (auto w : words)
        if (found_words.find(w.first) == found_words.end())
            w.second.set_value(tile, w.second.defval);
    for (auto e : enums)
        if (found_enums.find(e.first) == found_enums.end())
            if (e.second.defval)
                e.second.set_value(tile, *e.second.defval);
}

TileConfig TileBitDatabase::tile_cram_to_config(const CRAMView &tile) const {
    boost::shared_lock_guard<boost::shared_mutex> guard(db_mutex);
    TileConfig cfg;
    BitSet coverage;
    for (auto mux : muxes) {
        auto sink = mux.second.get_driver(tile, coverage);
        if (sink)
            cfg.carcs.push_back(ConfigArc{mux.first, *sink});
    }
    for (auto cw : words) {
        auto val = cw.second.get_value(tile, coverage);
        if (val)
            cfg.cwords.push_back(ConfigWord{cw.first, *val});
    }
    for (auto ce : enums) {
        auto val = ce.second.get_value(tile, coverage);
        if (val)
            cfg.cenums.push_back(ConfigEnum{ce.first, *val});
    }
    for (int f = 0; f < tile.frames(); f++) {
        for (int b = 0; b < tile.bits(); b++) {
            if (tile.bit(f, b) && (coverage.find(ConfigBit{f, b, false}) == coverage.end())) {
                cfg.cunknowns.push_back(ConfigUnknown{f, b});
            }
        }
    };
    return cfg;
}

void TileBitDatabase::load() {
    boost::lock_guard<boost::shared_mutex> guard(db_mutex);
    ifstream in(filename);
    if (!in) {
        throw runtime_error("failed to open tilebit database file " + filename);
    }
    muxes.clear();
    words.clear();
    enums.clear();
    while (!skip_check_eof(in)) {
        string token;
        in >> token;
        if (token == ".mux") {
            MuxBits mux;
            in >> mux;
            muxes[mux.sink] = mux;
        } else if (token == ".config") {
            WordSettingBits cw;
            in >> cw;
            words[cw.name] = cw;
        } else if (token == ".config_enum") {
            EnumSettingBits ce;
            in >> ce;
            enums[ce.name] = ce;
        } else if (token == ".fixed_conn") {
            FixedConnection c;
            in >> c;
            fixed_conns.push_back(c);
        } else {
            throw runtime_error("unexpected token " + token + " while parsing database file " + filename);
        }
    }
}

void TileBitDatabase::save() {
    boost::lock_guard<boost::shared_mutex> guard(db_mutex);
    ofstream out(filename);
    if (!out) {
        throw runtime_error("failed to open tilebit database file " + filename + " for writing");
    }
    out << "# Routing Mux Bits" << endl;
    for (auto mux : muxes)
        out << mux.second << endl;
    out << endl << "# Non-Routing Configuration" << endl;
    for (auto word : words)
        out << word.second << endl;
    for (auto senum : enums)
        out << senum.second << endl;
    out << endl << "# Fixed Connections" << endl;
    for (auto conn : fixed_conns)
        out << conn << endl;
    dirty = false;
}

vector<string> TileBitDatabase::get_sinks() const {
    boost::shared_lock_guard<boost::shared_mutex> guard(db_mutex);
    vector<string> result;
    boost::copy(muxes | boost::adaptors::map_keys, back_inserter(result));
    return result;
}

MuxBits TileBitDatabase::get_mux_data_for_sink(const string &sink) const {
    boost::shared_lock_guard<boost::shared_mutex> guard(db_mutex);
    return muxes.at(sink);
}

vector<string> TileBitDatabase::get_settings_words() const {
    boost::shared_lock_guard<boost::shared_mutex> guard(db_mutex);
    vector<string> result;
    boost::copy(words | boost::adaptors::map_keys, back_inserter(result));
    return result;
}

WordSettingBits TileBitDatabase::get_data_for_setword(const string &name) const {
    boost::shared_lock_guard<boost::shared_mutex> guard(db_mutex);
    return words.at(name);
}

vector<string> TileBitDatabase::get_settings_enums() const {
    boost::shared_lock_guard<boost::shared_mutex> guard(db_mutex);
    vector<string> result;
    boost::copy(enums | boost::adaptors::map_keys, back_inserter(result));
    return result;
}

EnumSettingBits TileBitDatabase::get_data_for_enum(const string &name) const {
    boost::shared_lock_guard<boost::shared_mutex> guard(db_mutex);
    return enums.at(name);
}

vector<FixedConnection> TileBitDatabase::get_fixed_conns() const {
    boost::shared_lock_guard<boost::shared_mutex> guard(db_mutex);
    return fixed_conns;
}

void TileBitDatabase::add_mux_arc(const ArcData &arc) {
    boost::lock_guard<boost::shared_mutex> guard(db_mutex);
    dirty = true;
    if (muxes.find(arc.sink) == muxes.end()) {
        MuxBits mux;
        mux.sink = arc.sink;
        muxes[mux.sink] = mux;
    }
    MuxBits &curr = muxes.at(arc.sink);
    auto found = find_if(curr.arcs.begin(), curr.arcs.end(), [arc](const ArcData &other) {
        return (arc.source == other.source);
    });
    if (found == curr.arcs.end()) {
        curr.arcs.push_back(arc);
    } else {
        if (found->bits == arc.bits) {
            // In DB already, no-op
        } else {
            throw DatabaseConflictError(fmt("database conflict: arc " << arc.source << " -> " << arc.sink <<
                                                                      " already in DB, but config bits " <<
                                                                      arc.bits
                                                                      << " don't match existing DB bits " <<
                                                                      found->bits));
        }
    }

}

void TileBitDatabase::add_setting_word(const WordSettingBits &wsb) {
    boost::lock_guard<boost::shared_mutex> guard(db_mutex);
    dirty = true;
    if (words.find(wsb.name) != words.end()) {
        WordSettingBits &curr = words.at(wsb.name);
        if (curr.bits.size() != wsb.bits.size()) {
            throw DatabaseConflictError(fmt("word " << curr.name << " already exists in DB, but new size "
                                                    << wsb.bits.size() << " does not match existing size "
                                                    << curr.bits.size()));
        }
        for (size_t i = 0; i < curr.bits.size(); i++) {
            if (!(curr.bits.at(i) == wsb.bits.at(i))) {
                throw DatabaseConflictError(fmt("bit " << wsb.name << "[" << i << "] already in DB, but config bits "
                                                       << wsb.bits.at(i) << " don't match existing DB bits "
                                                       << curr.bits.at(i)));
            }
        }
    } else {
        words[wsb.name] = wsb;
    }
}

void TileBitDatabase::add_setting_enum(const EnumSettingBits &esb) {
    boost::lock_guard<boost::shared_mutex> guard(db_mutex);
    dirty = true;
    if (enums.find(esb.name) != enums.end()) {
        EnumSettingBits &curr = enums.at(esb.name);
        for (const auto &opt : esb.options) {
            if (curr.options.find(opt.first) == curr.options.end()) {
                curr.options[opt.first] = opt.second;
            } else {
                if (curr.options.at(opt.first) == opt.second) {
                    // No-op
                } else {
                    throw DatabaseConflictError(
                            fmt("option " << opt.first << " of " << esb.name << " already in DB, but config bits "
                                          << opt.second << " don't match existing DB bits "
                                          << curr.options.at(opt.first)));
                }
            }
        }
    }
    enums[esb.name] = esb;
}

void TileBitDatabase::add_fixed_conn(const Trellis::FixedConnection &conn) {
    boost::lock_guard<boost::shared_mutex> guard(db_mutex);
    if (find(fixed_conns.begin(), fixed_conns.end(), conn) == fixed_conns.end())
        fixed_conns.push_back(conn);
}

TileBitDatabase::TileBitDatabase(const TileBitDatabase &other) {
    UNUSED(other);
    assert(false);
    terminate();
}

DatabaseConflictError::DatabaseConflictError(const string &desc) : runtime_error(desc) {}

TileBitDatabase::~TileBitDatabase() {
    if (dirty)
        save();
#ifdef FUZZ_SAFETY_CHECK
    ip_db_lock.unlock();
#endif
}

}
