#include "util/serialize_value.h"
#include <algorithm>
#include <string>
#include "util/coding.h"
#include <iostream>
#include "leveldb/slice.h"

namespace leveldb{
bool compareByFirst(const Field& a, const Field& b) {
    return a.first < b.first; // 按字段名升序排序
}

std::string SerializeValue(const FieldArray& fields){
    FieldArray sortFields = fields;
    std::sort(sortFields.begin(), sortFields.end(), compareByFirst);
    std::string result;
    for (const Field& pairs : sortFields) {
        PutLengthPrefixedSlice(&result, pairs.first);
        PutLengthPrefixedSlice(&result, pairs.second);
    }
    return result;
}

std::string SerializeValue(const FieldSliceArray& fields) {
    using pss = std::pair<Slice,Slice>;
    FieldSliceArray sortFields = fields;
    std::sort(sortFields.begin(), sortFields.end(),
    [&](const pss &lhs, const pss &rhs) {
        return lhs.first.compare(rhs.first);
    });
    std::string result;
    for (const pss& pairs : sortFields) {
        PutLengthPrefixedSlice(&result, pairs.first);
        PutLengthPrefixedSlice(&result, pairs.second);
    }
    return result;
}

FieldArray *ParseValue(const std::string& value_str,FieldArray *fields){
    Slice valueSlice(value_str);
    // FieldArray *res = new FieldArray;
    FieldArray *res = fields;
    Slice nameSlice = Slice();
    Slice valSlice = Slice();
    std::string nameStr;
    std::string valStr;
    while(GetLengthPrefixedSlice(&valueSlice, &nameSlice)){
        nameStr = nameSlice.ToString();

        if(GetLengthPrefixedSlice(&valueSlice, &valSlice)){
            valStr = valSlice.ToString();
            res->emplace_back(nameStr, valStr);
        } else {
            std::cout << "name and val not match! From ParseValue" << std::endl;
            assert(0);
        }
        nameSlice.clear();
        valSlice.clear();
    }
    return res;
}

void InternalFieldArray::Map() {
    if(isMapped) return;
    for(const Field& pair : fields) {
        map[pair.first] = pair.second;
    }
    isMapped = true;
}

std::string InternalFieldArray::Serialize() {
    std::string result;
    if(isMapped) {
        for(auto pair : map) {
            PutLengthPrefixedSlice(&result, pair.first);
            PutLengthPrefixedSlice(&result, pair.second);
        }
    } else {
        result = SerializeValue(fields);
    }
    return result;
}

bool InternalFieldArray::HasField(const Field& field) {
    if(isMapped) {
        if(map.count(field.first) && map[field.first] == field.second) {
            return true;
        }
        return false;
    }
    return std::find(fields.begin(),fields.end(),field) != fields.end();
}

Slice InternalFieldArray::ValOfName(const std::string &name) {
    if(isMapped) {
        if(map.count(name)) {
            return map[name];
        }
        return Slice();
    }
    
    for (auto iter = fields.begin(); iter != fields.end(); iter++){
        if (iter->first == name) {
            return iter->second;
        } else if (iter->first > name) {
            return Slice();
        }
    }
    return Slice();
}

}