#include <deque>
#include <string>
#include "leveldb/db.h"
#include "leveldb/slice.h"
#include "leveldb/status.h"
#include "leveldb/write_batch.h"
#include "port/port_stdcxx.h"
#include "util/coding.h"
#include "util/mutexlock.h"
#include "util/serialize_value.h"
#include <unordered_set>
// #include "fielddb/field_db.h"
#include "fielddb/SliceHashSet.h"

#ifndef REQUEST_H
#define REQUEST_H
namespace fielddb {
using namespace leveldb;
// 在taskqueue中的Request,由taskqueue最开始的线程处理一批Request
// 这个思路与write写入的思路类似
class FieldDB;
class Request {
public:
    friend class FieldDB;
    enum RequestType {
        FieldsReq_t,
        //ValueReq_t,
        iCreateReq_t,
        iDeleteReq_t,
        DeleteReq_t,
        BatchReq_t,
    };

public:
    // Request(std::string *Key,std::string *Value,port::Mutex *mu):
    //     Key(Key),Value(Value),hasFields(false),cond_(mu) { }
    // Request(std::string *Key,FieldArray *Fields,port::Mutex *mu):
    //     Key(Key),Fields(Fields),hasFields(true),cond_(mu) { }
    Request(RequestType type,port::Mutex *mu):
        type_(type),cond_(mu),done(false) { parent = this; };

    //virtual ~Request();

    inline bool isFieldsReq() { return type_ == FieldsReq_t; }
    // inline bool isValueReq() { return type_ == ValueReq_t; }
    inline bool isiCreateReq() { return type_ == iCreateReq_t; }
    inline bool isiDeleteReq() { return type_ == iDeleteReq_t; }
    inline bool isDeleteReq() { return type_ == DeleteReq_t; }
    inline bool isBatchReq() { return type_ == BatchReq_t; }

    //用于含有Fields的
    virtual void ConstructBatch(WriteBatch &KVBatch,WriteBatch &IndexBatch,
                WriteBatch &MetaBatch,fielddb::FieldDB *DB,SliceHashSet &batchKeySet);
    //主要用于icreate和idelete在队列中的注册当前状态
    virtual void Prepare(FieldDB *DB);
    virtual void Finalize(FieldDB *DB);

    virtual void PendReq(Request *req);
    bool isPending();
// protected:
    bool done;
    Status s;
    port::CondVar cond_;
    RequestType type_;
    Request *parent;
};

//含有field的put
class FieldsReq : public Request {
public:
    FieldsReq(Slice Key,const FieldArray &Fields,port::Mutex *mu):
        Key(Key),Request(FieldsReq_t,mu) {
            for(auto &[name,value] : Fields) {
                SliceFields.push_back({name,value});
            }
        };

    FieldsReq(Slice Key, Slice Value,port::Mutex *mu):
        Key(Key),Request(FieldsReq_t,mu) {
            Slice nameSlice, valSlice;
            while(GetLengthPrefixedSlice(&Value, &nameSlice)) {
                if(GetLengthPrefixedSlice(&Value, &valSlice)) {
                    SliceFields.push_back({nameSlice,valSlice});
                } else {
                    std::cout << "name and val not match! From FieldsReq Init" << std::endl;
                }
                nameSlice.clear(), valSlice.clear();
            }
        }

    void ConstructBatch(WriteBatch &KVBatch,WriteBatch &IndexBatch,
        WriteBatch &MetaBatch,fielddb::FieldDB *DB,SliceHashSet &batchKeySet) override;

    Slice Key;
    FieldSliceArray SliceFields;
};

//不含有field的put,但是计划被弃用了
// class ValueReq : public Request {
// public:
//     ValueReq(std::string *Key,std::string *Value,port::Mutex *mu):
//         Key(Key),Value(Value),Request(ValueReq_t,mu) { };

//     std::string *Key;
//     std::string *Value;
// };

//创建索引的request
class iCreateReq : public Request {
public:
    iCreateReq(Slice Field,port::Mutex *mu):
        Field(Field),Request(iCreateReq_t, mu),Existed(false) { };

    void ConstructBatch(WriteBatch &KVBatch,WriteBatch &IndexBatch,
        WriteBatch &MetaBatch,fielddb::FieldDB *DB,SliceHashSet &batchKeySet) override;
    void Prepare(FieldDB *DB) override;
    void Finalize(FieldDB *DB) override;
    void PendReq(Request *req) override;
        
    bool Existed;
    Slice Field;
    std::deque<Request *> pending_list;
};

//删除索引的request
class iDeleteReq : public Request {
public:
    iDeleteReq(Slice Field,port::Mutex *mu):
        Field(Field),Request(iDeleteReq_t, mu),Deleted(false) { };

    void ConstructBatch(WriteBatch &KVBatch,WriteBatch &IndexBatch,
        WriteBatch &MetaBatch,fielddb::FieldDB *DB,SliceHashSet &batchKeySet) override;
    void Prepare(FieldDB *DB) override;
    void Finalize(FieldDB *DB) override;
    void PendReq(Request *req) override;

    bool Deleted;
    Slice Field;
    std::deque<Request *> pending_list;
};

//删除key的request
class DeleteReq : public Request {
public:
    DeleteReq(Slice Key,port::Mutex *mu):
        Key(Key),Request(DeleteReq_t,mu) { };

    void ConstructBatch(WriteBatch &KVBatch,WriteBatch &IndexBatch,
        WriteBatch &MetaBatch,fielddb::FieldDB *DB,SliceHashSet &batchKeySet) override;

    Slice Key;
};

class BatchReq : public Request {
public:
    BatchReq(WriteBatch *Batch,port::Mutex *mu);
    ~BatchReq();

    void ConstructBatch(WriteBatch &KVBatch,WriteBatch &IndexBatch,
        WriteBatch &MetaBatch,fielddb::FieldDB *DB,SliceHashSet &batchKeySet) override;

    WriteBatch *Batch;
    std::deque<Request *> sub_requests;
    // std::deque<std::string> str_buf;
    // std::deque<FieldArray> fa_buf;
};

class SnapshotReq;

class XSnapshot {
friend class SnapshotReq;
public:
    XSnapshot(const Snapshot *kv,const Snapshot *index) 
        : kv_snapshot(kv), index_snapshot(index) {}

    const leveldb::Snapshot *kv_snapshot;
    const leveldb::Snapshot *index_snapshot;
};

class SnapshotReq : public Request {
public:
    SnapshotReq(port::Mutex *mu):Request(iCreateReq_t, mu) { };
    void Prepare(FieldDB *DB);
    XSnapshot *xSnapshot;
};

}

#endif