#include "wbillcontrol.h"
#include <QtSql/QSqlError>
#include <QtSql/QSqlQuery>
#include <QVariant>
#include <QDebug>
#include <QSettings>
#include <QNetworkAccessManager>
#include <QNetworkReply>
#include <QJsonObject>
#include <QJsonDocument>
#include <QEventLoop>
#include <QTimer>
#include <QJsonArray>
#include <QDataStream>
#include <QCryptographicHash>
#include <QThread>
#include <QMapIterator>
#include <QTcpSocket>
#include <iconv.h>
#include <errno.h>
#include <stdio.h>
#include <QTextCodec>
#include "QsLog.h"
#include "Util/IniDataManger.h"
#include "DClasses/Database.h"
#include "BillsManger.h"
#include "pos_print.h"

QThread g_thread;

WBillControl &WBillControl::GetInstance()
{
    static WBillControl wbc;
    return wbc;
}

WBillControl::WBillControl()
{
    this->moveToThread(&g_thread);
    g_thread.start();
    GetPosMenu();
    //test print
//    OrderObject obj;
//    obj.channelName="美团外卖";
//    obj.order_id="3014384743591261407";
//    obj.address="上海金巢铂瑞阁公寓合宝路18号金巢大厦金巢铂瑞阁公寓1116室";
//    obj.customer="钱多多";
//    obj.phone="15600833522";
//    obj.order_index=1;
//    obj.package_fee=600;
//    obj.send_fee=500;
//    obj.discount_fee=1300;
//    obj.user_fee=14701;
//    obj.channel="mtwm";
//    obj.pay_type="在线支付";
//    obj.product_fee=10000;
//    obj.service_fee=1000;
//    obj.dis_shop_fee=1300;
//    obj.create_time=1508640524;
//    obj.remark="4套餐具";
//    ComdObject comd1;
//    comd1.pid="001101";
//    comd1.productAmount=4;
//    comd1.price=123;
//    obj.proList.push_back(&comd1);
//    ComdObject comd2;
//    comd2.pid="006114";
//    comd2.productAmount=1;
//    comd2.price=45678;
//    obj.proList.push_back(&comd2);
//    ComdObject comd3;
//    comd3.pid="009091";
//    comd3.productAmount=1;
//    comd3.price=789;
//    obj.proList.push_back(&comd3);
    //PrintLable(&obj);

    //printMenu(&obj);
    //printTakeout(&obj);
   // printBill(&obj);
    //printCook(&obj,"061301",4);
}

WBillControl::~WBillControl()
{
    g_thread.quit();
    g_thread.wait();
}

void WBillControl::SetRemoteInfo(const QString &url)
{
    m_host = url;
}

void WBillControl::SetStoreInfo(const QString &partner_id, const QString &storeId, const QString &operaId, const QString &posId, const QString &dbusiness)
{
    QLOG_TRACE() << "WBillControl::SetStoreInfo" <<partner_id<< storeId << operaId << posId << dbusiness;
    QLOG_TRACE() << "WBillControl::SetStoreInfo" << QThread::currentThreadId();
    m_partner_id = partner_id;
    m_storeId = storeId;
    m_operatorId = operaId;
    m_posId = posId;
    m_dbusiness = dbusiness;
}

void WBillControl::DoOrderEntry(const OrderObject *orderObject)
{
    int iPosOrderStatus=0;
    QString orderId;
    QTcpSocket *socket = new QTcpSocket(this);
    // 连接
    QByteArray byteSlip=GetOrderEntryData(orderObject, false);
    QLOG_INFO() << "write order:"<<byteSlip.data();
    QLOG_INFO() << "ip:"<<IniDataManger::Instance().GetPOSServerIP();
    socket->connectToHost(IniDataManger::Instance().GetPOSServerIP(), 23772);
    if (socket->waitForConnected())
    {
        if(SendToMonitor(byteSlip,socket)){
            // 接收返回
            if (socket->waitForReadyRead())
            {
                QJsonObject recvJson =  QJsonDocument::fromJson(socket->readAll()).object();
                QLOG_INFO() <<"write order back:"<< recvJson;
                bool res=1;
                orderId=recvJson["orderid"].toString();
                iPosOrderStatus=recvJson["statusCode"].toInt();
                if(101==iPosOrderStatus)
                {
                    res=0;
                    QLOG_INFO() << "write order failed:" << recvJson["msg"].toString();
                }
                QString sql = QString("update %1 set products_fee=%2,service_fee=%3,dis_shop_fee=%4,pos_order_id='%5',isPosOK=%6 where fm_id='%7';")
                        .arg(Database::getInstance().GetInfoTableName())
                        .arg(orderObject->product_fee).arg(orderObject->service_fee).arg(orderObject->dis_shop_fee).arg(orderId).arg(res).arg(orderObject->fm_id);
                if(Database::getInstance().execSql(sql)){
                    emit sUpdatePosRes(orderObject);
                }

            }
        }
    }
    socket->close();
    //102 订单已存在
    if(102!=iPosOrderStatus){
        QLOG_INFO() << "开始打印小票";
        //打印小票
        PrintLable(orderObject,orderId);
    }
}

void WBillControl::RefundOrder(const QString &fmId)
{
    QTcpSocket *socket = new QTcpSocket(this);
    // 连接
    QByteArray byteSlip=GetRefundOrderData(fmId);
    QLOG_INFO() << "refund order:"<<byteSlip.data();

    //socket->connectToHost("127.0.0.1", 23772);
    socket->connectToHost(IniDataManger::Instance().GetPOSServerIP(), 23772);
    if (socket->waitForConnected())
    {
        if(SendToMonitor(byteSlip,socket)){
            // 接收返回
            if (socket->waitForReadyRead())
            {
                QJsonObject recvJson =  QJsonDocument::fromJson(socket->readAll()).object();
                QLOG_INFO() << "refund order back:"<<recvJson;
                bool res=1;
                if(recvJson["statusCode"].toInt()==101)
                {
                    res=0;
                    QLOG_INFO() << "write order failed:" << recvJson["msg"].toString();
                }
                QString sql = QString("update %1 set isPosRefundOK=%2 where fm_id='%3';")
                        .arg(Database::getInstance().GetInfoTableName()).arg(res).arg(fmId);
                Database::getInstance().execSql(sql);
            }
        }
    }
    socket->close();
}

QByteArray WBillControl::GetOrderEntryData(const OrderObject *orderObject, bool bVerify)
{
    QJsonObject rObj, cObj;
    if(bVerify)
    {
        rObj.insert("fm_cmd", "put_order_check");
    }else
    {
        rObj.insert("fm_cmd", "put_order");
    }

    rObj.insert("fm_ver", "1.0");

    cObj.insert("pay_id", "002");
    cObj.insert("pay_str", QString("非码外卖"));
    cObj.insert("pay_ebcode", orderObject->channel);
    cObj.insert("pay_ebcode_str", orderObject->channelName);
    cObj.insert("shop_fee", orderObject->shop_fee);
    cObj.insert("service_fee", orderObject->service_fee);
    cObj.insert("products_fee", orderObject->product_fee);
    cObj.insert("discount_fee", orderObject->discount_fee);
    cObj.insert("dis_shop_fee", orderObject->dis_shop_fee);
    cObj.insert("send_fee", orderObject->send_fee);
    cObj.insert("package_fee", orderObject->package_fee);
    cObj.insert("invoice_amount", 0);
    cObj.insert("paid_trans_id", orderObject->order_id);
    cObj.insert("fm_id", orderObject->fm_id);
    cObj.insert("customer_address", orderObject->address);
    cObj.insert("customer_name", orderObject->customer);
    cObj.insert("customer_phone", orderObject->phone);
    cObj.insert("delivery_time", orderObject->delivery_time);
    cObj.insert("order_index", orderObject->order_index);
    cObj.insert("remark", orderObject->remark);
    cObj.insert("dis_platform_fee", 0);

    rObj.insert("pay_id", cObj);

    QJsonArray tAry;
    for(int i=0; i < orderObject->pvm.keys().count(); i++)
    {

        QJsonObject tObj;
        tObj.insert("consume_num", orderObject->proList.at(i)->productAmount);
        tObj.insert("pid", orderObject->proList.at(i)->pid);
        tObj.insert("original_price", orderObject->proList.at(i)->price);
        tAry.insert(i, tObj);
    }
    rObj.insert("products", tAry);

    qDebug() << rObj;
    QJsonDocument doc(rObj);
    QString strArray = QString(doc.toJson( QJsonDocument::Compact));
    return strArray.toUtf8();
}

QByteArray WBillControl::GetRefundOrderData(const QString &fmId)
{
    QJsonObject rObj;
    rObj.insert("fm_cmd", "refund_order");
    rObj.insert("fm_ver", "1.0");
    rObj.insert("fm_id", fmId);

     qDebug() << "退款数据" << rObj;
    QJsonDocument doc(rObj);
    QString strArray = QString(doc.toJson( QJsonDocument::Compact));
    return strArray.toUtf8();
}

bool WBillControl::SendToMonitor(const QByteArray &data,QTcpSocket *pSocket)
{
    bool result=true;
    //QTcpSocket client;

    int jsonLength=data.length();
    char* m_pFmPackage = new char[jsonLength + sizeof(FMSOCKEHEADER)];
    FMSOCKEHEADER header = { 0, 0, 0 };
    header.flag = 0x4d46;
    header.len = jsonLength;
    header.ver = 0x1;

    memcpy(m_pFmPackage, &header, sizeof(FMSOCKEHEADER));
    memcpy(m_pFmPackage+sizeof(FMSOCKEHEADER), data, jsonLength);


    int toSendLength = jsonLength + sizeof(FMSOCKEHEADER);
    int curSendLength = 0;

    while(curSendLength < toSendLength)
    {
        int rlt= pSocket->write(m_pFmPackage+curSendLength,toSendLength - curSendLength);
        pSocket->waitForBytesWritten();
        if(rlt==-1){
            QLOG_ERROR() << QString::fromLocal8Bit("发送数据失败：") << data;
            result=false;
            break;
        }
        curSendLength += rlt;
    }

    delete[] m_pFmPackage;
    return result;
}

void WBillControl::GetPosMenu()
{
    QTcpSocket *socket = new QTcpSocket(this);
    // 连接
    QJsonObject rObj;
    rObj.insert("fm_cmd", "get_menu");
    rObj.insert("fm_ver", "1.0");
    QJsonDocument doc(rObj);

    QByteArray byteSlip=QString(doc.toJson( QJsonDocument::Compact)).toUtf8();
    QLOG_INFO() << "------------------------------get_menu:"<<byteSlip.data();

    socket->connectToHost(IniDataManger::Instance().GetPOSServerIP(), 23772);
    if (socket->waitForConnected())
    {
        if(SendToMonitor(byteSlip,socket)){
            // 接收返回
            bool flag=true;
            QByteArray arr;
            while(flag){
                if (socket->waitForReadyRead())
                {
                    arr.push_back(socket->readAll());
                    QJsonObject recvJson =  QJsonDocument::fromJson(arr).object();
                    if(!recvJson.isEmpty())
                        flag=false;
                }
            }
           // QLOG_INFO() << "------------------------------menu json:"<<arr.data();
            setMenu(arr);
        }
    }
    socket->close();
}

void WBillControl::setMenu(const QByteArray &JsonMenu)
{
    //QMap<QString,QVector<SetMenuItem>> mapSetMenu;
    vecMenu.clear();
    mapSetMenu.clear();
    QJsonObject recvJson =  QJsonDocument::fromJson(JsonMenu).object();
    QJsonArray orders = recvJson["MenuList"].toArray();
    PrinterMenu menu;
    foreach (QJsonValue order, orders) {
       QJsonObject orderObj = order.toObject();
       menu.strMenuId = orderObj["strMenuId"].toString();
       menu.strMenuName = orderObj["strMenuName"].toString();
       menu.iPrinterId = orderObj["iPrinterId"].toInt();
       menu.strDevice = orderObj["strDevice"].toString();

       menu.iBaud = orderObj["iBaud"].toInt();
       menu.strTitle = orderObj["strTitle"].toString();
       menu.iOrderPrinterId = orderObj["iOrderPrinterId"].toInt();
       menu.strOrderDevice = orderObj["strOrderDevice"].toString();
       menu.iOrderBaud = orderObj["iOrderBaud"].toInt();
       menu.strOrderTitle = orderObj["strOrderTitle"].toString();
       vecMenu.push_back(menu);
    }

    QJsonArray arrySetMenuList = recvJson["SetMenuMap"].toArray();
    foreach (QJsonValue order, arrySetMenuList){
        QJsonObject orderObj = order.toObject();
        QString setMenuId = orderObj["strSetMenuId"].toString();

        QVector<SetMenuItem> vecItem;
        QJsonArray arrayItems = orderObj["arrayItems"].toArray();
        foreach (QJsonValue orderItem, arrayItems){
            SetMenuItem item;
            QJsonObject objItem = orderItem.toObject();
            item.strMenuId = objItem["strMenuId"].toString();
            item.num = objItem["iNum"].toInt();
            vecItem.push_back(item);
        }
        mapSetMenu.insert(setMenuId,vecItem);
    }
}

void WBillControl::PrintLable(const OrderObject *obj,const QString posOrderId)
{
    //外卖单打印
    printTakeout(obj,posOrderId);
    //上菜单打印
    printMenu(obj,posOrderId);
    //收银单打印
    printBill(obj,posOrderId);
    //厨房单打印
    for(int i=0; i < obj->proList.size(); i++)
    {
        QString pid=obj->proList.at(i)->pid;
        int num = obj->proList.at(i)->productAmount;
        QMap<QString,QVector<SetMenuItem>>::ConstIterator it;
        it = mapSetMenu.find(pid);
        if(it!=mapSetMenu.end()){
            QLOG_INFO() << "------ setmenu pid:"<<pid;
            QVector<SetMenuItem> vecItem = it.value();
            for(SetMenuItem item:vecItem){
                QLOG_INFO() << "------ child menu id:"<<item.strMenuId;
                printCook(obj,item.strMenuId,item.num,posOrderId);
            }
        }
        else{
            QLOG_INFO() << "------ menu pid:"<<pid;
            printCook(obj,pid,num,posOrderId);
        }
    }
    updatePosPrintCount(posOrderId);
}

void WBillControl::updatePosPrintCount(const QString &posOrderId)
{
    QJsonObject rObj;
    rObj.insert("fm_cmd", "update_count");
    rObj.insert("order_id", posOrderId);

    qDebug() << "更新Pos打印计数" << rObj;

    QJsonDocument doc(rObj);
    QByteArray strArray = doc.toJson( QJsonDocument::Compact);
    QLOG_INFO() << "------ json string:"<<strArray;
    sendToPrintServer(strArray);
}

//厨房单打印
void WBillControl::printCook(const OrderObject *obj,const QString& menuId,int num,const QString &posOrderId,bool bJump)
{
    for(PrinterMenu menu:vecMenu){
        if(menu.strMenuId==menuId){
            //print
            QJsonObject rObj;
            rObj.insert("fm_cmd", "print_lable");
            rObj.insert("order_id", posOrderId);

            //不是打印跳转
            if(!bJump){
                rObj.insert("device", menu.strDevice.toStdString().data());
                rObj.insert("baud", menu.iBaud);
                //rObj.insert("device", "/dev/ttyM2");
                //rObj.insert("baud", 9600);
            }
            else{
                rObj.insert("device", menu.strOrderDevice.toStdString().data());
                rObj.insert("baud", menu.iOrderBaud);
                //rObj.insert("device", "/dev/ttyS1");
                //rObj.insert("baud", 9600);
            }


            QJsonArray tAry;
            QJsonObject tObj;

            //QByteArray str=menu.strTitle.toUtf8();
            //tObj.insert("text", menu.strTitle.toLatin1().data());

            tObj.insert("text", QTextCodec::codecForName("GBK")->toUnicode(menu.strTitle.toLatin1()));
            tObj.insert("type", 3);
            tAry.insert(0, tObj);

            QString strDesk="   台号：";
            strDesk+=obj->channelName;
            strDesk+=QString::number(obj->order_index);
            tObj.insert("text", strDesk);
            tObj.insert("type", 8);
            tAry.insert(1, tObj);

            QString order="单据:";
            order+=obj->order_id;
            tObj.insert("text", order);
            tObj.insert("type", 2);
            tAry.insert(2, tObj);

            QString posOrder="POS单号:";
            posOrder+=posOrderId;
            tObj.insert("text", posOrder);
            tObj.insert("type", 2);
            tAry.insert(3, tObj);

            QString datetime =QDateTime::currentDateTime().toString("日期:yyyy-MM-dd   时间:hh:mm");
            tObj.insert("text", datetime);
            tObj.insert("type", 2);
            tAry.insert(4, tObj);

            std::string stdSep="----------------------------------------";
            tObj.insert("text", stdSep.data());
            tObj.insert("type", 1);
            tAry.insert(5, tObj);

            QByteArray menuName=QString::number(num).toLatin1();
            menuName.append(" ");
            menuName.append(QTextCodec::codecForName("GBK")->toUnicode(menu.strMenuName.toLatin1()));
            tObj.insert("text", menuName.data());
            tObj.insert("type", 3);
            tAry.insert(6, tObj);

            tObj.insert("text", "");
            tObj.insert("type", 1);
            tAry.insert(7, tObj);

            tObj.insert("text", "");
            tObj.insert("type", 1);
            tAry.insert(8, tObj);

            tObj.insert("text", "");
            tObj.insert("type", 1);
            tAry.insert(9, tObj);

            tObj.insert("text", "");
            tObj.insert("type", 1);
            tAry.insert(10, tObj);

            rObj.insert("print", tAry);

            qDebug() << rObj;
            QJsonDocument doc(rObj);
            QByteArray strArray = doc.toJson( QJsonDocument::Compact);
            QLOG_INFO() << "------ json string:"<<strArray;
            QString sDateTime =QDateTime::currentDateTime().toString("  时间    :yyyy-MM-dd hh:mm:ss");
            if(!sendToPrintServer(strArray)){
                QLOG_INFO() << "打印失败，开始跳转打印";
                if(!bJump){
                    QJsonObject rObjNew;
                    rObjNew.insert("fm_cmd", "print_lable");
                    rObjNew.insert("order_id", posOrderId);
                    rObjNew.insert("device", menu.strOrderDevice.toStdString().data());
                    rObjNew.insert("baud", menu.iOrderBaud);
                    //rObjNew.insert("device", "/dev/ttyS1");
                    //rObjNew.insert("baud", 9600);

                    QJsonArray tAryNew;
                    QJsonObject tObjNew;
                    tObjNew.insert("text", "**************************************");
                    tObjNew.insert("type", 1);
                    tAryNew.insert(0, tObjNew);

                    tObjNew.insert("text", "           打印跳转");
                    tObjNew.insert("type", 5);
                    tAryNew.insert(1, tObjNew);

                    tObjNew.insert("text", "从");
                    tObjNew.insert("type", 1);
                    tAryNew.insert(2, tObjNew);

                    QString sPrinter="  打印列  :";
                    sPrinter+=QTextCodec::codecForName("GBK")->toUnicode(menu.strTitle.toLatin1());
                    tObjNew.insert("text", sPrinter);
                    tObjNew.insert("type", 1);
                    tAryNew.insert(3, tObjNew);

                    tObjNew.insert("text", sDateTime);
                    tObjNew.insert("type", 1);
                    tAryNew.insert(4, tObjNew);

                    tObjNew.insert("text", "到");
                    tObjNew.insert("type", 1);
                    tAryNew.insert(5, tObjNew);

                    QString ePrinter="  打印列  :";
                    ePrinter+=QTextCodec::codecForName("GBK")->toUnicode(menu.strOrderTitle.toLatin1());
                    tObjNew.insert("text", ePrinter);
                    tObjNew.insert("type", 1);
                    tAryNew.insert(6, tObjNew);

                    QString eDateTime =QDateTime::currentDateTime().toString("  时间    :yyyy-MM-dd hh:mm:ss");
                    tObjNew.insert("text", eDateTime);
                    tObjNew.insert("type", 1);
                    tAryNew.insert(7, tObjNew);

                    tObjNew.insert("text", "**************************************");
                    tObjNew.insert("type", 1);
                    tAryNew.insert(8, tObjNew);

                    rObjNew.insert("print", tAryNew);
                    QJsonDocument docNew(rObjNew);
                    QByteArray strArrayNew = docNew.toJson( QJsonDocument::Compact);
                    QLOG_INFO() << "------jump json string:"<<strArrayNew;
                    if(sendToPrintServer(strArrayNew)){
                        printCook(obj,menuId,num,posOrderId,true);
                    }
                    else
                    {
                        QLOG_INFO() << "------jump print failed";
                    }
                }
            }

            break;
        }
    }
}

bool WBillControl::sendToPrintServer(QByteArray &JsonPrint)
{
    bool result=false;
    QTcpSocket *socket = new QTcpSocket(this);
    // 连接
    QByteArray byteSlip=JsonPrint;
    QLOG_INFO() << "ip:"<<IniDataManger::Instance().GetPOSServerIP();
    socket->connectToHost(IniDataManger::Instance().GetPOSServerIP(), 23775);
    if (socket->waitForConnected())
    {
        if(SendToMonitor(byteSlip,socket)){
            // 接收返回
            if (socket->waitForReadyRead())
            {
                QJsonObject recvJson =  QJsonDocument::fromJson(socket->readAll()).object();
                QLOG_INFO() <<"write order back:"<< recvJson;
                if(recvJson["statusCode"].toInt()!=100)
                {
                    QLOG_INFO() << "write order failed:" << recvJson["msg"].toString();
                }
                else{
                    result=true;
                }
            }
        }
    }
    socket->close();
    return result;
}

//外卖单打印
void WBillControl::printTakeout(const OrderObject *obj,const QString &posOrderId)
{ 
#ifdef Q_OS_LINUX
    int fd=-1;
    for(int i=0; i < obj->proList.size(); i++)
    {
        QString pid=obj->proList.at(i)->pid;
        int num = obj->proList.at(i)->productAmount;
        int price =obj->proList.at(i)->price;
        for(PrinterMenu menu:vecMenu){
            if(menu.strMenuId==pid){
                //订单头  打印
                if(0==i){
                    //fd = open_port("/dev/ttyS1");
                    //set_port(fd,19200);
                    fd = open_port(IniDataManger::Instance().GetPOSLocalPrinterPort().toStdString().data());
                    if(-1==fd){
                        QLOG_ERROR() << "printTakeout open_port failed";
                        return;
                    }
                    if(!set_port(IniDataManger::Instance().GetPOSLocalPrinterBaud())){
                        QLOG_ERROR() << "printTakeout device error";
                        return;
                    }

                    QString str=getPrintTitle(obj->channel,obj->order_index);
                    std::string title = str.toStdString();
                    print(charset_u2g(title).data(),3);

                    //QString strTitle="     避风塘(金玉兰店)";
                    QString strTitle="     ";
                    strTitle+=IniDataManger::Instance().GetPOSStoreName();
                    std::string stdTitle=strTitle.toStdString();
                    print(charset_u2g(stdTitle).data(),3);
                    print("",1);

                    QString strPayType="      —";
                    strPayType+=obj->pay_type;
                    strPayType+="—";
                    std::string stdPaytype=strPayType.toStdString();
                    print(charset_u2g(stdPaytype).data(),3);
                    print("",1);

                    print("-----------------------------------------------",1);
                    QString strOrderTime= QDateTime::fromTime_t(obj->create_time).toString("下单时间:MM-dd hh:mm");
                    std::string stdOrderTime=strOrderTime.toStdString();
                    print(charset_u2g(stdOrderTime).data(),3);
                    print("-----------------------------------------------",1);
                }
                QByteArray menuName=QString("%1").arg(menu.strMenuName,-36).toLatin1();
                menuName.append("x");
                menuName.append(QString::number(num).toLatin1());
                menuName.append("  ");
                menuName.append(QString("%1").arg(QString::number(price/100.00,'f',2),6).toLatin1());
                print(menuName.data(),5);
                break;
            }
        }
    }
    if(-1!=fd){
        print("-----------------------------------------------",1);
        QString strPakage="餐盒          x1 ";
        strPakage+=QString("%1").arg(QString::number(obj->package_fee/100.00,'f',2),6);
        std::string stdPakage=strPakage.toStdString();
        print(charset_u2g(stdPakage).data(),3);
        print("-----------------------------------------------",1);
        QString strDiscount="优惠             ";
        strDiscount+=QString("%1").arg(QString::number(obj->discount_fee/100.00,'f',2),6);
        std::string stdDiscount=strDiscount.toStdString();
        print(charset_u2g(stdDiscount).data(),3);

        QString strSend="配送费           ";
        strSend+=QString("%1").arg(QString::number(obj->send_fee/100.00,'f',2),6);
        std::string stdSend=strSend.toStdString();
        print(charset_u2g(stdSend).data(),3);
        print("-----------------------------------------------",1);

        QString strUser="已付             ";
        strUser+=QString("%1").arg(QString::number(obj->user_fee/100.00,'f',2),6);
        std::string stdUser=strUser.toStdString();
        print(charset_u2g(stdUser).data(),3);
        print("-----------------------------------------------",1);

        std::string stdAddress=obj->address.toStdString();
        print(charset_u2g(stdAddress).data(),3);

        std::string stdName=obj->customer.toStdString();
        print(charset_u2g(stdName).data(),3);

        std::string stdPhone=obj->phone.toStdString();
        print(charset_u2g(stdPhone).data(),3);

        QString strId="订单号:";
        strId+=obj->order_id;
        std::string stdId=strId.toStdString();
        print(charset_u2g(stdId).data(),3);

        QString strPosId="POS单号:";
        strPosId+=posOrderId;
        std::string stdPosId=strPosId.toStdString();
        print(charset_u2g(stdPosId).data(),3);

        if(!obj->invoice_title.isEmpty()){
            QString strInvoiceTitle="发票抬头:";
            strInvoiceTitle+=obj->invoice_title;
            std::string stdInvoiceTitle=strInvoiceTitle.toStdString();
            print(charset_u2g(stdInvoiceTitle).data(),3);
        }

        QString strRemark="备注:";
        strRemark+=obj->remark;
        std::string stdRemark=strRemark.toStdString();
        print(charset_u2g(stdRemark).data(),3);

        //为空时换行
        print("",1);
        QString end="*********";
        end+=QString("%1").arg("#"+QString::number(obj->order_index),4);
        end+="完";
        end+="********";
        std::string strEnd=end.toStdString();
        print(charset_u2g(strEnd).data(),3);

        cut_paper();
        close_port();
    }
    else{
        QLOG_ERROR() <<"posOrderId:"<<posOrderId<< "printTakeout failed:"<<obj->toString();
    }
#endif
}

//上菜单打印
void WBillControl::printMenu(const OrderObject *obj,const QString &posOrderId)
{
#ifdef Q_OS_LINUX
    int fd=-1;
    for(int i=0; i < obj->proList.size(); i++)
    {
        QString pid=obj->proList.at(i)->pid;
        int num = obj->proList.at(i)->productAmount;
        for(PrinterMenu menu:vecMenu){
            if(menu.strMenuId==pid){
                //订单头  打印
                if(0==i){
                    fd = open_port(IniDataManger::Instance().GetPOSLocalPrinterPort().toStdString().data());
                    if(-1==fd){
                        QLOG_ERROR() << "printMenu open_port failed";
                        return;
                    }
                    if(!set_port(IniDataManger::Instance().GetPOSLocalPrinterBaud())){
                        QLOG_ERROR() << "printMenu device error";
                        return;
                    }

                    print(menu.strOrderTitle.toLatin1().data(),5);

                    QString strDesk="    台号：";
                    strDesk+=obj->channelName;
                    strDesk+=QString::number(obj->order_index);
                    std::string stdDesk=strDesk.toStdString();
                    print(charset_u2g(stdDesk).data(),4);

                    print("",1);
                    QString order="单据:";
                    order+=obj->order_id;
                    std::string stdOrder=order.toStdString();
                    print(charset_u2g(stdOrder).data(),1);

                    QString posOrder="POS单号:";
                    posOrder+=posOrderId;
                    std::string stdPosOrder=posOrder.toStdString();
                    print(charset_u2g(stdPosOrder).data(),1);

                    QString datetime =QDateTime::currentDateTime().toString("日期:yyyy-MM-dd   时间:hh:mm");
                    std::string stdDatetime=datetime.toStdString();
                    print(charset_u2g(stdDatetime).data(),1);
                    print("----------------------------------------",1);
                }

                QByteArray menuName=QString::number(num).toLatin1();
                menuName.append(" ");
                menuName.append(menu.strMenuName.toLatin1());
                print(menuName.data(),5);

                //如果是套餐，列出子项
                QMap<QString,QVector<SetMenuItem>>::ConstIterator it;
                it = mapSetMenu.find(pid);
                if(it!=mapSetMenu.end()){
                    QLOG_INFO() << "------ 上菜单,打印套餐子项 pid:"<<pid;
                    QVector<SetMenuItem> vecItem = it.value();
                    for(SetMenuItem item:vecItem){
                        QLOG_INFO() << "------ child menu id:"<<item.strMenuId;
                        for(PrinterMenu childMenu:vecMenu){
                            if(childMenu.strMenuId==item.strMenuId){
                                QByteArray name;
                                name.append("  ");
                                name.append(QString::number(item.num).toLatin1());
                                name.append(" ");
                                name.append(childMenu.strMenuName.toLatin1());
                                print(name.data(),5);
                            }
                        }
                    }
                }

                break;
            }

        }
    }
    if(-1!=fd){
        //为空时换行
        print("",1);
        print("",1);

        cut_paper();
        close_port();
    }
    else{
        QLOG_ERROR() << "printMenu failed";
    }
#endif
}

//收银单打印
void WBillControl::printBill(const OrderObject *obj,const QString &posOrderId)
{
#ifdef Q_OS_LINUX
    int fd=-1;
    for(int i=0; i < obj->proList.size(); i++)
    {
        QString pid=obj->proList.at(i)->pid;
        int num = obj->proList.at(i)->productAmount;
        int price = obj->proList.at(i)->price;
        for(PrinterMenu menu:vecMenu){
            if(menu.strMenuId==pid){
                //订单头  打印
                if(0==i){
                    fd = open_port(IniDataManger::Instance().GetPOSLocalPrinterPort().toStdString().data());
                    if(-1==fd){
                        QLOG_ERROR() << "printBill open_port failed";
                        return;
                    }
                    if(!set_port(IniDataManger::Instance().GetPOSLocalPrinterBaud())){
                        QLOG_ERROR() << "printBill device error";
                        return;
                    }

                    QString strTitle="         ";
                    strTitle+=IniDataManger::Instance().GetPOSStoreName();
                    std::string stdTitle=strTitle.toStdString();
                    QLOG_INFO() << "-----------print start";
                    print(charset_u2g(stdTitle).data(),5);
                    QLOG_INFO() << "-----------print end";

                    std::string stdAddress="地址:";
                    print(charset_u2g(stdAddress).data(),1);
                    std::string stdPhone="电话:";
                    print(charset_u2g(stdPhone).data(),1);
                    print("",1);

                    QString strDesk="台号：";
                    strDesk+=obj->channelName;
                    strDesk+=QString::number(obj->order_index);
                    std::string stdDesk=strDesk.toStdString();
                    print(charset_u2g(stdDesk).data(),6);
                    print("-----------------------------------------------",1);

                    QString order="单号:";
                    order+=obj->order_id;
                    std::string stdOrder=order.toStdString();
                    print(charset_u2g(stdOrder).data(),1);

                    QString posOrder="POS单号:";
                    posOrder+=posOrderId;
                    std::string stdPosOrder=posOrder.toStdString();
                    print(charset_u2g(stdPosOrder).data(),1);

                    QString datetime =QDateTime::currentDateTime().toString("日期:yyyy-MM-dd   时间:hh:mm");
                    std::string stdDatetime=datetime.toStdString();
                    print(charset_u2g(stdDatetime).data(),1);
                    print("",1);
                    std::string stdType="数量              项目                  价格";
                    print(charset_u2g(stdType).data(),1);
                    print("---- --------------------------------- --------",1);
                }
                QByteArray menuName=QString::number(num).toLatin1();
                menuName.append("   ");
                menuName.append(QString("%1").arg(menu.strMenuName,-36).toLatin1());
                menuName.append(QString("%1").arg(QString::number(price/100.00,'f',2),6).toLatin1());
                print(menuName.data(),1);
                break;
            }

        }
    }
    if(-1!=fd){
        print("-----------------------------------------------",1);
        QString strPakage="餐盒                                    ";
        strPakage+=QString("%1").arg(QString::number(obj->package_fee/100.00,'f',2),6);
        std::string stdPakage=strPakage.toStdString();
        print(charset_u2g(stdPakage).data(),1);
        print("-----------------------------------------------",1);

        QString strDisShop="商户优惠：  ";
        strDisShop+=QString("%1").arg(QString::number(obj->dis_shop_fee/100.00,'f',2),6);
        std::string stdDisShop=strDisShop.toStdString();
        print(charset_u2g(stdDisShop).data(),1);

        QString strServiceFee="平台服务费：";
        strServiceFee+=QString("%1").arg(QString::number(obj->service_fee/100.00,'f',2),6);
        std::string stdServiceFee=strServiceFee.toStdString();
        print(charset_u2g(stdServiceFee).data(),1);
        print("-----------------------------------------------",1);

        QString strTotle="商品总额：  ";
        strTotle+=QString("%1").arg(QString::number(obj->product_fee/100.00,'f',2),6);
        std::string stdTotle=strTotle.toStdString();
        print(charset_u2g(stdTotle).data(),1);

        QString strActual="应到账金额：";
        int actual=obj->product_fee-obj->service_fee-obj->dis_shop_fee;
        strActual+=QString("%1").arg(QString::number(actual/100.00,'f',2),6);
        std::string stdActual=strActual.toStdString();
        print(charset_u2g(stdActual).data(),2);

        cut_paper();
        close_port();
    }
    else{
        QLOG_ERROR() << "printMenu failed";
    }
#endif
}

QString WBillControl::getPrintTitle(const QString& channel,int index)
{
    QString title;
    if("eleme"==channel){
        title="****";
        title+=QString("%1").arg("#"+QString::number(index),4);
        title+="饿了么外卖单";
        title+="****";
    }
    else if("mtwm"==channel){
        title="*****";
        title+=QString("%1").arg("#"+QString::number(index),4);
        title+="美团外卖单";
        title+="*****";
    }
    else if("bdwm"==channel){
        title="*****";
        title+=QString("%1").arg("#"+QString::number(index),4);
        title+="百度外卖单";
        title+="*****";
    }
    else if("jdwm"==channel){
        title="******";
        title+=QString("%1").arg("#"+QString::number(index),4);
        title+="京东到家";
        title+="******";
    }
    else if("sdg"==channel){
        title="*******";
        title+=QString("%1").arg("#"+QString::number(index),4);
        title+="闪电购";
        title+="*******";
    }
    else if("fmwd"==channel){
        title="******";
        title+=QString("%1").arg("#"+QString::number(index),4);
        title+="非码微店";
        title+="******";
    }
    else if("mall"==channel){
        title="******";
        title+=QString("%1").arg("#"+QString::number(index),4);
        title+="非码Mall";
        title+="******";
    }

    return title;
}

int WBillControl::charset_convert(const char* charset_from, const char* charset_to
                    , const std::string& string_from, std::string& string_to)
{
#ifdef Q_OS_LINUX
    iconv_t cd = iconv_open(charset_to, charset_from);
    if (!cd)
    {
        return -1;
    }

    string_to = "";
    int ret = 0;
    size_t inbytes = string_from.size();
    char* inbuf = const_cast<char*>(string_from.c_str());
    while (inbytes > 0)
    {
        char buffer[1024] = {0};
        char *outbuf = buffer;
        size_t outbytes = sizeof(buffer) - 1;
        ret = iconv(cd, &inbuf, &inbytes, &outbuf, &outbytes);
        if (ret == 0 || errno == E2BIG)
        {
            string_to.append(buffer);
        }
        else
        {
            break;
        }
    }
    ret = iconv_close(cd);
    if (inbytes != 0 || ret != 0)
    {
        return -1;
    }

    return 0;
#endif
    return 0;
}

std::string WBillControl::charset_u2g(const std::string& utf8)
{
#ifdef Q_OS_LINUX
    std::string gbk;
    charset_convert("UTF-8", "GB18030//IGNORE", utf8, gbk);
    //std::cout<<"convert res:"<<i<<std::endl;
    return gbk;
#endif
    return utf8;
}
