#ifndef BILLMANGER_H
#define BILLMANGER_H

#include "NetWork/Socket.h"
#include <QTimer>
#include "DataObject/OrderObject.h"
#include "DataObject/DeliverObject.h"
#include <QDateTime>
#include "../fmTakeaway_db/FmTakeaway_db.h"

class BillsManger : public QObject
{
    Q_OBJECT
public:
    // 服务器错误、网络错误
    typedef enum{SERVER=0, SOCKET}ErrorType;

public:
    static BillsManger& Instance();
    OrderObject* GetOrderObjByOrderId(const QString& orderId);

    void Login();
    void ProcOrders(const QString& operaName,const QString& orderId, int reasonCode = -1, const DeliverObject& deliverObj=DeliverObject());
    void ProcOrders(const QString& operaName,const QString& orderId, const QString& desc);
    void StopPullOrder();
    void PullDelivers();
    QList<DeliverObject> GetDelivers();

    //! Write POS bills
    bool        WriteBill(OrderObject *order);
    bool        WriteBill(const QString &oid);
    bool        WriteTill(const OrderObject *order);

    //! Decides destination virtual table id
    int         GetTableVID(OrderObject *order);
    int         GetTableVID(const QJsonObject &order);

    QString     LastError() const;

public slots:
    void        onOperatorChanged(const FmTakeaway_db::OperatorInfo&);
    void        onGetNewStoreInfo(const QJsonObject&);
    void        onUpdateWritePosStatus(const OrderObject *order);

private:
    BillsManger();
    BillsManger(BillsManger const&);
    BillsManger& operator=(BillsManger const&);

    void        _ProcLoginReply(const QByteArray &data);
    void        _ProcPullOrdersReply(const QByteArray &data);
    void        _ProcConfirmReply(const QByteArray &data);
    void        _ProcRejectReply(const QByteArray &data);
    void        _ProceSendoutReply(const QByteArray &data);
    void        _ProceCompleteReply(const QByteArray &data);
    void        _ProceDeliversReply(const QByteArray &data);
    void        _ProcRefundReply(const QByteArray &data);
    QString     _GetJsonString(const QJsonObject &);
    bool        _OrderTableChanged(int &last, int &current, const QJsonObject &new_order);
    int         _GetTableVID(OrderObject *order);
    int         _CalcPosAmount(const QByteArray &order);
    void        _CheckReservations();



private:
    Socket m_loginSocket;
    Socket m_pullOrdersSocket;
    Socket m_procOrdersSocket;
    Socket m_pullDeliversSocket;

    // 存放所有的订单 key:订单ID value:订单具体信息
    QMap<QString,OrderObject*>  m_ordersMap;
    QStringList                 m_rsv_orders;   //! Reservation orders' ID

    // 存放所有送货员信息
    QList<DeliverObject> m_deliverObjs;

    QString m_timestamp;
    QTimer m_pullOrdersTimer;
    QDateTime m_dateBusiness;
    QString m_lastError;

    FmTakeaway_db::OperatorInfo m_operator;

    int     m_retry_cnt;
    int     m_retry_max;

private slots:
    //
//    void onRecvReply(const Socket::RequstType type, const QJsonObject &json);
    void onRecvReply(const Socket::RequstType type, const QByteArray &json);
    void onError(int socketError, const QString &message);
    void onPullOrdersError(int socketError, const QString &message);
    void onPullOrders();
    void onPullDeliversError(int socketError, const QString &message);

signals:
    void sucessful(const QString& msg, const QString &extra = QString());
    void error(const QString &msg,BillsManger::ErrorType type=BillsManger::SERVER);
    void pullOrdersError(const QString &msg,BillsManger::ErrorType type=BillsManger::SERVER);

    void pullDeliversSucessful(const QString &msg);
    void pullDeliversError(const QString &msg,BillsManger::ErrorType type=BillsManger::SERVER);
    void OrderTableChanged(int last, int curr, OrderObject *orderObj);

    // 写销售单
    void sWriteBill(OrderObject const *orderObject);
    // 撤销销售单
    void sRefundBill(const QString& orderId);

    void ChangeUiStatus(QString text);
    void CLearTable();
};

#endif // BILLMANGER_H
