/********************
 * 流程控制
 * *****************/

#ifndef FLOWCONTROL_H
#define FLOWCONTROL_H

//#include <QObject>
#include "Network/billSocket.h"
#include "Model/orderObject.h"
#include "Model/dishesObject.h"
#include "LocalServer/loaclHttpServer.h"
#include "alertForm.h"
#include <QMap>
#include <JQHttpServer.h>
#include <QMutex>
#include <QDateTime>
#include <QJsonArray>
#include <QTimer>
#include <QPair>
#include <QSemaphore>

class FlowControl : public QObject
{
    Q_OBJECT
public:
    static FlowControl& GetInstance();

    /* 功能:获取收银员ID
     * 参数:NULL
     * 返回:是否成功
     * */
    QString _GetCashierId();


    /* 功能:获取收银员Name
     * 参数:NULL
     * 返回:是否成功
     * */
    QString _GetCashierName();

    /* 功能:判断SIM有效订单队列list 是否为空；
     * 参数:NULL
     * 返回:SIM有效订单队列是否为空;
     * */
    bool _SimValidOrdersListIsEmpty();

    //QStringList& _GetSimValidOrdersList();

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

    typedef struct TOPULL_ORDER
    {
        int pageSize;
        int pageNumber;
        QString channel;
        QString orderId;
    }PullOrderInfo;

    typedef struct ORDER_OPERATION
    {
        int operation;//1:接单,0:取消订单
        int result;//1:成功,0:失败
        QString orderId;

    }OrderOperation;

    //存放向OMS汇报的结构体: 订单入机POS的情况;
    typedef struct REPORTOMS_ORDERRECORD
    {
        QString orderNo;  //订单号
        QString type;     //订单状态:[3:正向单；6:退货单; 9:POS机系统级别错误; 0:未知订单状态]
        QString status;   //订单入机状态:[1:成功; 2:失败]
        QString opUser;   //当前收银员;
        QString recordDate; //入机成功、入机失败的时间[时间格式: 2018-10-09 10:41:22]
        QString storeId;    //门店编号
        QString remark;     //备注:入机出错信息
        QString checkNo;    //小票号:入机成功时的小票号;
        int     reqResult;    //向OMS请求汇报结果;
    }RepOMSRecordOrderInfo;

private:
    // 门店信息
    QString m_storeId;
    QString m_password;
    QString m_posId;
    QString m_cashierId;
    QString m_cashierName;
    QDateTime m_bDate;
    QString m_storeName;
    int m_orderCount;
    //订单清除定时器
    QTimer *m_clearTimer;
    QTimer *m_heartTimer;
    QTimer *m_pullTimer;
    QTimer *m_reportOMSReocrdOrderTimer;
    QTimer *m_loginTimer;
    QTimer *m_notifySimPullTimer;
    QTimer *m_remindCasherBlinkFloatTimer;  //插件程序收到外卖订单后，需要一致提醒店员[直到此外卖订单被全部录入到POS系统]
    // 网络通信
    BillSocket *m_loginSocket;
    BillSocket *m_pullOrderSocket;
    BillSocket *m_reportOMSRecordOrderSocket;
    BillSocket *m_pullOrderListSocket;
    BillSocket *m_procOrderSocket;
    BillSocket *m_pullDishesSocket;
    // FM外卖插件维护的有效订单容器
    QMap<QString, OrderObject*> m_FmOrdersMap;
    // 是否第一次获取到门店信息
    bool m_bFirstRecvInfo;
    bool m_bLoginResult;
    bool m_bOperateResult;
    // 标记目前悬浮框是否 锁住状态[false:悬浮框解锁状态; true:悬浮框锁住状态]；
    bool m_bFloatFromLockSt;
    // HttpServer
    //JQHttpServer::TcpServerManage* m_tcpServerManage;
    LoaclHttpServer* loaclHttpServer;

    QMap<QString,  QMultiMap<QString, dishesObject> >m_dishesMap;
    //等待Simphony拉取的有效订单队列list[orderId]
    QStringList m_simValidOrdersList;
    //订单号与pos短号映射:[可能同时存在两种状态:1:新单记录；2:退单记录；但是小票号就存一个;]
    QMap<QString,QString> m_orderIdToPosCheckNoMap;
    //记录当前订单操作
    QMap<QString, int> m_orderOperatePair;
    //订单拉取记录
    QList<PullOrderInfo*> m_orderPullList;
    QMutex m_PullOrderDataMutex;

    //向OMS汇报订单的POS入机情况 队列;
    QList<RepOMSRecordOrderInfo*> m_orderRecordRepOMSList;
    QMutex m_RepOMSRecordOrderMutex;

    //订单操作互斥信号
    //QSemaphore semaphore;
    QMutex m_OrderEntryMutex;

    //插件订单创造新订单，订单数据解析时，必须加锁，防止订单对象的数据被窜改;
    //QMutex m_UpdateOrderObjMutex;

    //新增三个bool变量用来标识 程序初始化时，两个数据库中的三张表是否能够连接正常；
    bool m_initSimProcOrderDBRet;
    bool m_initPrintSumBillPosDBRet;
    bool m_initGetAuthPosDBRet;

signals:
    // 发送信号给自己 做登陆
    void doLogin();

    /* 功能:隐藏通知窗口
     * 参数:NULL
     * 返回:NULL
     * */
    void hideAlert();
    /* 功能:显示通知窗口
     * 参数:[1]窗口类型[2]显示信息
     * 返回:NULL
     * */
    void showAlert(AlertForm::Type type, const QString& msg);

    /* 功能:隐藏主界面显示悬浮窗口
     * 参数:[1]窗口类型[2]显示信息
     * 返回:NULL
     * */
    void doHideMainShowFloatFrom();

    /* 功能:通知 锁住 悬浮窗
     * 参数:NULL
     * 返回:NULL
     * */
    void doLockFloatForm();

    /* 功能:通知 解锁 悬浮窗
     * 参数:NULL
     * 返回:NULL
     * */
    void doUnLockFloatFrom();

    /* 功能:通知 更新门店 开店/关店 状态;
     * 参数:1 [true:开店; false:关店]
     * 返回:Null
     * */
    void doUpdateStoreStatus(bool flag);


    /* 功能:设置主界面门店信息
     * 参数:[1]门店号
     * 返回:NULL
     * */
    void setStoreInfo(const QString& storeId);
    /* 功能:设置主界收银员信息
     * 参数:[1]收银员信息
     * 返回:NULL
     * */
    void setCashierInfo(const QString& cashierInfo);
    /* 功能:设置门店营业状态
     * 参数:[1]营业状态
     * 返回:NULL
     * */
    void setOpeStatus(const QString& status);
    /* 功能:设置门店网络状态
     * 参数:[1]网络状态
     * 返回:NULL
     * */
    void setNetStatus(const QString& status);

    /* 功能:更改订单显示表
     * 参数:[1]订单对象[2]旧订单的状态
     * 返回:NULL
     * */
    void changeOrderStatus(OrderObject* orderObject, int oldStatus=-100);

    /* 功能:显示订单详情界面
     * 参数:[1]收银员信息
     * 返回:NULL
     * */
    void showOrderDetails(OrderObject* orderObject);
    /* 功能:显示订单搜索结果
     * 参数:[1]搜索结果
     * 返回:NULL
     * */
    void showSearchOrderResult(const QMap<QString,QString>& orderMap);

    // 通知菜品管理界面初始化菜品信息
    void iniDishesData(QMap< QString, QMultiMap<QString, dishesObject> >);

    // 通知门店营业管理界面初始化信息
    void initChannelsData(QStringList);


    // 通知菜品管理界面操作成功刷新界面 [1]菜品所属分类 [2]具体菜品
    void processDishiesSuccssful(QString, QMap<QString, int>);

    // 通知营业状态管理界面操作成功
    void setStoreOperatingStatusFinsh(QString);

    /* 功能:通知界面清空订单
     * 参数:[1]订单号[2]订单状态
     * 返回:NULL
     * */
    void clearorder(const QString& orderId,const int& oldstatus);
    /* 功能:通知界面展示日结
     * 参数:[1]日结数据JSON
     * 返回:NULL
     * */
    void showDailyReportData(QJsonObject);


    /* 功能:通知开始提醒
     * 参数:[1]提醒类型
     * 返回:NULL
     * */
    void startRemind(int);

    void setStoreStatusChanged(QJsonArray);

    void doConfirmOrder(const QString& orderId);
    void doRefundOrder(const QString& orderId, int reasonCode, const QString &reason, const QString & dishesListString);
    void doStartOperateTimer();

private slots:
    bool _GetStoreInfo();
    /* 功能:登录
     * 参数:NULL
     * 返回:是否成功
     * */
    bool _Login();
    /* 功能:拉取订单
     * 参数:[1]订单编号
     * 返回:是否成功
     * */
    void _PullOrderData();
    /* 功能:拉取指定订单
     * 参数:[1]订单编号
     * 返回:是否成功
     * */
    bool _PullOrderDetail(const QString &orderId);
    /* 功能:拉取订单
     * 参数:NULL
     * 返回:是否成功
     * */
    bool _PullOrderList(const int &pageSize, const int &pageNo);
    /* 功能:发送心跳
     * 参数:NULL
     * 返回:是否成功
     * */
    bool _SendHeart();
    /* 功能:确认订单
     * 参数:[1]订单编号[2]配送员信息
     * 返回:是否成功
     * */
    bool _ConfirmOrder(const QString& orderId);
    /* 功能:拒绝订单
     * 参数:[1]订单编号[2]拒单原因
     * 返回:是否成功
     * */
    bool _RefuseOrder(const QString& orderId, int refuseCode, const QString reason);
    /* 功能:送出订单
     * 参数:[1]订单编号
     * 返回:是否成功
     * */
    bool _SendOrder(const QString& orderId);
    /* 功能:完成订单
     * 参数:NULL
     * 返回:是否成功
     * */
    bool _CompleteOrder(const QString& orderId);
    /* 功能:拒绝退单
     * 参数:NULL
     * 返回:是否成功
     * */
    bool _RefuseRefund(const QString& orderId);
    /* 功能:退单
     * 参数:NULL
     * 返回:是否成功
     * */
    bool _RefundOrder(const QString& orderId, int reasonCode, const QString &reason,const QString& dishesListString);

    /* 功能:定时触发向OMS 汇报本地POS订单的入机情况;
     * 参数:NULL
     * 返回:NULL
     * */
    void _ReportOMSRecordOrderInfo();

    /* 功能:获取Json对象的字符
     * 参数:NULL
     * 返回:Json字符串
     * */
    QString _GetJsonStr(const QJsonObject& json);
    /* 功能:获取Http返回Json数据
     * 参数:NULL
     * 返回:Json对象
     * */
    //QJsonObject _PackHttpReplyJson(const int status, const QString& msg, const QJsonObject& data, const int &iscontinue);
    /**
    *功能:定时清空订单Map里两天前的订单
    *参数:无
    *返回:无
    **/
    void _CrondClearExpireOrder();

    // 单位转换
    QString _Penny2Dollar(int penny);

    QString _GetIpAddress();
    void _AddOrderPull(const QString& orderId=0,const QString& channel=0,const int& pageNumber=1,const int& pageSize=100);
    // 避免获取较多历史订单的同时，OMS又有推单过来，导致死锁;
    bool _TryAddOrderPull(const QString &orderId=0, const QString &channel=0, const int &pageNumber=1, const int &pageSize=100);

    //点击屏幕指定区域
    void _ClickOMSAssignArea();
    void _ClickToLogin();
    void _ClickToNotifySimPullOrder();
    void _RemindCasherBlinkFloatForm();
    void _OrderAnalysis(const QJsonObject &jsonObject);



public slots:
    /* 功能:获取到新的门店信息
     * 参数:[1]操作员ID[2]POS机ID
     *      [3]门店ID[4]营业日
     * 返回:NULL
     * */
    void onGetNewStoreInfo();
    /* 功能:处理订单
     * 参数:[1]操作动作名[2]订单编号[3]配送员姓名
     * 返回:NULL
     * */
    void onProcessOrder(const QString& operation, const QString& orderId);
    /* 功能:获取订单详情
     * 参数:NULL
     * 返回:NULL
     * */
    void onGetOrderDetails(const QString &orderId);
    /* 功能:搜索订单
     * 参数:[1]搜索内容
     * 返回:NULL
     * */
    void onSerachOrder(const QString& text);
    void onProcessRejectOrder(const QString& orderId, const int& reasonCode,const QString &reason);
    void onProcessRepealOrder(const QString& orderId, const int& reasonCode,const QString &reason,const QString& dishesListString);

    /* 功能:获取门店营业状态
     * 参数:NULL
     * 返回:NULL
     * */
    void onGetBusinessStatus();
    /* 功能:获取菜品信息
     * 参数:NULL
     * 返回:NULL
     * */
    void onPullDishes();
    /* 功能:获取菜品信息
     * 参数:NULL
     * 返回:NULL
     * */
    void onUpdDishes(QString channelCode, QMap<QString, int> dishes);

    /* 功能:获取菜品信息
     * 参数:NULL
     * 返回:NULL
     * */
    void onUpdDishesForRef(QString channelCode, QMap<QString, int> dishes);
    /* 功能:设置门店营业状态
     * 参数:NULL
     * 返回:NULL
     * */
    void onSetStoreOperatingStatus(const QString& channelCode, const QString& channelName,int business_status);
    /* 功能:向服务端获取日结数据
     * 参数:NULL
     * 返回:NULL
     * */
    void onDailyReport();


    /* 功能:获取Http返回Json数据
     * 参数:NULL
     * 返回:Json对象
     * */
    QJsonObject _PackHttpReplyJson(const int status, const QString& msg, const QJsonObject& data, const int &iscontinue);

    /**
    *功能:FM外卖插件为响应Simphony请求准备返回数据
    *参数:1、请求json参数；2、准备返回请求数据的Buff；3、返回错误信息；
    *返回:是否准备成功；
    **/
    bool _ResponseHttpRequest(const QJsonObject &content, QJsonObject &data,QString &error);

    /**
    *功能:FM外卖插件为响应Simphony请求[action:01 -> 拉取订单]准备返回数据
    *参数:1、请求json参数；2、准备返回请求数据的Buff；3、返回错误信息；
    *返回:是否准备成功；
    **/
    bool _ResponseSimphony01Request(const QJsonObject &content, QJsonObject &data,QString &error);

    /**
    *功能:FM外卖插件为响应Simphony请求[action:02 -> 确认订单]准备返回数据
    *参数:1、请求json参数；2、准备返回请求数据的Buff；3、返回错误信息；
    *返回:是否准备成功；
    **/
    bool _ResponseSimphony02Request(const QJsonObject &content, QJsonObject &data,QString &error);

    /**
    *功能:FM外卖插件为响应Simphony请求[action:03 -> 取消订单]准备返回数据
    *参数:1、请求json参数；2、准备返回请求数据的Buff；3、返回错误信息；
    *返回:是否准备成功；
    **/
    bool _ResponseSimphony03Request(const QJsonObject &content, QJsonObject &data,QString &error);

    /**
    *功能:FM外卖插件为响应Simphony请求[action:04 -> 汇报订单Sim/POS产生的小票号]准备返回数据
    *参数:1、请求json参数；2、准备返回请求数据的Buff；3、返回错误信息；
    *返回:是否准备成功；
    **/
    bool _ResponseSimphony04Request(const QJsonObject &content, QJsonObject &data,QString &error);

    /**
    *功能:FM外卖插件为响应Simphony请求[action:05 -> simphony更新订单数据到POS本地数据库以以便POS打印小票及汇总单信息]准备返回数据
    *参数:1、请求json参数；2、准备返回请求数据的Buff；3、返回错误信息；
    *返回:是否准备成功；
    **/
    bool _ResponseSimphony05Request(const QJsonObject &content, QJsonObject &data,QString &error);


    /**
    *功能:FM外卖插件为响应Simphony请求[action:06 -> simphony汇报SIM录单异常]准备返回数据
    *参数:1、请求json参数；2、准备返回请求数据的Buff；3、返回错误信息；
    *返回:是否准备成功；
    **/
    bool _ResponseSimphony06Request(const QJsonObject &content, QJsonObject &data,QString &error);


    /**
    *功能:FM外卖插件为响应Simphony请求[action:11 -> Sim/POS推送订单到FM插件]准备返回数据
    *参数:1、请求json参数；2、准备返回请求数据的Buff；3、返回错误信息；
    *返回:是否准备成功；
    **/
    bool _ResponseOMS11Request(const QJsonObject &content, QJsonObject &data,QString &error);

    /**
    *功能:FM外卖插件为响应OMS推送门店状态 请求[action:12 -> OMS->POS推送门店营业状态]准备返回数据
    *参数:1、请求json参数；2、准备返回请求数据的Buff；3、返回错误信息；
    *返回:是否准备成功；
    **/
    bool _ResponseOMS12Request(const QJsonObject &content, QJsonObject &data,QString &error);


    /**
    *功能:FM外卖插件为响应盒马生鲜 推订单请求[action:21]准备返回数据
    *参数:1、请求json参数；2、准备返回请求数据的Buff；3、返回错误信息；
    *返回:是否准备成功；
    **/
    bool _ResponseHM21Request(const QJsonObject &content, QJsonObject &data,QString &error);

    /**
    *功能:FM外卖插件响应Simphony请求时，如果外卖插件未登录则进行登陆；
    *参数:1、请求json参数；2、返回错误信息；
    *返回:是否登陆成功；
    **/
    bool _ResponseSimReqTryLogin(const QJsonObject &content, QString &error);

    /**
    *功能:FM外卖插件为响应Simphony请求[查询FM插件第一条订单数据作为返回数据]准备返回数据
    *参数:1、请求json参数；2、准备返回请求数据的Buff；3、返回错误信息；
    *返回:是否准备成功；
    **/
    bool _ResponseSimReqFristOrderData(const QJsonObject &content,QJsonObject &data,QString &error, const QString &orderId);

};

#endif // FLOWCONTROL_H
