#include "printlib.h"
#include <QFile>
#include <QCoreApplication>
#include <QDateTime>
#include <QDebug>
#include <QSettings>
#include <QDateTime>
#include <QStringList>
#include <QsLog.h>



PrintLib::PrintLib()
{
    m_b_load_sucfl =false;
    m_print_lib.setFileName("fmposdll.dll");
    if(m_print_lib.load())
    {
        f_OpenPrinter = (OpenPrinter)m_print_lib.resolve("InItConfig");
        f_PrintText = (PrintText)m_print_lib.resolve("PrintData");
        f_InitPrinter = (InitPrinter)m_print_lib.resolve("Initconfigini");
        f_ClosePrinter = (ClosePrinter)m_print_lib.resolve("Unloaddll");
        f_LaodAddress = (LoadAddress)m_print_lib.resolve("LoadAddress");
        f_PrintLine = (PrintLine)m_print_lib.resolve("PrintDataLine");
        f_PrintBarCode = (PrintBarCode)m_print_lib.resolve("PrintBarCode");
        f_PrintQRCode = (PrintQRCode)m_print_lib.resolve("PrintQRCode");
        f_FreeLine = (FreeLine)m_print_lib.resolve("FreeLine");

        f_TSCInit = (TSCInit)m_print_lib.resolve("TSCInit");
        f_TSCWinPrintln = (TSCWinPrintln)m_print_lib.resolve("TSCWinPrintln");
        f_TSCWinPrintPage = (TSCWinPrintPage)m_print_lib.resolve("TSCWinPrintPage");

    }
    qDebug()<<"dll load";
    if(f_OpenPrinter&&f_ClosePrinter&&f_LaodAddress)
    {
        qDebug()<<"dll load success";
        m_b_load_sucfl=true;
    }
}

void PrintLib::_PrintLabTest()
{
    f_TSCInit();

    f_TSCWinPrintln(10, 0, 28, 0, 2, 0, 0, "\xE5\xAE\x8B\xE4\xBD\x93", "7   09/03 09:36 1/2", 0);

    f_TSCWinPrintln(0, 0, 24, 0, 2, 2, 0, "\xE5\xAE\x8B\xE4\xBD\x93", "------------------------------", 0.0266665);

    f_TSCWinPrintln(10, 0, 32, 0, 2, 0, 0, "\xE5\xAE\x8B\xE4\xBD\x93", "big tea", 0.0666665);

    f_TSCWinPrintln(10, 0, 24, 0, 2, 2, 0, "\xE5\xAE\x8B\xE4\xBD\x93", "add sweets, add milk", 0.0666665);

    f_TSCWinPrintln(10, 0, 24, 0, 2, 2, 0, "\xE5\xAE\x8B\xE4\xBD\x93", "test store", 0.0666665);

    f_TSCWinPrintln(10, 0, 24, 0, 2, 2, 0, "\xE5\xAE\x8B\xE4\xBD\x93", "-----------------------------", 0.0266665);

    f_TSCWinPrintln(0, 0, 24, 0, 2, 0, 0, "\xE5\xAE\x8B\xE4\xBD\x93", "                freemudtest", 0);

    f_TSCWinPrintPage("1","1");
}


void PrintLib::_PrintLab( OrderObject* order)
{
    QString deliveryTime;
    QString datetime;
    if(order->delivery_time==0)
    {
        deliveryTime = QDateTime::currentDateTime().toString("hh:mm");
        datetime = QDateTime::currentDateTime().toString("MM/dd");
    }else{
        deliveryTime = QDateTime::fromTime_t(order->delivery_time).toString("hh:mm");
        datetime = QDateTime::currentDateTime().toString("MM/dd");
    }

    int allprod = 0;

    foreach(ProductObject* dish,order->proList)
    {
        allprod += dish->product_amount;
    }

    int index = 0;
    foreach(ProductObject* dish,order->proList)
    {
        int num = dish->product_amount;

        while(num > 0)
        {

            f_TSCInit();
            //qDebug() << "f_TSCInit";
            QString title = QString("%1   %2 %3 %4/%5").arg(QString::number(order->order_index), datetime, deliveryTime, QString::number(++index), QString::number(allprod));
            f_TSCWinPrintln(10,0,25,0,2,0,0,QString("\xE5\xAE\x8B\xE4\xBD\x93").toLocal8Bit().data(),title.toLocal8Bit().data(),0);
            f_TSCWinPrintln(0,0,22,0,2,0,0,QString("\xE5\xAE\x8B\xE4\xBD\x93").toLocal8Bit().data(),"-----------------------------------",0.0266666);
            f_TSCWinPrintln(10,0,30,0,2,0,0,QString("\xE5\xAE\x8B\xE4\xBD\x93").toLocal8Bit().data(),dish->name.
                            append(" ¥").
                            append(QString::number(dish->price/100.0, 'f', 2)).toLocal8Bit().data(),0.0666665);
            QString property_tags;
            if(!dish->property_tags.isEmpty())
            {
                property_tags.append(dish->property_tags);
                property_tags.append(",");
            }
            if(!dish->sub_products.isEmpty())
            {
                foreach(ProductObject* sub_dish,dish->sub_products)
                {
                    property_tags.append(sub_dish->name);
                    property_tags.append(",");
                }
            }
            property_tags.remove(property_tags.length()-1,1);
            f_TSCWinPrintln(10,0,24,0,2,2,0,QString("\xE5\xAE\x8B\xE4\xBD\x93").toLocal8Bit().data(),property_tags.toLocal8Bit().data(),0.0666665);
            f_TSCWinPrintln(10,180,26,0,2,0,0,QString("\xE5\xAE\x8B\xE4\xBD\x93").toLocal8Bit().data(),order->store_name.toLocal8Bit().data(),0.0666665);

            //qDebug() << "up f_TSCWinPrintPage";

            f_TSCWinPrintPage("1","1");

            -- num;
        }
        //qDebug() << "down f_TSCWinPrintPage";
    }
}

bool PrintLib::DoPrint(const QByteArray &content, OrderObject *orderObject, QString &error)
{
    QByteArray iniData = _GetPrintIni().toLocal8Bit();
    char inichar[2048]={0x0};
    strcpy(inichar,iniData.data());
    if(m_b_load_sucfl)
    {
        if(!f_LaodAddress())
        {
            return false;
        }
        f_InitPrinter(inichar);
        if(!f_OpenPrinter())
        {
            f_ClosePrinter();
            return false;
        }
        _order = orderObject;
        bool result;
        PrintDocument doc = PrintDocument::ParseToDocument(content, result,error);
        if(!result)
        {
            f_ClosePrinter();
            return false;
        }
        _PrintLineNode(doc,_order);

        QString confilename = qApp->applicationDirPath() + "/" + "config.ini";
        int needlabel = QSettings(confilename, QSettings::IniFormat).value("all/needlabel", 0).toInt();
        if(needlabel)
            _PrintLab(_order);

        f_ClosePrinter();
        return true;
    }
    else{
        memset(inichar,0x0,sizeof(inichar));
        return false;
    }
}

bool PrintLib::DoPrint(const QString &content, OrderObject *orderObject, QString &error)
{

    QByteArray iniData = _GetPrintIni().toLocal8Bit();
    char inichar[2048]={0x0};
    strcpy(inichar,iniData.data());
    if(m_b_load_sucfl)
    {
        if(!f_LaodAddress())
        {
            return false;
        }
        f_InitPrinter(inichar);
        if(!f_OpenPrinter())
        {
            f_ClosePrinter();
            return false;
        }
        _order = orderObject;
        bool result;
        PrintDocument doc = PrintDocument::ParseToDocument(content, result,error);
        if(!result)
        {
            f_ClosePrinter();
            return false;
        }
        _PrintLineNode(doc,_order);

        QString confilename = qApp->applicationDirPath() + "/" + "config.ini";
        int needlabel = QSettings(confilename, QSettings::IniFormat).value("all/needlabel", 0).toInt();
        if(needlabel)
            _PrintLab(_order);

        f_ClosePrinter();
        return true;
    }
    else{
        memset(inichar,0x0,sizeof(inichar));
        return false;
    }
}

bool PrintLib::OnlyDoPrint(const QString &content, OrderObject *orderObject, QString &error)
{

    QByteArray iniData = _OnlyGetPrintIni().toLocal8Bit();
    char inichar[2048]={0x0};
    strcpy(inichar,iniData.data());
    if(m_b_load_sucfl)
    {
        if(!f_LaodAddress())
        {
            return false;
        }
        f_InitPrinter(inichar);
        if(!f_OpenPrinter())
        {
            f_ClosePrinter();
            return false;
        }
        _order = orderObject;
        bool result;
        PrintDocument doc = PrintDocument::ParseToDocument(content, result,error);
        if(!result)
        {
            f_ClosePrinter();
            return false;
        }
        _PrintLineNode(doc,_order);
        //_PrintLab(_order);
        f_ClosePrinter();
        return true;
    }
    else{
        memset(inichar,0x0,sizeof(inichar));
        return false;
    }
}

bool PrintLib::DoTestPrint(QByteArray iniData, const QString &content, OrderObject *orderObject, QString &error)
{
    //QByteArray iniData = _GetPrintIni().toLocal8Bit();
    char inichar[2048]={0x0};
    strcpy(inichar,iniData.data());
    if(m_b_load_sucfl)
    {
        if(!f_LaodAddress())
        {
            return false;
        }
        f_InitPrinter(inichar);
        if(!f_OpenPrinter())
        {
            f_ClosePrinter();
            return false;
        }
        _order = orderObject;
        bool result;
        PrintDocument doc = PrintDocument::ParseToDocument(content, result,error);
        if(!result)
        {
            f_ClosePrinter();
            return false;
        }
        _PrintLineNode(doc,_order);
        //_PrintLab(_order);
        f_ClosePrinter();
        return true;
    }
    else{
        memset(inichar,0x0,sizeof(inichar));
        return false;
    }
}

bool PrintLib::DoTestLabelPrint(QByteArray iniData, OrderObject *orderObject)
{
    //QByteArray iniData = _GetPrintIni().toLocal8Bit();
    char inichar[2048]={0x0};
    strcpy(inichar,iniData.data());
    if(m_b_load_sucfl)
    {
        if(!f_LaodAddress())
        {
            return false;
        }
        f_InitPrinter(inichar);
//        if(!f_OpenPrinter())
//        {
//            f_ClosePrinter();
//            return false;
//        }
        _order = orderObject;
//        bool result;
//        PrintDocument doc = PrintDocument::ParseToDocument(content, result,error);
//        if(!result)
//        {
//            f_ClosePrinter();
//            return false;
//        }
        //_PrintLineNode(doc,_order);
        _PrintLabTest();
        //f_ClosePrinter();
        return true;
    }
    else{
        memset(inichar,0x0,sizeof(inichar));
        return false;
    }
}

//bool PrintLib::OpenPrinter()
//{
//    QByteArray iniData = _GetPrintIni().toLocal8Bit();
//    char inichar[2048]={0x0};
//    strcpy(inichar,iniData.data());
//    if(m_b_load_sucfl)
//    {
//        if(!f_LaodAddress())
//        {
//            return false;
//        }
//        f_InitPrinter(inichar);
//        if(!f_OpenPrinter())
//        {
//            f_ClosePrinter();
//            return false;
//        }
//        return true;
//    }
//    else{
//        return false;
//    }

//}

//void PrintLib::ClosePrinter()
//{
//    f_ClosePrinter();
//    return;
//}

//bool PrintLib::PrintQRCode(char data[], int type, int leftMargin, int width)
//{
//    return f_PrintQRCode(data,type,leftMargin,width);
//}

//bool PrintLib::PrintBarCode(char data[], int type, int leftMargin, int fontType, int width, int height, int position)
//{
//    return f_PrintBarCode(data,type,leftMargin,fontType,width,height,position);
//}

//bool PrintLib::PrintText(char data[], int fontType, int fontStyle, int width, int height)
//{
//    return f_PrintLine(data,fontType,fontStyle,width,height);
//}

bool PrintLib::_PrintLineNode(const PrintDocument &doc, OrderObject *orderObject)
{
    QList<int> productNodeList = doc.GetProductNodeIndex();
    QList<LineNode*> list = doc.GetNodeList();
    bool first=true;
    for(int i=0;i<list.size();i++)
    {
        if(productNodeList.contains(i))
        {
            if(first){
                first = false;
                _PrintProcudt(list,productNodeList);
            }

        }
        else
        {
            _PrintLine(*list.at(i));
        }
    }
    return first;
}

//void PrintLib::_FreeLine()
//{
//    return f_FreeLine();
//}

void PrintLib::_PrintLine(const LineNode &line, ProductObject *dish)
{
    QString text = line.text;
    QString content = line.content;
    int time = line.time;
    int printType = line.printType;
    int fontType = line.fontType;
    int fontStyle = line.fontStyle;
    int width = line.width;
    int height = line.height;
    int codeType = line.codeType;
    int position = line.position;
    int leftMargin = line.leftMargin;
    QStringList contentList;
    content.simplified();
    contentList = content.split('|');
    int i=1;
    foreach(QString value,contentList)
    {
        QStringList list;
        bool isMath = false;
        QString format;
        Calculator::SplitMath(value,list,format ,isMath );
        QString index= QString("%%1").arg(i++);
        if(!isMath){
            QVariant v;
            if(dish==0){
                 v = _order->property(value.toUtf8());
            }
            else{
                 v = dish->property(value.toUtf8());
            }
            if(time)
            {
                int delivertime = v.toInt();
                if(delivertime == 0)
                {
                    text.replace(index,QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm"));
                }else{
                    text.replace(index,QDateTime::fromTime_t(v.toInt()).toString("yyyy-MM-dd hh:mm"));
                }
            }else
            {
                text.replace(index,v.toString());
            }
        }
        else{
            int j=1;
            foreach(QString value,list)
            {
                QString index= QString("%%1").arg(QString::number(j++));
                bool ok;
                value.toInt(&ok,10);
                if(ok)
                {
                    format.replace(index,value);
                    continue;
                }
                QVariant v;
                if(dish==0){
                     v = _order->property(value.toUtf8());
                }
                else{
                     v = dish->property(value.toUtf8());
                }
                if(time)
                {
                    format.replace(index,QDateTime::fromTime_t(v.toInt()).toString("yyyy-MM-dd hh:mm"));
                }else
                {
                    format.replace(index,v.toString());
                }
            }
            format.insert(0,'(');
            format.append(')');
            float result=Calculator::parenth_final(string((const char *)format.toUtf8()));
            text.replace(index,QString::number(result));
        }
    }
    char temchar[2048]={0x0};
    strcpy(temchar,text.toLocal8Bit().data());
    if(printType==1)
    {
        f_PrintLine(temchar,fontType,fontStyle,width,height) ;
    }
    if(printType==2)
    {
        f_PrintQRCode(temchar,codeType,leftMargin,width);
    }
    if(printType==3)
    {
        f_PrintBarCode(temchar,codeType,leftMargin,fontType,width,height,position);
    }
    memset(temchar,0x0,sizeof(temchar));
}

void PrintLib::_PrintProcudt(const QList<LineNode*> &list,const QList<int>& protlist)
{
    QList<int> productNodeList = protlist;
    int firstIndex = productNodeList.first();
    int lastIndex = productNodeList.last();
    foreach (ProductObject* value, _order->proList) {
        for(int index = firstIndex;index<=lastIndex;index++) {
              _PrintLine(*list.at(index),value);
        }
    }
}

PrintLib &PrintLib::GetInstance()
{
    static PrintLib fp;
    return fp;
}

QString PrintLib::_GetPrintIni()
{
    QString path = QString("%1/printer.ini").arg(QCoreApplication::applicationDirPath());
    QSettings config(path, QSettings::IniFormat);
    QString ini;
    ini.append(config.value("Printer/Name").toString());
    ini.append("|");
    ini.append(config.value("Printer/printType").toString());
    ini.append("|");
    ini.append(config.value("Printer/PaperWidth").toString());
    ini.append("|");
    ini.append(config.value("Printer/levlel").toString());
    ini.append("|");
    ini.append(config.value("Printer/parallel").toString());
    ini.append("|");
    ini.append(config.value("Printer/type").toString());
    ini.append("|");
    ini.append(config.value("Printer/usb").toString());
    ini.append("|");
    ini.append(config.value("Printer/IP").toString());
    ini.append("|");
    ini.append( config.value("Printer/Printlabel").toString());
    ini.append("|");
    ini.append( config.value("Printer/LogDays").toString());
    ini.append("|");

    //打印标签
    ini.append(config.value("Printer/wigth","40").toString());
    ini.append("|");
    ini.append(config.value("Printer/high","30").toString());
    ini.append("|");
    ini.append( config.value("Printer/speed","3").toString());
    ini.append("|");
    ini.append( config.value("Printer/crow","1").toString());
    ini.append("|");

    //ini.append( config.value("Printer/crow").toString());
//	ini.append("1");
//	ini.append("|");
    //ini.append( config.value("Printer/label_type").toString());
//	ini.append("1");
//	ini.append("|");
    //ini.append( config.value("Printer/clabel_parallrow").toString());
//	ini.append("1");
//	ini.append("|");
    //ini.append( config.value("Printer/label_usb").toString());
//	ini.append("1");
//	ini.append("|");
    //ini.append( config.value("Printer/label_ip").toString());
//	ini.append("1");
//	ini.append("|");
    //ini.append( config.value("Printer/label_ip").toString());
//	ini.append("4");
//	ini.append("|");
//	strcpy(data, ini.c_str());

    //指令集选项
    //标签打印机指令集0是TSC 适用佳博等;1PBAL 使用新北洋等;
    ini.append(config.value("Printer/labeltype","0").toString());
    ini.append("|");
    ini.append(config.value("Printer/labelparall","LPT1").toString());
    ini.append("|");
    ini.append( config.value("Printer/labelusb","USB-0").toString());
    ini.append("|");
    ini.append( config.value("Printer/labelip","127.0.0.1").toString());
    ini.append("|");
    //标签打印机端口打开方式 3:Ip 4:驱动;
    ini.append( config.value("Printer/labelprttype","4").toString());
    ini.append("|");

    return ini;
}

QString PrintLib::_OnlyGetPrintIni()
{
    QString path = QString("%1/printer.ini").arg(QCoreApplication::applicationDirPath());
    QSettings config(path, QSettings::IniFormat);
    QString ini;
    ini.append(config.value("OtherPrinter/Name").toString());
    ini.append("|");
    ini.append(config.value("OtherPrinter/printType").toString());
    ini.append("|");
    ini.append(config.value("OtherPrinter/PaperWidth").toString());
    ini.append("|");
    ini.append(config.value("Printer/levlel").toString());
    ini.append("|");
    ini.append(config.value("Printer/parallel").toString());
    ini.append("|");
    ini.append(config.value("OtherPrinter/type").toString());
    ini.append("|");
    ini.append(config.value("Printer/usb").toString());
    ini.append("|");
    ini.append(config.value("OtherPrinter/IP").toString());
    ini.append("|");
    ini.append( config.value("Printer/Printlabel").toString());
    ini.append("|");
    ini.append( config.value("Printer/LogDays").toString());
    ini.append("|");
    //打印标签
    ini.append(config.value("Printer/wigth","40").toString());
    ini.append("|");
    ini.append(config.value("Printer/high","30").toString());
    ini.append("|");
    ini.append( config.value("Printer/speed","3").toString());
    ini.append("|");
    ini.append( config.value("Printer/crow","1").toString());
    ini.append("|");
    //指令集选项
    //标签打印机指令集0是TSC 适用佳博等;1PBAL 使用新北洋等;
    ini.append(config.value("Printer/labeltype","0").toString());
    ini.append("|");
    ini.append(config.value("Printer/labelparall","LPT1").toString());
    ini.append("|");
    ini.append( config.value("Printer/labelusb","USB-0").toString());
    ini.append("|");
    ini.append( config.value("Printer/labelip","127.0.0.1").toString());
    ini.append("|");
    //标签打印机端口打开方式 3:Ip 4:驱动;
    ini.append( config.value("Printer/labelprttype","4").toString());
    ini.append("|");

    return ini;
}
