#ifndef ORDERGETWORK_H
#define ORDERGETWORK_H

#include <QObject>
#include <QFile>
#include <QTimer>
#include <QJsonObject>
#include <QJsonArray>
#include <QVariantMap>
#include <QJsonDocument>
#include <QApplication>

#include "base/Network/billSocket.h"

#include "preDefine.h"

#include "base/Arithmetic/cretopt.h"

#define FMH_BIND                0
#define FMH_LOGIN               1
#define FMH_GETORDER            2
//确认接单
#define FMH_CONFIRM             4
//拒绝接单
#define FMH_REFUSE              5
//送出订单
#define FMH_SENDOUT             6
//完成订单
#define FMH_COMPLETE            7
//拒绝退单
#define FMH_REFUSEREFUND        8
//退单
#define FMH_REFUNDORDER         9

#define FMH_GETRORDER           32
//
#define FMH_MAKEOVER            10

//...

#define FMH_MAX         256

//拉订单工作了流 送出 退单 接单 等 非阻塞可以和其他对象共享线程 不允许阻塞操作在该对象中
class OrderGetWork : public QObject
{
    Q_OBJECT
public:
    explicit OrderGetWork(QObject *parent = 0);

    void workStart();

    unsigned int timeout() const;

    void setTimeout(unsigned int timeout);

    void setStopflag(bool stopflag);

    bool loginToServer(QString &error);

    bool bingToServer(QString &error);

    virtual bool event(QEvent *e);

    void setStoreinfo(const QVariantMap &storeinfo);

    void setUrl(const QString &url);

    void setAutoconfirm(const QString &autoconfirm);

    void loginStart();

signals:
    void quit();

private:
    void optOrder(const QJsonArray &orders);

    bool PullOrder(unsigned int timeout, QString &error);
    //订单操作
    void optOrderWithType(const QVariantMap &map);
    //登录成功回写数据
    void SetStoreInfoToConfig();
    //内部登录不推送消息到界面
    void login();
private:
    //门店信息 门店编号 pos编号 用户名 密码
    QVariantMap _storeinfo;
    //超时时间
    unsigned int _timeout;
    //事件带过来的信息
    QString _ordersinfo;
    //服务器地址
    QString _url;
    //停止标识
    bool _stopflag;
    //是否登录成功
    bool _islogin;
    //拉单时间戳
    QString _timestamp;
    //拉单用token
    QString _token;
    //是否自动接单
    QString _autoconfirm;
    //自动重新登录
    QTimer _timer;
};

class OrderGetDataProcess
{
public:
    friend class OrderGetWork;
private:

    static bool isBind(QVariantMap storeinfo)
    {
        if(storeinfo.isEmpty())
            return false;

        if(storeinfo.contains(JSON_KEY_PARTNERID) && storeinfo.contains(JSON_STOREID) && storeinfo.contains(JSON_STATIONID))
        {
            QString partnerid = storeinfo[JSON_KEY_PARTNERID].toString();
            QString storeid = storeinfo[JSON_STOREID].toString();
            QString stationid = storeinfo[JSON_STATIONID].toString();
            QString tmp = partnerid + storeid + stationid;

            QLOG_DEBUG() << "Store Info : " << tmp;

            QFile file(qApp->applicationDirPath() + "/bing.flag");

            if(!file.open(QFile::ReadOnly))
                return false;

            QByteArray data = file.readAll();

            file.close();

            QLOG_DEBUG() << qApp->applicationDirPath() + "/bing.flag" << ":" << data;

            QString info = QString::fromUtf8(data);

            if(tmp.compare(info, Qt::CaseInsensitive) == 0)
                return true;
        }

        return false;
    }

    static void setBind(QVariantMap storeinfo)
    {
        if(storeinfo.isEmpty())
            return ;

        if(storeinfo.contains(JSON_KEY_PARTNERID) && storeinfo.contains(JSON_STOREID) && storeinfo.contains(JSON_STATIONID))
        {
            QString partnerid = storeinfo[JSON_KEY_PARTNERID].toString();
            QString storeid = storeinfo[JSON_STOREID].toString();
            QString stationid = storeinfo[JSON_STATIONID].toString();
            QString tmp = partnerid + storeid + stationid;

            QLOG_DEBUG() << "Store Info : " << tmp;

            QFile file(qApp->applicationDirPath() + "/bing.flag");

            if(file.open(QFile::WriteOnly))
            {
                file.write(tmp.toUtf8());
                file.close();
            }
        }
    }

    static bool getLogingRequest(const QVariantMap &json, QJsonObject &data)
    {
        if(!json.contains(JSON_STOREID) || !json.contains(JSON_STATIONID) ||
                !json.contains(JSON_KEY_USERID) || !json.contains(JSON_KEY_PWD) ||
                !json.contains(JSON_KEY_PARTNERID))
            return false;

        data.insert(JSON_STOREID, json[JSON_STOREID].toString());
        data.insert(JSON_DEVICEID, json[JSON_STATIONID].toString());
        data.insert(JSON_KEY_USERID, json[JSON_KEY_USERID].toString());
        data.insert(JSON_KEY_PWD, json[JSON_KEY_PWD].toString());
        //data.insert(JSON_KEY_PARTNERID, json[JSON_KEY_PARTNERID].toInt());
        data.insert(JSON_KEY_PARTNERID, json[JSON_KEY_PARTNERID].toString());

        return true;
    }

    static bool getOrderRequest(const QVariantMap &json, QJsonObject &data, QString timestamp, QString token, QString autoconfirm)
    {
        if(!json.contains(JSON_STOREID) || !json.contains(JSON_STATIONID) ||
                !json.contains(JSON_KEY_USERID) || !json.contains(JSON_KEY_PWD) ||
                !json.contains(JSON_KEY_PARTNERID))
            return false;

        data.insert(JSON_STOREID, json[JSON_STOREID].toString());
        //data.insert(JSON_DEVICEID, json[JSON_STATIONID].toString());
        //data.insert(JSON_KEY_USERID, json[JSON_KEY_USERID].toString());
        //data.insert(JSON_KEY_PWD, json[JSON_KEY_PWD].toString());
        data.insert(JSON_KEY_PARTNERID, token);
        data.insert(JSON_KEY_TIMESTAMP, timestamp);
        //data.insert(JSON_KEY_TIMESTAMP, 0);
        data.insert(JSON_KEY_AUTOCONFIRM, autoconfirm);

        return true;
    }

    static bool getBindRequest(const QVariantMap &json, QJsonObject &data)
    {
        if(!json.contains(JSON_STOREID) || !json.contains(JSON_STATIONID))
            return false;

        data.insert(JSON_STOREID, json[JSON_STOREID].toString());
        data.insert(JSON_DEVICEID, json[JSON_STATIONID].toString());
        //data.insert(JSON_KEY_PARTNERID, json[JSON_KEY_PARTNERID].toInt());
        data.insert(JSON_KEY_PARTNERID, json[JSON_KEY_PARTNERID].toString());
        data.insert(JSON_KEY_APPVER, DEFAULT_APP_VER);
        data.insert(JSON_KEY_SYSTEMVER, DEFAULT_SYSTEM_VER);

        return true;
    }

    static void getOptRequest(const QVariantMap &map, QJsonObject &json)
    {
        json = QJsonObject::fromVariantMap(map);
        if(map.contains(EVENT_KEY_STATUS))
            json.remove(EVENT_KEY_STATUS);
        if(map.contains(EVENT_KEY_MSG))
        {
            json.remove(EVENT_KEY_MSG);
            json.insert(JSON_KEY_REASON, map[EVENT_KEY_MSG].toString());
        }
    }

    static void getComplateJson(QString action, QString access_token, QString ver, const QJsonObject &json, QJsonObject &complatejson)
    {
        complatejson = json;

        complatejson.insert(JSON_KEY_ACTION, action);
        complatejson.insert(JSON_KEY_ACCESS_TOKEN, access_token);
        complatejson.insert(JSON_KEY_VER, ver);
    }

    static void getRequestType(QString status, int &reqtype)
    {
        reqtype = -1;

        if(status.compare(OPERATION_CONFRIM, Qt::CaseInsensitive) == 0)
            reqtype = FMH_CONFIRM;
        if(status.compare(OPERATION_REFUSE, Qt::CaseInsensitive) == 0)
            reqtype = FMH_REFUSE;
        if(status.compare(OPERATION_SENDOUT, Qt::CaseInsensitive) == 0)
            reqtype = FMH_SENDOUT;
        if(status.compare(OPERATION_COMPLETE, Qt::CaseInsensitive) == 0)
            reqtype = FMH_COMPLETE;
        if(status.compare(OPERATION_REFUSEREFUND, Qt::CaseInsensitive) == 0)
            reqtype = FMH_REFUSEREFUND;
        if(status.compare(OPERATION_REFUNDORDER, Qt::CaseInsensitive) == 0)
            reqtype = FMH_REFUNDORDER;
        if(status.compare(OPERATION_GETDELIVERS, Qt::CaseInsensitive) == 0)
            reqtype = FMH_CONFIRM;
        if(status.compare(OPERATION_MAKEOVER, Qt::CaseInsensitive) == 0)
            reqtype = FMH_MAKEOVER;
    }

    static bool getAction(int REQ, QString &action)
    {
        switch (REQ)
        {
            case FMH_BIND:
                action = QString("saas.posdevice.bind");
                return true;
            case FMH_LOGIN:
                action = QString("saas.posdevice.login");
                return true;
            case FMH_GETORDER:
                action = QString("saas.order.get");
                return true;
            case FMH_MAKEOVER:
                action = QString("saas.order.doneNotify");
                return true;
            case FMH_CONFIRM:
                action = QString("saas.order.confirmTake");
                return true;
            case FMH_REFUSE:
                action = QString("saas.order.rejectTake");
                return true;
            case FMH_SENDOUT:
                action = QString("saas.dispatch.create");
                return true;
            case FMH_COMPLETE:
                action = QString("saas.dispatch.finish");
                return true;
            case FMH_REFUSEREFUND:
                action = QString("saas.refund.reject");
                return true;
            case FMH_REFUNDORDER:
                action = QString("saas.refund.agree");
                return true;
            case FMH_GETRORDER:
                action = QString("saas.order.get");
                return true;
            default:
                return false;
        }
    }

#ifdef FM_TEST
    static bool requestGetRSASign(int reqtype, const QJsonObject &json, QString &sign, QString &action, QString &access_token, QString &ver)
    {
        QJsonObject tmpjson;

        if(!OrderGetDataProcess::getAction(reqtype, action) ||
            !OrderGetDataProcess::getAccess_Token(access_token) ||
                !OrderGetDataProcess::getVer(ver))
            return false;

        OrderGetDataProcess::getComplateJson(action, access_token, ver, json, tmpjson);

        sign = "abcdefghijklmnopqrstuvwxyz";

        return true;
    }

    static bool getAccess_Token(QString &access_token)
    {
        access_token = "888888888888888888";
        return true;
    }

    static bool getVer(QString &ver)
    {
        ver = "1";
        return true;
    }

#else
    static bool requestGetRSASign(int reqtype, const QJsonObject &json, QString &sign, QString &action, QString &access_token, QString &ver)
    {
        QJsonObject tmpjson;

        if(!OrderGetDataProcess::getAction(reqtype, action) ||
            !OrderGetDataProcess::getAccess_Token(access_token) ||
                !OrderGetDataProcess::getVer(ver))
            return false;

        OrderGetDataProcess::getComplateJson(action, access_token, ver, json, tmpjson);
        return CretOperate::GetSign(tmpjson, sign);
    }

    static bool getAccess_Token(QString &access_toekn)
    {
        access_toekn = DEFAULT_ACCESS_TOKEN;
        return true;
    }

    static bool getVer(QString &ver)
    {
        ver = "1";
        return true;
    }
#endif
    static bool getRealUrl(int reqtype, const QJsonObject &json, const QString &url, QString &realurl)
    {

        QString action, access_token, ver, sign;

        if(!OrderGetDataProcess::requestGetRSASign(reqtype, json, sign, action, access_token, ver))
            return false;

        QString tmpurl = url;

        realurl = tmpurl.arg(action, access_token, ver, sign);

        return true;
    }
    //这里本来应该有服务端控制下次轮询时间的
    static void getRSTTimeout(const QJsonObject &json, unsigned int &timeout, unsigned int defaulttimeout)
    {
        if(json.contains(JSON_KEY_RESULT) && json[JSON_KEY_RESULT].isObject() &&
                json[JSON_KEY_RESULT].toObject().contains(JSON_KEY_SYNCTIME))
            //timeout = json[JSON_KEY_RESULT].toObject()[JSON_KEY_SYNCTIME].toInt() * 1000;
            timeout = VALUE_PULLSYNCTIME;
        if(timeout <= 0)
            timeout = VALUE_PULLSYNCTIME;
    }

    static void getTimestamp(const QJsonObject &json, QString &timestamp)
    {
        QString tmps;

        tmps.clear();

        if(json.contains(JSON_KEY_RESULT) && json[JSON_KEY_RESULT].isObject() &&
                json[JSON_KEY_RESULT].toObject().contains(JSON_KEY_TIMESTAMP))
            tmps = json[JSON_KEY_RESULT].toObject()[JSON_KEY_TIMESTAMP].toString();
        if(!tmps.isEmpty())
            timestamp = tmps;
    }

    static bool checkStatusCode(const QJsonObject &json, QString &error)
    {
        if(json.contains(JSON_KEY_CODE) && json[JSON_KEY_CODE].toString().compare("ok", Qt::CaseInsensitive) == 0)
            return true;

        error.append(json[JSON_KEY_MESSAGE].toString());

        return false;
    }

    static bool getOrders(const QJsonObject &json, QJsonArray &array)
    {
        if(json.contains(JSON_KEY_RESULT) && json[JSON_KEY_RESULT].isObject() &&
                json[JSON_KEY_RESULT].toObject().contains(JSON_KEY_ORDERS) && json[JSON_KEY_RESULT].toObject()[JSON_KEY_ORDERS].isArray())
        {
            array = json[JSON_KEY_RESULT].toObject()[JSON_KEY_ORDERS].toArray();
            return true;
        }
        return false;
    }

    static bool getOrderStatus(const QJsonObject &json, QString &orderid, QString &status, QString &refundstatus)
    {
        if(json.contains(JSON_KEY_RESULT) && json[JSON_KEY_RESULT].isObject() &&
                json[JSON_KEY_RESULT].toObject().contains(JSON_KEY_ORDERID)&&
                json[JSON_KEY_RESULT].toObject().contains(JSON_KEY_ORDERSTATUS))
        {
            orderid = json[JSON_KEY_RESULT].toObject()[JSON_KEY_ORDERID].toString();
            status = json[JSON_KEY_RESULT].toObject()[JSON_KEY_ORDERSTATUS].toString();

            if(json[JSON_KEY_RESULT].toObject().contains(JSON_KEY_REFUNDSTATUS))
                refundstatus = json[JSON_KEY_RESULT].toObject()[JSON_KEY_REFUNDSTATUS].toString();
            else
               refundstatus.clear();

            return true;
        }
        return false;
    }

    static bool setToken(const QJsonObject &json, QString &token)
    {
        if(json.contains(JSON_KEY_RESULT) && json[JSON_KEY_RESULT].isObject() &&
                json[JSON_KEY_RESULT].toObject().contains(JSON_KEY_UNIFYID))
        {
            token = json[JSON_KEY_RESULT].toObject()[JSON_KEY_UNIFYID].toString();
            return true;
        }

        return false;
    }

    static bool getToken(const QJsonObject &json, QString &token)
    {
        if(json.contains(JSON_KEY_RESULT) && json[JSON_KEY_RESULT].isObject() &&
                json[JSON_KEY_RESULT].toObject().contains(JSON_KEY_TOKEN))
        {
            token = json[JSON_KEY_RESULT].toObject()[JSON_KEY_TOKEN].toString();
            return true;
        }

        return false;
    }
};
#endif // ORDERGETWORK_H
