//
// Created by Ht on 2019/8/14.
//

#ifndef JSONPROTOCOL_JRDPFIELDDEF_H
#define JSONPROTOCOL_JRDPFIELDDEF_H

#include <qlibc/StringUtils.hpp>
#include <qlibc/NumberUtils.hpp>

namespace jedp{

    static const char* vkey_field_typekey_prefix_byte = "@Byte_";
    static const char* vkey_field_typekey_prefix_uri = "@Uri_";
    static const char* vkey_field_typekey_prefix_val = "@Val_";

    static const char* sval_dp_array_seperator = "@";
    static const char* vkey_field_typekey_prefix_array = "array@";

    static const char* sval_dp_prefix_func = "@";
    static const char* sval_dp_prefix_primary = "*";
    static const char* sval_dp_key_connector = "_";
    static const char* sval_dp_key_setvalue = "=";

	//添加大小端模式 Add by hechuan 2019-09-19
	static const char* vkey_field_big_endian_val = "big-endian";
	static const char* vkey_field_little_endian_val = "little-endian";

    typedef enum {
		bigEndian = 0,					//大端模式
		littleEndian,					//小端模式
		defaultEndian = littleEndian	//默认为小端模式
	} JRDpEndianType;

    typedef enum {
        otypeNull = 0,
        otypeCommon,
        otypeRelative,
        otypeVar,
        otypeRelativeVar     //变动偏移、且变长
    } JRDpFieldOffsetType;

	

    class JE_API JROffsetDef {

    public:
        long  offsetByte;
        QByte  offsetBit;

        JROffsetDef(){
            offsetByte = -1;
            offsetBit = 0;
        };

        JROffsetDef(long offset, QByte bit) {
            offsetByte = offset;
            offsetBit = bit;
        }

        JROffsetDef & operator = (const JROffsetDef& org){
            this->offsetByte = org.offsetByte;
            this->offsetBit = org.offsetBit;
            return *this;
        };

        //计算bit位长度差，用于计算当前的位长度。
        //要求前者应该大于后者，否则结果为异常
        JROffsetDef operator - (const JROffsetDef& org) {
			//之前暂时注释，其在处理存在取位运算时，两个字节连接的地方有问题 Delete by hechuan 2019-09-16
			char offsetBit = this->offsetBit - org.offsetBit;
			 long offsetByte = this->offsetByte - org.offsetByte;
			 if(offsetBit<0){
				 offsetByte--;
				 offsetBit = static_cast<char>(BIT_CNT_OF_BYTE + offsetBit);
			 }
            return JROffsetDef(offsetByte, static_cast<QByte>(offsetBit));
        };

        size_t bitSize() const{
            return static_cast<size_t>(offsetByte * BIT_CNT_OF_BYTE + offsetBit);
        }

        size_t byteSize() const{
            return static_cast<size_t>(offsetByte + (offsetBit >0 ? 1 : 0));
        }

    };

    typedef std::vector<JROffsetDef> JROffsetList;

    static const char* sval_type_null = "null";
    static const char* sval_type_bool = "bool";
    static const char* sval_type_byte = "byte";
    static const char* sval_type_word = "word";
    static const char* sval_type_rword = "rword";   //reverse sequence word.
    static const char* sval_type_dword = "dword";
    static const char* sval_type_rdword = "rdword";
    static const char* sval_type_qword = "qword";
    static const char* sval_type_rqword = "rqword";
    static const char* sval_type_int = "int";
    static const char* sval_type_rint = "rint";
    static const char* sval_type_uint = "uint";
    static const char* sval_type_ruint = "ruint";
    static const char* sval_type_string = "string";
    static const char* sval_type_longlong = "longlong";
    static const char* sval_type_rlonglong = "rlonglong";
    static const char* sval_type_ullong = "ulong";
    static const char* sval_type_rullong = "rulong";
    static const char* sval_type_date = "date";
    static const char* sval_type_bytestr = "bytestr";
    static const char* sval_type_table = "table";
    static const char* sval_type_array = "array";
    static const char* sval_type_expandable = "expandable";
    static const char* sval_type_object = "object";
    static const char* sval_type_fixbytes = "fixbytes";
    static const char* sval_type_unkown = "unkown";
    static const char* sval_type_default = sval_type_byte;

    static const char* sval_mismatch_type = "[type mismatch]";
    static const char* sval_bool_str_true = "true";
    static const char* sval_bool_str_false = "false";

    static const QByte ival_expandable_max_ = BYTE_CNT_OF_QWORD;   //可扩展整数字节最大扩展到16个字节

    static const char* transTable[] = {
            sval_type_null,
            sval_type_bool,
            sval_type_byte,
            sval_type_word,
            sval_type_rword,
            sval_type_dword,
            sval_type_rdword,
            sval_type_qword,
            sval_type_rqword,
            sval_type_int,
            sval_type_rint,
            sval_type_uint,
            sval_type_ruint,
            sval_type_expandable,
            sval_type_string,
            sval_type_longlong,
            sval_type_rlonglong,
            sval_type_ullong,
            sval_type_rullong,
            sval_type_date,
            sval_type_bytestr,
            sval_type_table,
            sval_type_array,
            sval_type_object,
            sval_type_fixbytes,
            sval_type_unkown,
            nullptr
    };
    static const char* jsonValType[] = {
            "nullValue",
            "intValue",
            "uintValue",
            "realValue",
            "stringValue",
            "booleanValue",
            "arrayValue",
            "objectValue",
    };

    typedef enum {
        typeNull = 0 ,
        typeBool,
        typeByte,
        typeWord,
        typeRWord,
        typeDWord,
        typeRDWord,
        typeQWord,
        typeRQWord,
        typeInt,
        typeRInt,
        typeUInt,
        typeRUInt,
        typeExpandableInt,
        typeString,
        typeLongLong,
        typeRLongLong,
        typeULLong,
        typeRULLong,
        typeDate,
        typeByteStr,
        typeTable,
        typeArray,
        typeObject,
        typeFixBytes,
        typeUnkown
    } JRDpFieldValueType;

    typedef enum {
        rangeTypeNull = 0,
        rangeTypeByte,
        rangeTypeArray
    } JRDpFieldRangeType;

    class JE_API JRDpFieldTypeUtils {
    public:
        static JRDpFieldValueType valueTypeOf(const std::string& stypeName);
        //用于log输出
        static const char* nameOfValueType(JRDpFieldValueType valType);
        //用于log输出
        static const char* nameofJsonValueType(const Json::Value& valType);
        //将字符串、转换为特定类型的值的Value
        static void stringToValueWithType(const std::string &str, JRDpFieldValueType valueType, Json::Value& value);
        //将特定类型的值，转换为对应格式的字符串
        static void valueToStringByType(const Json::Value &val, JRDpFieldValueType valueType, std::string& str);
        static std::string valueToStringByType(const Json::Value &val, JRDpFieldValueType valueType, size_t bitlen );
        //检验类型匹配性
        static bool typeMatch(const Json::Value &value, JRDpFieldValueType valueType);


        /**
         *      从buff的 bit offset开始，转换位type的Value值,
         * @param buff
         * @param bitlen
         * @param bitOffset
         * @param type
         * @param val
         */
        static void bufferToValueByType(const QByte* buff, size_t bitOffset, size_t bitlen, JRDpFieldValueType type, Json::Value& val);
        /**
         *      将Value值，按类型type转换为Buff，存放在buff中，bit偏移为bitOffset，bit长度为bitlen
         *      buff需要预先分配内存空间，不能为空，长度足够覆盖bitlen
          *     注意，buff不能直接是目标缓存，bitlen的处理过程中，可能覆盖掉部分数据。
          * @param value
          * @param type
          * @param buff
          * @param bitlen
          * @return
          */
        static size_t valueToBufferByType(const Json::Value &value, JRDpFieldValueType type, QByte *buff, size_t bitlen);

        static JRDpFieldValueType valueTypeOfByteLength(JRDpFieldOffsetType offsettype, size_t bitCount, const std::string* varSize);

        static size_t valueToUIntByType(Json::Value value, JRDpFieldValueType type);

        /**
         * 根据Value的类型，决定Field的valueType
         *          并判断需要的Buffer的长度
         * @param value
         * @return
         */
        static void valueTypeByValue(const Json::Value &value, JRDpFieldValueType& type, size_t& size);

        static QBitShiftAlignType alignTypeOfValueType(JRDpFieldValueType valueType);

        static size_t byteLenOfType(JRDpFieldValueType strType);

		//设置大小端模式 Add by hechuan 2019-09-19
		static void setEdianMode(JRDpEndianType endianType);
	private:
		static JRDpEndianType mEdianType;	//大小端模式
		static bool mCheckedEndian;			//标记大小端模式是否已经被初始化，默认值为false

    };
};

#endif //JSONPROTOCOL_JRDPFIELDDEF_H
