//
// Created by Kyle Cook on 6/24/17.
//

#include <iostream>

#include "edge.h"
#include "../util/db.h"
#include <boost/functional/hash.hpp>

/**
 * @brief Constructor for Edge
 * @details Initializes information with given parameters and initializes id to
 * 0.
 *
 * @param iFrom The From Node
 * @param iTo The To Node
 * @param ex Exploit associated with the Edge
 * @param ag AssetGroup associated with the Edge
 */
//Edge::Edge(int iFrom, int iTo, Exploit &ex, AssetGroup &ag)
//    : from_node(iFrom), to_node(iTo), exploit(ex), assetGroup(ag), deleted(false) {}

Edge::Edge(int iFrom, int iTo, Exploit &ex, AssetGroup &ag)
    : from_node(iFrom), to_node(iTo), exploit(ex), assetGroup(ag), deleted(false) {}

Edge::Edge(unsigned long iFrom, unsigned long iTo, Exploit &ex, AssetGroup &ag)
    : from_node(iFrom), to_node(iTo), exploit(ex), assetGroup(ag), deleted(false) {}

Edge::Edge()
{
    
}

/**
 * @return The Edge ID
 */
int Edge::get_id() const { return id; }

void Edge::set_deleted() { deleted = true; }

bool Edge::is_deleted() { return deleted; }

//int Edge::get_from_id()
//{

    //return from_node;

//}

unsigned long Edge::get_from_id() const
{
    return from_node;
}

//int Edge::get_to_id()
//{

//    return to_node;

//}

unsigned long Edge::get_to_id() const
{
    return to_node;
}

int Edge::get_exploit_id() const
{

    return exploit.get_id();

}

/**
 * @return The Edge information as a string for SQL
 */
std::string Edge::get_query() {
    return std::to_string(from_node) + "," + std::to_string(to_node) + "," +
           std::to_string(exploit.get_id()) + ")";
}

/**
 * @brief Sets the Edge id to the current id and increments edge_current_id.
 *
 * @return The new id
 */
int Edge::set_id() {
    id = edge_current_id++;
    return id;
}

void Edge::force_from_id(unsigned long i) {
    from_node = i;
}

void Edge::force_to_id(unsigned long i) {
    to_node = i;
}

int Edge::edge_current_id = 0;

/**
 * @return The Assets as a string for SQL
 */
std::string Edge::get_asset_query() {
    auto current_perm = assetGroup.get_perm();
    std::string sql;
    for (size_t i = 0; i < current_perm.size(); ++i) {

        if (i == 0)
            sql += "(" + std::to_string(id) + "," + std::to_string(i) + "," +
                   std::to_string(current_perm[i]) + ")";

        else
            sql += ",(" + std::to_string(id) + "," + std::to_string(i) + "," +
                   std::to_string(current_perm[i]) + ")";
    }
    return sql;
}
bool Edge::operator==(const Edge& ed2)
{
    if(get_to_id() == ed2.get_to_id() &&
        get_from_id() == ed2.get_from_id() &&
        get_exploit_id() == ed2.get_exploit_id()){
        return true;
    }
    else return false;
}

void Edge::force_set_id(int i)
{
	id = i;
}

size_t Edge::hash(){
    //  size_t hash = 0xf848b64e; // Random seed value
    // size_t seed = 0x0c32a12fe19d2119;
    size_t seed = 0;

    boost::hash_combine(seed, get_exploit_id());
    boost::hash_combine(seed, get_from_id());
    boost::hash_combine(seed, get_to_id());

    return seed;
}
