#include "DetailsForm.h"
#include "ui_DetailsForm.h"
#include "Util/Tools.h"
#include "QsLog.h"
#include "PreDefined.h"
#include "NotifyForm.h"
#include "RejectForm.h"
#include "RefundForm.h"
#include "NoRefundForm.h"
#include "DataObject/DeliverObject.h"
#include "DeliversForm.h"
#include "MateChooser.h"
#include "../fmTakeaway_printer/Fmtakeaway_printer.h"
#include "MainForm.h"
#include "DrinkItem.h"
#include "Util/IniDataManger.h"
#include <QFile>
#include <QFileInfo>
#include <QPointer>
#include "XCBOperate.h"

DetailsForm::DetailsForm(OrderObject *orderObj, QWidget *parent) :
    QDialog(parent),
    ui(new Ui::DetailsForm)
{
    ui->setupUi(this);
    m_orderObj = orderObj;

//    ui->detailsTable->setColumnHidden(0, true);
//    ui->detailsTable->setColumnHidden(1, true);
//    ui->detailsTable->setColumnHidden(2, true);
    ui->detailsTable->setColumnHidden(3, true);
    ui->detailsTable->setColumnHidden(4, true);

    _InitUi();

    connect(OBJPTR(BillsManger), SIGNAL(sucessful(QString, QString)), this, SLOT(onSucessful(QString, QString)));
    connect(OBJPTR(BillsManger), SIGNAL(error(QString,BillsManger::ErrorType)),
            this, SLOT(onError(QString,BillsManger::ErrorType)));

    connect(ui->detailsTable, SIGNAL(itemClicked(QTreeWidgetItem*,int)), SLOT(onItemClicked(QTreeWidgetItem*,int)));
}

DetailsForm::~DetailsForm()
{
    delete ui;
}

void DetailsForm::_InitUi()
{
    this->setWindowFlags(this->windowFlags()|Qt::FramelessWindowHint|Qt::Dialog);
    QDialog *parent = (QDialog*)this->parent();
    this->setGeometry(parent->pos().x(), parent->pos().y(), parent->width(), parent->height());

    int vid = OBJREF(BillsManger).GetTableVID(m_orderObj);

    //! Titles and tips
    ui->detailsBtn0->setText(OPERABTN_NAME_REJECT);
    ui->detailsBtn1->setText(OPERABTN_NAME_HOLD);
    ui->detailsBtn2->setText(GetOperaBtnNameByVID(vid));
    ui->detailsLabStatus->setText(GetOrderStatusName(m_orderObj->status, m_orderObj->delivery_status));

    bool show_cancel = (OBJREF(IniDataManger).GetShowCancel()
                        || vid == TABLE_VID_SHIPSELF || vid == TABLE_VID_SELF_REFUND
                        || vid == TABLE_VID_REFUND);
    if (!show_cancel) {
        ui->detailsBtn0->setVisible(false);
        ui->horizontalLayout_11->removeItem(ui->horizontalSpacer);
    }

    switch(vid) {
    case TABLE_VID_RESERVATION: {
        ui->optTitle->setText(DETAILTITLE_RESERVATION);
        QString tip = DETAILTIP_RESERVATION;
        tip = tip.arg(QDateTime::fromTime_t(m_orderObj->delivery_time).toString("hh:mm"));
        ui->optTip->setText(tip);
        break;
    }
    case TABLE_VID_SHIPSELF:
        ui->optTitle->setText(DETAILTITLE_SHOP_DELIVERY);
        ui->optTip->setText(DETAILTIP_SHOP_DELIVERY);
        break;
    case TABLE_VID_MAKING:
    case TABLE_VID_SELF_MAKING:
        ui->optTitle->setText(DETAILTITLE_MAKING);
        break;
    case TABLE_VID_CONFIRM_MATE:
        ui->optTitle->setText((DETAILTITLE_CONFIRM_MATE));
        ui->optTip->setText(DETAILTIP_CONFIRM_MATE);
        break;
    case TABLE_VID_SHIPING:
    case TABLE_VID_SELF_SHIPING:
        ui->optTitle->setText(DETAILTITLE_DELIVERING);
        break;
    case TABLE_VID_FINISH:
    case TABLE_VID_SELF_FINISH:
        ui->optTitle->setText(DETAILTITLE_COMPLETE);
        ui->detailsBtn0->setVisible(false);
        ui->detailsBtn2->setVisible(false);
        ui->detailsBtn1->setText(OPERABTN_NAME_CLOSE);
        ui->horizontalLayout_11->removeItem(ui->horizontalSpacer_2);
        break;
    case TABLE_VID_REFUND:
    case TABLE_VID_SELF_REFUND:
        ui->optTitle->setText(DETAILTITLE_REFUND);
        ui->optTip->setText(DETAILTIP_REFUND );

        ui->detailsLabStatus->setStyleSheet("color: red;");
        ui->detailsBtn0->setText(OPERABTN_NAME_REFUND_REJECT);
        ui->detailsBtn1->setText(OPERABTN_NAME_HOLD);
        ui->detailsBtn2->setText(OPERABTN_NAME_REFUND_ACCEPT);
        ui->detailsLabStatus->setText(GetOrderStatusName(m_orderObj->status, m_orderObj->delivery_status)
                                      + "(" + m_orderObj->status_desc +")");
        ui->optTitle->setStyleSheet("#optTitle { background: rgb(204, 9, 20);}");
        ui->optTip->setStyleSheet("#optTip { color: rgb(222, 97, 50); }");
        break;
    default:
        ui->optTitle->setText(DETAILTITLE_OTHER);
        ui->detailsBtn1->setText(OPERABTN_NAME_CLOSE);
        ui->detailsBtn2->setVisible(false);
        ui->horizontalLayout_11->removeItem(ui->horizontalSpacer_2);
        break;
    }

    int tableWidth = this->width()/2-90;
    ui->detailsTable->setColumnWidth(0, tableWidth*7/10);
    ui->detailsTable->setColumnWidth(1, tableWidth*2/10);
    ui->detailsTable->header()->setDefaultAlignment(Qt::AlignCenter);
    ui->detailsTable->header()->setFixedHeight(40);
    ui->detailsTable->header()->setStretchLastSection(true);
    ui->detailsTable->header()->setSectionResizeMode(QHeaderView::Fixed);

    ui->detailsLabChannel->setText(m_orderObj->channelName + QString("(#%1)").arg(m_orderObj->order_index));
    QString channelColor = OBJREF(IniDataManger).GetChannelColor(m_orderObj->channel);
    ui->detailsLabChannel->setStyleSheet("QLabel {color:" + channelColor + "; font-weight: bold;}");
    ui->detailsLabAdress->setText(m_orderObj->address);
    ui->detailsLabName->setText(m_orderObj->customer);
    ui->detailsLabOrderId->setText(m_orderObj->order_id);
    ui->detailsLabRemark->setText(QString("[%1]%2").arg(m_orderObj->pay_type).arg(m_orderObj->remark));
    ui->detailsLabShipFee->setText(UnitConver(m_orderObj->send_fee));
    ui->detailsLabShipType->setText(m_orderObj->delivery_party);
    ui->detailsLabTelNum->setText(m_orderObj->phone);

    if (m_orderObj->channel == CHANNEL_ID_BD) {
        ui->detailsSlabShopFee->setText("配送员付现");
        ui->detailsSlabShopFee->setStyleSheet("QLabel {color:" + channelColor + "; font-weight: bold;}");
        ui->detailsLabShopFee->setStyleSheet("QLabel {color:" + channelColor + "; font-weight: bold;}");
    }
    ui->detailsLabShopFee->setText(!m_orderObj->pay_type.compare("在线支付")?"0":UnitConver(m_orderObj->shop_fee));

    ui->detailsBtn0->setProperty(OPERABTN_PROPERTY_NAME, m_orderObj->order_id);
    ui->detailsBtn1->setProperty(OPERABTN_PROPERTY_NAME, m_orderObj->order_id);
    ui->detailsBtn2->setProperty(OPERABTN_PROPERTY_NAME, m_orderObj->order_id);

    //! Read bill
    bool assigned = _ReadBilledMates();

    QLOG_INFO() << "read order mates: " << m_orderObj->pvm << assigned;

    //! Display drinks and assigned mates
    QList<ComdObject*> product_list = m_orderObj->pvm.keys();
    foreach(ComdObject *product, product_list) {
        _TableInsert(product);
    }

    //! Display unassigned drinks' mates
    foreach(ComdObject *mate, m_orderObj->mateList) {
        if (!m_orderObj->assignedMateList.contains(mate)) {
            _TableInsert(mate);
        }
    }
}

bool DetailsForm::_ReadBilledMates()
{
    QFileInfo bill_fm(m_orderObj->bill_file);

    QString vivi_file = OBJREF(IniDataManger).GetViviBillFile();
    vivi_file += bill_fm.fileName();

    QFile file(m_orderObj->bill_file);
    if (m_orderObj->billed && !bill_fm.exists()) {
        file.setFileName(vivi_file);
        m_orderObj->bill_file = vivi_file;
    }

    if (m_orderObj->billed && file.open(QFile::ReadOnly)) {
        QLOG_INFO() << "order file read: " << m_orderObj->bill_file;
        QByteArray bill_content = file.readAll();
//        QJson::Parser p;
//        QVariantMap bill = p.parse(bill_content).toMap();
        QJsonObject bill = QJsonDocument::fromJson(bill_content).object();
        if (!bill.isEmpty()) {
            QJsonArray products = bill["products"].toArray();
            m_orderObj->MatchObjectsFromBill(products);
        }
    }
    else {
        QLOG_INFO() << "order file read failed: " << m_orderObj->bill_file;
    }
    m_orderObj->CheckIfMatesAssigned();

    return m_orderObj->mate_assigned;
}

void DetailsForm::_GetMatesSelection(QTreeWidgetItem *item, QList<ComdObject*> &selected, QList<ComdObject*> &unselected)
{
    MateChooser mateChooser(this);
    mateChooser.setTitle(item->text(0));

    QList<ComdObject*> pendingMates;
    //! Unassigned items
    foreach(ComdObject *obj, m_orderObj->mateList) {
        if (!m_orderObj->assignedMateList.contains(obj)) {
            pendingMates << obj;
        }
    }

    //! Items assigned to current item
    QList<ComdObject*> childMates;
    int acnt = item->childCount();
    for (int i = 0; i < acnt; ++i) {
        QTreeWidgetItem *child = item->child(i);
        childMates << _ItemToObject(child);
    }

    mateChooser.setMates(pendingMates, childMates);
    QList<ComdObject*> candidates = mateChooser.candidates();
    if (!candidates.isEmpty()) {
        XCBOperate oper;
        oper.update(mateChooser.winId());
        mateChooser.exec();
        if (mateChooser.result() == QDialog::Accepted) {
            selected = mateChooser.selectedMates();
            unselected = candidates;
            foreach(ComdObject* m, selected) {
                unselected.removeOne(m);
            }
        }
        else {
            QLOG_INFO() << "canceled choosing mates.";
        }
    }
    else {
        QLOG_INFO() << "no candidates.";
    }
}

void DetailsForm::_AssignMate(QTreeWidgetItem *parent, ComdObject *child)
{
    QLOG_TRACE() << "DetailsForm" << __FUNCTION__ << "parent: " << parent->text(3)
                 << parent->text(0) << ", child:" << child << child->name;
    int parent_cnt = parent->text(2).toInt();
    int mate_cnt = child->productAmount;
    ComdObject *parent_object = _ItemToObject(parent);
    if (!parent_object) {
        QLOG_ERROR() << "can't find object from item:" << parent->text(3) << parent->text(0);
        return;
    }

    if (m_orderObj->pvm[parent_object].contains(child)) {
        return;
    }

    if (parent_cnt > mate_cnt) {
        //! Duplicate parent
        parent_object->productAmount = mate_cnt;
        m_orderObj->pvm[parent_object] << child;
        m_orderObj->assignedMateList << child;
        _TableUpdate(parent_object);

        ComdObject *lone_parent = _LoneObjectByName(parent_object->name, parent_object->property_tags);
        if (lone_parent) {
            lone_parent->productAmount += parent_cnt - mate_cnt;
            _TableUpdate(lone_parent);
        }
        else {
            ComdObject *dup_obj = new ComdObject();
            dup_obj->fetchDataFromJson(parent_object->toJson());
            dup_obj->productAmount = parent_cnt - mate_cnt;
            m_orderObj->pvm[dup_obj] = QList<ComdObject*>();
            _TableInsert(dup_obj);
        }
    }
    else if (parent_cnt == mate_cnt) {
        //! Move to parent
        parent_object->productAmount = mate_cnt;
        m_orderObj->pvm[parent_object] << child;
        m_orderObj->assignedMateList << child;
        _TableUpdate(parent_object);
    }
    else if (parent_cnt < mate_cnt) {
        //! Duplicate child
        child->productAmount = mate_cnt - parent_cnt;
        _TableUpdate(child);

        ComdObject *dup_child = new ComdObject();
        dup_child->fetchDataFromJson(child->toJson());
        dup_child->productAmount = parent_cnt;
        _TableInsert(dup_child);
        m_orderObj->pvm[parent_object] << dup_child;
        m_orderObj->assignedMateList << dup_child;
        m_orderObj->mateList << dup_child;
        _TableUpdate(parent_object);
    }

//    QLOG_INFO() << "Assigned " << child->name << "to" << parent->text(3) << parent->text(0);
}

void DetailsForm::_UnassignMate(QTreeWidgetItem *parent, ComdObject *child)
{
    QLOG_TRACE() << "DetailsForm" << __FUNCTION__ << "parent: " << parent->text(3)
                 << parent->text(0) << ", child:" << child << child->name;

    if (m_orderObj->assignedMateList.contains(child)) {
        ComdObject *lone_child = _LoneObjectByName(child->name, child->property_tags);
        if (lone_child) {
            lone_child->productAmount += child->productAmount;
            _TableUpdate(lone_child);
            QTreeWidgetItem* child_item = _TableFindItem(child);
            if (child_item) {
                parent->removeChild(child_item);
            }
            m_orderObj->mateList.removeOne(child);
        }
        else {
            _TableSetChild(0, child);
        }
        m_orderObj->assignedMateList.removeOne(child);

        ComdObject *parent_obj = _ItemToObject(parent);
        if (m_orderObj->pvm.contains(parent_obj)) {
            ComdObject *lone_parent = _LoneObjectByName(parent_obj->name, parent_obj->property_tags);
            m_orderObj->pvm[parent_obj].removeOne(child);
            _TableUpdate(parent_obj);
            if (parent->childCount() == 0) {
                QLOG_INFO() << "lone object: " << lone_parent << "current object:" << parent_obj;
                if (lone_parent) {
                    if (parent_obj != lone_parent) {
                        lone_parent->productAmount += parent_obj->productAmount;
                        _TableUpdate(lone_parent);
                        QLOG_INFO() << "deleted parent:" << parent_obj;
                        ui->detailsTable->takeTopLevelItem(ui->detailsTable->indexOfTopLevelItem(parent));
                        m_orderObj->pvm.remove(parent_obj);
                    }
                }
            }
        }
        else {
            QLOG_WARN() << "can't find parent object from item: " << parent->text(3) << parent->text(0);
        }
    }
    else {
        QLOG_WARN() << "child haven't been assigned:" << child;
    }
}

void DetailsForm::_TableInsert(ComdObject *obj)
{
    QLOG_TRACE() << "DetailsForm" << __FUNCTION__ << obj << obj->name;
    QStringList row;
    row << obj->name << UnitConver(obj->price) << QString::number(obj->productAmount)
        << QString::number((uint)obj, 16) << obj->property_tags;
    QLOG_INFO() << "item added: " << row;
    QTreeWidgetItem *item = new QTreeWidgetItem(ui->detailsTable, row);
    item->setTextAlignment(0, Qt::AlignCenter);
    item->setTextAlignment(1, Qt::AlignCenter);
    item->setTextAlignment(2, Qt::AlignCenter);
    item->setTextAlignment(3, Qt::AlignCenter);
    item->setTextAlignment(4, Qt::AlignCenter);

    if (m_orderObj->pvm.contains(obj)) {
        QString mates;
        QList<ComdObject*> mate_list = m_orderObj->pvm[obj];
        if (!mate_list.isEmpty()) {
            int mate_price = 0;
            foreach(ComdObject *mo, mate_list) {
                mate_price += mo->price;
                mates += mo->name + "|";
                row.clear();
                row << mo->name << UnitConver(mo->price) << QString::number(mo->productAmount)
                    << QString::number((uint)mo, 16) << mo->property_tags;
                QTreeWidgetItem *child = new QTreeWidgetItem(item, row);
                QFont ft = child->font(1);
                ft.setPointSize(ft.pointSize() - 1);
                child->setFont(0, ft);
                child->setTextAlignment(0, Qt::AlignCenter);
                child->setTextAlignment(1, Qt::AlignCenter);
                child->setTextAlignment(2, Qt::AlignCenter);
                child->setTextAlignment(3, Qt::AlignCenter);
                child->setTextAlignment(4, Qt::AlignCenter);
            }

            item->setText(1, UnitConver(obj->price + mate_price));
        }
        if (obj->property_tags.isEmpty()) {
            mates.remove(mates.lastIndexOf("|"), 1);
        }
        mates += obj->property_tags;
        if (!mates.isEmpty()) {
            mates.replace("|", ",");
            DrinkItem *drink = new DrinkItem(item->text(0), mates, this);
            ui->detailsTable->setItemWidget(item, 0, drink);
        }
    }
}

void DetailsForm::_TableUpdate(ComdObject *obj)
{
    QLOG_TRACE() << "DetailsForm" << __FUNCTION__ << obj << obj->name;
    QTreeWidgetItem *item = _TableFindItem(obj);
    if (item) {
        int mate_price = 0;
        //! Product
        if (m_orderObj->pvm.contains(obj)) {
            QString mates;
            QList<ComdObject*> mate_list = m_orderObj->pvm[obj];
            if (!mate_list.isEmpty()) {
                foreach(ComdObject *mo, mate_list) {
                    mates += mo->name + "|";
                    mate_price += mo->price;
                    QTreeWidgetItem *child_item = _TableFindItem(mo);
                    if (child_item && child_item->parent() == item) {
                        _TableUpdateChild(obj, mo);
                    }
                    else {
                        _TableSetChild(item, mo);
                    }
                }
            }
            if (obj->property_tags.isEmpty()) {
                mates.remove(mates.lastIndexOf("|"), 1);
            }
            mates += obj->property_tags;
            DrinkItem *drink = (DrinkItem*)ui->detailsTable->itemWidget(item, 0);
            if (!mates.isEmpty()) {
                mates.replace("|", ",");
                if (drink) {
                    drink->setDrinkMate(mates);
                }
                else {
                    DrinkItem *drink = new DrinkItem(item->text(0), mates, this);
                    ui->detailsTable->setItemWidget(item, 0, drink);
                }
            }
            else {
                if (drink) {
                    drink->setDrinkMate(mates);
                }
            }
        }
        //! Mates

        item->setText(1, UnitConver(obj->price + mate_price));
        item->setText(2, QString::number(obj->productAmount));
    }
}

void DetailsForm::_TableUpdateChild(ComdObject *parent, ComdObject *child)
{
    QLOG_TRACE() << "DetailsForm" << __FUNCTION__ << "parent: " << parent
                 << parent->name << ", child:" << child << child->name;
    if (parent && child && parent->productAmount < child->productAmount) {
        int dup_cnt = child->productAmount - parent->productAmount;
        child->productAmount = parent->productAmount;
        _TableUpdate(child);

        ComdObject *lone_child = _LoneObjectByName(child->name, child->property_tags);
        if (lone_child) {
            lone_child->productAmount += dup_cnt;
            _TableUpdate(lone_child);
        }
        else {
            ComdObject *dup_child = new ComdObject();
            dup_child->fetchDataFromJson(child->toJson());
            dup_child->productAmount = dup_cnt;
            _TableInsert(dup_child);
            m_orderObj->mateList << dup_child;
        }
    }
}

void DetailsForm::_TableSetChild(QTreeWidgetItem *parent, ComdObject *child)
{
    QTreeWidgetItem *child_item = _TableFindItem(child);
    if (child_item) {
        QTreeWidgetItem* prev_parent = child_item->parent();
        if (parent) {
            QLOG_TRACE() << "DetailsForm" << __FUNCTION__ << "parent: " << parent->text(3)
                         << parent->text(0) << ", child:" << child << child->name;
            ui->detailsTable->takeTopLevelItem(ui->detailsTable->indexOfTopLevelItem(child_item));
            QFont ft = child_item->font(1);
            ft.setPointSize(ft.pointSize() - 1);
            child_item->setFont(0, ft);
            parent->addChild(child_item);
        }
        else {
            QLOG_TRACE() << "DetailsForm" << __FUNCTION__ << "remove child:" << child << child->name;
            if (prev_parent) {
                prev_parent->removeChild(child_item);
                QFont ft = child_item->font(1);
                child_item->setFont(0, ft);
                ui->detailsTable->addTopLevelItem(child_item);
            }
        }
    }
    else {
        QLOG_ERROR() << "can't find child item from object:" << child << child->name;
    }

}

QTreeWidgetItem* DetailsForm::_TableFindItem(const ComdObject *obj)
{
//    QLOG_TRACE() << "DetailsForm" << __FUNCTION__ << obj << obj->name;
    QList<QTreeWidgetItem*> item_list = ui->detailsTable->findItems(QString::number((uint)obj, 16),
                                                                    Qt::MatchExactly | Qt::MatchRecursive,
                                                                    3);
    foreach(QTreeWidgetItem *item, item_list) {
        if (item_list.size() > 1) {
            QLOG_WARN() << "matches more:" << item->text(0);
        }
        return item;
    }

    return 0;
}

ComdObject *DetailsForm::_ItemToObject(const QTreeWidgetItem * item)
{
    QLOG_TRACE() << "DetailsForm" << __FUNCTION__ << item->text(3) << item->text(0);

    bool ok = false;
    ComdObject *obj = (ComdObject*)item->text(3).toUInt(&ok, 16);
    if (ok) {
        return obj;
    }
    else {
        return 0;
    }
}

ComdObject *DetailsForm::_LoneObjectByName(const QString &name, const QString &props)
{
    QLOG_TRACE() << "DetailsForm" << __FUNCTION__ << name << props;

    QList<ComdObject*> products = m_orderObj->pvm.keys();
    foreach(ComdObject *po, products) {
        if (po->name == name && po->property_tags == props && m_orderObj->pvm[po].isEmpty()) {
            return po;
        }
    }

    foreach(ComdObject *mo, m_orderObj->mateList) {
        if (mo->name == name) {
            QTreeWidgetItem *item = _TableFindItem(mo);
            if (!item->parent()) {
                return mo;
            }
        }
    }

    return 0;
}

// 拒单
void DetailsForm::on_detailsBtn0_clicked()
{
    QLOG_TRACE() << "DetailsForm" << __FUNCTION__;
    QPushButton *targetBtn = (QPushButton*)sender();

    int code = 0;
    if (!targetBtn->text().compare(OPERABTN_NAME_REJECT)) {
        RejectForm rjForm(this);
        XCBOperate oper;
        oper.update(rjForm.winId());
        if(QDialog::Rejected==rjForm.exec()) {
            return;
        }
        else {
            code = rjForm.GetReasonCode();
        }
        OBJREF(BillsManger).ProcOrders(targetBtn->text(), targetBtn->property(OPERABTN_PROPERTY_NAME).toString(), code);
    }
    else if (!targetBtn->text().compare(OPERABTN_NAME_REFUND_REJECT)) {
        QString reason;
        NoRefundForm no_rfdForm(this);
        XCBOperate oper;
        oper.update(no_rfdForm.winId());
        if(QDialog::Rejected==no_rfdForm.exec()) {
            return;
        }
        else {
            reason = no_rfdForm.GetReason();
        }
        OBJREF(BillsManger).ProcOrders(targetBtn->text(), targetBtn->property(OPERABTN_PROPERTY_NAME).toString(), reason);
    } else {
        OBJREF(BillsManger).ProcOrders(targetBtn->text(), targetBtn->property(OPERABTN_PROPERTY_NAME).toString());
    }

    NotifyForm ntForm(NTFORM_LOADING, NotifyForm::LOADING, this);
    connect(this, SIGNAL(ntFormClose()), &ntForm, SLOT(accept()));
    XCBOperate oper;
    oper.update(ntForm.winId());
    ntForm.exec();
}

// 拒单
void DetailsForm::on_detailsBtn1_clicked()
{
    QLOG_TRACE() << "DetailsForm" << __FUNCTION__;
    close();
}

// 状态对应的操作
void DetailsForm::on_detailsBtn2_clicked()
{
    QLOG_TRACE() << "DetailsForm" << __FUNCTION__;

    QPushButton *targetBtn = (QPushButton*)sender();
    DeliverObject deliverObj;
    deliverObj.name = "自配送";
    if(!targetBtn->text().compare(OPERABTN_NAME_DEAFULT))
    {
        NotifyForm ntForm(NTFORM_FAILED, NotifyForm::ERROR, this);
        XCBOperate oper;
        oper.update(ntForm.winId());
        ntForm.exec();
        return;
    }
    if(!targetBtn->text().compare(OPERABTN_NAME_CONFIRM))
    {
        OBJREF(BillsManger).ProcOrders(targetBtn->text(), targetBtn->property(OPERABTN_PROPERTY_NAME).toString(), -1, deliverObj);
        if ( m_orderObj->has_mate && !m_orderObj->mate_assigned) {
            return;
        }
    }else if (!targetBtn->text().compare(OPERABTN_NAME_REFUND_ACCEPT)) {
        QString reason;
        RefundForm rfdForm(this);
        XCBOperate oper;
        oper.update(rfdForm.winId());
        if(QDialog::Rejected==rfdForm.exec()) {
            return;
        }
        else {
            reason = rfdForm.GetReason();
        }
        OBJREF(BillsManger).ProcOrders(targetBtn->text(), targetBtn->property(OPERABTN_PROPERTY_NAME).toString(), reason);
    }
    else if (!targetBtn->text().compare(OPERABTN_NAME_MAKE)) {
        OBJREF(BillsManger).ProcOrders(targetBtn->text(), targetBtn->property(OPERABTN_PROPERTY_NAME).toString());
        return;
    } else if (!targetBtn->text().compare(OPERABTN_NAME_CONFIRM_MATE)) {
        OBJREF(BillsManger).ProcOrders(targetBtn->text(), targetBtn->property(OPERABTN_PROPERTY_NAME).toString());
        emit orderMateChanged(m_orderObj->order_id);
        return;
    }
    else {
        OBJREF(BillsManger).ProcOrders(targetBtn->text(), targetBtn->property(OPERABTN_PROPERTY_NAME).toString());
    }

    NotifyForm ntForm(NTFORM_LOADING, NotifyForm::LOADING, this);
    connect(this, SIGNAL(ntFormClose()), &ntForm, SLOT(accept()));
    XCBOperate oper;
    oper.update(ntForm.winId());
    ntForm.exec();
}

// 关闭
void DetailsForm::on_detailsBtnClose_clicked()
{
    QLOG_TRACE() << "DetailsForm" << __FUNCTION__;
    this->reject();
}

void DetailsForm::onItemClicked(QTreeWidgetItem* item, int col)
{
    Q_UNUSED(col);
    QLOG_TRACE() << "DetailsForm" << __FUNCTION__;

    int vid = OBJREF(BillsManger).GetTableVID(m_orderObj);

    switch(vid) {
    case TABLE_VID_MAKING:
    case TABLE_VID_SELF_MAKING:
    case TABLE_VID_CONFIRM_MATE:
    case TABLE_VID_SHIPING:
    case TABLE_VID_SELF_SHIPING:
    case TABLE_VID_RESERVATION:
    case TABLE_VID_SHIPSELF:
        break;
    default:
        item->setExpanded(!item->isExpanded());
        return;
    }

    if (m_orderObj->billed) {
        item->setExpanded(!item->isExpanded());
        return;
    }

    if (m_orderObj->has_mate) {
        QList<ComdObject*> sel_mates, unsel_mates;
        ComdObject *parent_obj = _ItemToObject(item);

        if (m_orderObj->mateList.contains(parent_obj)) {
            return;
        }

        _GetMatesSelection(item, sel_mates, unsel_mates);

        //! Assign to product
        QList<ComdObject *> sorted_mo;
        if (!sel_mates.isEmpty()) {
            ComdObject *curr = sel_mates.first();
            sorted_mo << curr;
            foreach(ComdObject *smo, sel_mates) {
                if (smo->productAmount < curr->productAmount) {
                    sorted_mo.insert(sorted_mo.indexOf(curr), smo);
                    curr = smo;
                }
                else if (!sorted_mo.contains(smo)){
                    sorted_mo << smo;
                }
            }

            foreach(ComdObject *smo, sorted_mo) {
                _AssignMate(item, smo);
            }
        }

        //! Remove from product
        foreach (ComdObject *umo, unsel_mates) {
            _UnassignMate(item, umo);
        }

        m_orderObj->CheckIfMatesAssigned();
        QLOG_INFO() << "assigned mates:" << m_orderObj->assignedMateList;
        QLOG_INFO() << "lone mates:" << m_orderObj->loneMateList;
        QLOG_INFO() << "all mates:" << m_orderObj->mateList;
    }
}

void DetailsForm::onError(const QString &msg, BillsManger::ErrorType type)
{
    QLOG_TRACE() << "DetailsForm" << __FUNCTION__;
    emit ntFormClose();
    QString err = OBJREF(BillsManger).LastError();
    if (!err.isEmpty()) {
        err = "," + err;
    }
    NotifyForm ntForm(msg + err, NotifyForm::ERROR, this);
    XCBOperate oper;
    oper.update(ntForm.winId());
    ntForm.exec();
    // 网络错误
    if(BillsManger::SOCKET==type)
    {
        NotifyForm ntForm(NTFORM_LOADING, NotifyForm::LOADING, this);
        connect(this, SIGNAL(ntFormClose()), &ntForm, SLOT(accept()));
        OBJREF(BillsManger).Login();
        oper.update(ntForm.winId());
        ntForm.exec();
    }
    return;
}

void DetailsForm::onSucessful(const QString &msg, const QString &extra)
{
    QLOG_TRACE() << "DetailsForm" << __FUNCTION__;
    emit ntFormClose();
    NotifyForm ntForm(msg, NotifyForm::OK, this);
    if (m_orderObj->channel == CHANNEL_ID_BD) {
        QString msg = DETAILTIP_BD_SEND;
        msg = msg.arg(m_orderObj->order_id, UnitConver(m_orderObj->shop_fee));
        ntForm.SetExtraInfo(msg);
    }
//    ntForm.SetAutoClose(OBJREF(IniDataManger).GetNotifyAcceptTimer());
    XCBOperate oper;
    oper.update(ntForm.winId());
    ntForm.exec();

    this->accept();
}

void DetailsForm::on_detailsBtn3_clicked()
{
    QLOG_TRACE() <<  __FUNCTION__ << "reprinter";
    FmTakeaway_printer::Instance().DoPrint(IniDataManger::Instance().GetPrinterName(), m_orderObj);
}
