#include <iostream>
#include <vector>
#include <string> //NOAH
#include "../util/db_functions.h" //NOAH
#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(const Keyvalue &kv_facts) const {
    EncodedQuality qual{};
    qual.dec.asset_id = asset_id;
    qual.dec.attr = kv_facts[name];
    //std::cout<<"DONE PART 2"<<std::endl;
    //std::cout<<"ASSET ID " <<asset_id<<std::endl;
    //std::cout<<" NAME" <<kv_facts[name]<<std::endl;
    //std::cout<<"VALUE " <<value<<std::endl;  
   
    //THIS IS THE ONE THAT THROWS THE OUT OF RANGE FOR THE UNORDERED MAP
   // std::cout<<"Break"<<std::endl;
    //std::cout<<"ATTEMPTING TO FIND " <<value<<std::endl;
    //std::cout<<"SIZE FROM ENCODE " <<kv_facts.size() << std::endl;
    //std::unordered_map<std::string,int>::const_iterator got = kv_facts.hash_table.find(value);
    //if(got==kv_facts.hash_table.end())
      //  std::cout<< " NOT FOUND"<<std::endl;
    //else
      //  std::cout<<" YES FOUND " <<std::endl;

    //std::cout<<"NAME "<<name<<"VALUE " <<value<< "KEY OR W/E "<< kv_facts[value]<<std::endl;
   // std::cout<<"SIZE FROM ENCODE "<<kv_facts.size()<<std::endl;
    //try { 
   
    qual.dec.val = kv_facts[value];
    //}
    //catch (std::out_of_range outofrange)
      //  kv_facts.hash_table.insert(value, kv_facts.size()+1);
        //kv_facts.length+=1;
        //std::cout<<"YES" << std::endl;
        //qual.dec.val=kv_facts[value];
    //std::cout<<"DONE PART 3"<<std::endl;
    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);
}
