#include <iostream>
#include <vector>
#include <string> 
#include "../util/db_functions.h"
#include "ag_gen.h"
#include "unistd.h" //Included for sleep function for debugging purposes only

/**
 * @brief Constructor for Quality
 *
 * @param asset The id of the asset with which the Quality is associated
 * @param qualName The name of the Quality
 * @param o The operation
 * @param qualValue The value of the Quality
 */


//ORIGINAL QUALITY
Quality::Quality(int asset, std::string qualName, std::string o, std::string qualValue, Keyvalue &facts)
    : asset_id(asset), name(std::move(qualName)), op(std::move(o)), value(std::move(qualValue)), encoded(encode(facts).enc) {}


//TESTING ENCODING ERROR
//Quality::Quality(int asset, std::string qualName, std::string o, std::string qualValue, Keyvalue &facts)
//    : asset_id(asset), name(std::move(qualName)), op(std::move(o)), value(std::move(qualValue)), encoded((size_t)facts.size()) {}

Quality::Quality()
{

}

int Quality::get_asset_id() const { return asset_id; }

/**
 * @return The name of the Quality
 */
std::string Quality::get_name() const { return name; }

/**
 * @return The operation
 */
std::string Quality::get_op() const { return op; }

std::string Quality::get_value() const { return value; }

const size_t Quality::get_encoding() const {
    return encoded;
}

void Quality::set_value(std::string &val) {
    value = val;
}
void Quality::set_value_addp(std::string &val) {
    //value=stoi(value)+stoi(val);
    //std::string old_val=
    //int intval=stoi(val);
    //int fin=intvalue+intval;
 
    value=val;
}
void Quality::set_value_minp(std::string &val) {
    int intvalue=stoi(value);
    int intval=stoi(val);
    int fin=intvalue-intval;
   
    value=std::to_string((fin));
}
/**
 * @brief Prints the Quality
 */
void Quality::print() const {
    std::cout << std::to_string(asset_id) << ": " << name << op << value
              << std::endl;
}

/**
 * @brief Encodes the Quality
 *
 * @param kv_facts The Keyvalue of the facts
 *
 * @return The EncodedQuality
 */
EncodedQuality Quality::encode(Keyvalue &kv_facts) {
    EncodedQuality qual{};
    qual.dec.asset_id = asset_id;
    qual.dec.attr = kv_facts[name];
    
    std::unordered_map<std::string,int>::const_iterator got = kv_facts.hash_table.find(value);
    if(got == kv_facts.hash_table.end()){
        //kv_facts.hash_table[value] = kv_facts.length;
        //Reasoning: Populate fills table with all string values. If we run across an instance where
        //we don't have a value, we know that it must be due to a compound operator, so we can safely assign it its own value.
        kv_facts.hash_table[value] = stoi(value);
	    kv_facts.str_vector.push_back(value);
	    kv_facts.length++;
    }

    qual.dec.val = kv_facts[value];

    return qual;
}

bool Quality::operator==(const Quality &rhs) const {
    return this->asset_id == rhs.asset_id && this->name == rhs.name && this->value == rhs.value;
}

bool Quality::operator<(const Quality &rhs) const {
    return this->asset_id == rhs.asset_id && this->name == rhs.name && stoi(this->value) < stoi(rhs.value);
}

bool Quality::operator>(const Quality &rhs) const {
    return this->asset_id == rhs.asset_id && this->name == rhs.name && stoi(this->value) > stoi(rhs.value);
}

bool Quality::operator>=(const Quality &rhs) const {
    return this->asset_id == rhs.asset_id && this->name == rhs.name && stoi(this->value) >= stoi(rhs.value);
}

bool Quality::operator<=(const Quality &rhs) const {
    return this->asset_id == rhs.asset_id && this->name == rhs.name && stoi(this->value) <= stoi(rhs.value);
}
