#include <QTimer>
#include <PeonySideBarModel>
#include <QScrollBar>
#include <QHeaderView>
#include <QPainterPath>
#include <QPainter>
#include <QDebug>
#include <QApplication>
#include <QTreeWidget>
#include <QMessageBox>
#include <QToolTip>
#include <QScreen>
#include <QDBusInterface>
#include "kyfiledialog.h"
#include "peony-qt/controls/menu/side-bar-menu/side-bar-menu.h"
#include "peony-qt/side-bar-abstract-item.h"
#include "peony-qt/volume-manager.h"
#include "peony-qt/file-enumerator.h"
#include "peony-qt/file-utils.h"
#include "peony-qt/file-info.h"
#include "vfs-plugin-iface.h"
#include "side-bar-abstract-item.h"
#include "global-settings.h"
#include "plugin-manager.h"
#include "../libqt5-ukui-style/settings/ukui-style-settings.h"
#include "debug.h"
#include "kyfiledialog.h"
#include "sidebar.h"

using namespace Peony;
using namespace UKUIFileDialog;
FileDialogComboBox::FileDialogComboBox(QWidget *parent):QComboBox(parent)
{
    if (QGSettings::isSchemaInstalled("org.ukui.style")) {
        auto settings = UKUIStyleSettings::globalInstance();
        connect(settings, &QGSettings::changed, this, [=](const QString &key){
            pDebug << "key changed:" << key << this->size();
                m_styleChanged = true;
        });
    }

    connect(this, &FileDialogComboBox::setStyleChanged, this, [=](bool change){
        pDebug << "setStyleChanged m_styleChanged:" << change;
        m_styleChanged = change;
    });
//    QDBusInterface *interFace = new QDBusInterface(SERVICE, PATH, INTERFACE, QDBusConnection::sessionBus());
//    if(interFace->isValid()){
//        connect(interFace, SIGNAL(mode_change_signal(bool)), this,  SLOT(tableModeChanged(bool)));
//    }
    m_minSize = this->minimumSize();
    pDebug << "combobox minsize...." << m_minSize;
}

void FileDialogComboBox::tableModeChanged(bool isTableMode)
{
    m_styleChanged = true;
}

QSize FileDialogComboBox::minimumSizeHint() const
{
    pDebug << "minimumSizeHint...." << m_styleChanged << this->size() << m_minSize;
    if(m_styleChanged || (qApp->screenAt(QCursor::pos())->availableSize().width() - 300) < QComboBox::minimumSizeHint().width())
    {
        Q_EMIT setStyleChanged(false);
        return m_minSize;//this->size();
    }
    QSize size = QComboBox::minimumSizeHint();

    return size;
}


FileDialogSideBar::FileDialogSideBar(QWidget *parent) : QTreeView(parent)
{
    static SideBarStyle *global_style = new SideBarStyle;

    setIconSize(QSize(16, 16));

//    header()->setSectionResizeMode(QHeaderView::Stretch );
    header()->setStretchLastSection(false);
    header()->hide();

    this->verticalScrollBar()->setProperty("drawScrollBarGroove", false);
    setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
    this->setFrameStyle(QFrame::NoFrame);
    setSortingEnabled(true);

    setProperty("useIconHighlightEffect", true);
    setProperty("highlightMode", true);

    setDragDropMode(QTreeView::NoDragDrop);
    setProperty("doNotBlur", true);
    viewport()->setProperty("doNotBlur", true);
    setContextMenuPolicy(Qt::CustomContextMenu);
    setAttribute(Qt::WA_TranslucentBackground);
    viewport()->setAttribute(Qt::WA_TranslucentBackground);
    viewport()->setAttribute(Qt::WA_Disabled, false);

    setExpandsOnDoubleClick(false);
    setMouseTracking(true);//追踪鼠标
    setAutoScrollMargin(0);


    m_delegate = new SideBarItemDelegate(this);
    setItemDelegate(m_delegate);

    m_model = new Peony::SideBarModel(this);
    m_proxyModel = new Peony::SideBarProxyFilterSortModel(this);
    m_proxyModel->setSourceModel(m_model);
    setModel(m_proxyModel);

    Peony::VolumeManager *volumeManager = Peony::VolumeManager::getInstance();
    connect(volumeManager,&Peony::VolumeManager::volumeAdded,this,[=](const std::shared_ptr<Peony::Volume> &volume){
        m_proxyModel->invalidate();//display DVD device in real time.
    });
    connect(volumeManager,&Peony::VolumeManager::volumeRemoved,this,[=](const std::shared_ptr<Peony::Volume> &volume){
        m_proxyModel->invalidate();//The drive does not display when the DVD device is removed.
        //pDebug << "volumeRemoved:" <<QToolTip::text();
        //fix abnormal pull out usb device tips not hide issue, link to bug#81190
        if (QToolTip::isVisible()) {
            QToolTip::hideText();
        }
    });
    connect(volumeManager,&Peony::VolumeManager::driveDisconnected,this,[=](const std::shared_ptr<Peony::Drive> &drive){
        m_proxyModel->invalidate();//Multiple udisk eject display problem
    });
        connect(volumeManager,&Peony::VolumeManager::mountAdded,this,[=](const std::shared_ptr<Peony::Mount> &mount){
        m_proxyModel->invalidate();//display udisk in real time after format it.
    });


    connect(this, &FileDialogSideBar::clicked, this, [=](const QModelIndex &index){
        switch (index.column()) {
        case 0: {
            auto item = m_proxyModel->itemFromIndex(index);

            if (! item)
                break;
            //continue to fix crash issue, related to bug#116201,116589
            if(item->isMountable()&&!item->isMounted())
                item->mount();
            else{
                auto uri = item->uri();

                if (!item->uri().isEmpty()){
                    if (uri == "computer:///ukui-data-volume") {
                        uri = "file:///data";
                    }
                    Q_EMIT goToUriRequest(uri);
                }
            }
            break;
        }
        case 1: {
            auto item = m_proxyModel->itemFromIndex(index);
            if (item->isMounted() || item->isEjectable()||item->isStopable()) {
                auto leftIndex = m_proxyModel->index(index.row(), 0, index.parent());
                this->collapse(leftIndex);
                item->ejectOrUnmount();
            } else {
                // if item is not unmountable, just be same with first column.
                // fix #39716
                auto uri = item->uri();

                if (!item->uri().isNull()){
                    if (uri == "computer:///ukui-data-volume") {
                        uri = "file:///data";
                    }
                    Q_EMIT goToUriRequest(uri);
                }
            }
            break;
        }
        default:
            break;
        }
    });

    connect(this, &FileDialogSideBar::expanded, this, [=](const QModelIndex &index){
        auto item = m_proxyModel->itemFromIndex(index);
        /*!
          \bug can not expanded? enumerator can not get prepared signal, why?
          */
        bool isShowNetwork = Peony::GlobalSettings::getInstance()->isExist(SHOW_NETWORK) ?
                    Peony::GlobalSettings::getInstance()->getValue(SHOW_NETWORK).toBool() : true;
        if (item->type() == Peony::SideBarAbstractItem::NetWorkItem && !isShowNetwork) {
            this->setRowHidden(index.row(), index.parent(), true);
            return;
        }

        QStringList disExtensions = Peony::GlobalSettings::getInstance()->getValue(DISABLED_EXTENSIONS).toStringList();
        for (auto extensions : disExtensions) {
            Peony::VFSPluginIface *pIface = dynamic_cast<Peony::VFSPluginIface*>(Peony::PluginManager::getInstance()->getPluginByFileName(extensions));
            if (pIface && pIface->pluginType() == Peony::PluginInterface::VFSPlugin
                    && item->type() == Peony::SideBarAbstractItem::FileSystemItem
                    && !item->uri().contains("computer:///")
                    && item->uri().contains(pIface->uriScheme())) {
                this->setRowHidden(index.row(), index.parent(), true);
                return;
            }

            if (pIface && pIface->pluginType() == PluginInterface::VFSPlugin
                    && item->type() == SideBarAbstractItem::FavoriteItem
                    && pIface->uriScheme() == "kmre://"
                    && item->uri().contains(pIface->uriScheme())) {
                this->setRowHidden(index.row(), index.parent(), true);
                return;
            }
        }

        item->findChildrenAsync();
    });

    connect(this, &FileDialogSideBar::collapsed, this, [=](const QModelIndex &index){
        auto item = m_proxyModel->itemFromIndex(index);
        item->clearChildren();
    });

    connect(this, &QTreeView::customContextMenuRequested, this, [=](const QPoint &pos){
        auto index = indexAt(pos);
        auto item = m_proxyModel->itemFromIndex(index);
        if (item) {
            if (item->type() != Peony::SideBarAbstractItem::SeparatorItem) {
                Peony::SideBarMenu menu(item, nullptr, parent ? parent : this);
                QList<QAction *> actionList;
                if (item->type() == Peony::SideBarAbstractItem::FileSystemItem) {
                    if ((0 != QString::compare(item->uri(), "computer:///")) &&
                        (0 != QString::compare(item->uri(), "filesafe:///"))) {
                        for (const auto &actionItem : actionList) {
                            if(item->isVolume())/* 分区才去需要判断是否已挂载 */
                                actionItem->setEnabled(item->isMounted());
                        }
                    }
                }

                menu.exec(QCursor::pos());
            }
        }
    });

//    QDBusInterface *interFace = new QDBusInterface(SERVICE, PATH, INTERFACE, QDBusConnection::sessionBus());
//    if(interFace->isValid()){
//        connect(interFace, SIGNAL(mode_change_signal(bool)), this,  SLOT(tableModeChanged(bool)));
//    }

//    if (QGSettings::isSchemaInstalled("org.ukui.style")) {
//        auto settings = UKUIStyleSettings::globalInstance();
//        connect(settings, &QGSettings::changed, this, [=](const QString &key){
//            pDebug << "key changed:" << key << width();
//            if (key == "styleName") {
//                m_siderWidth = this->width();
//            }
//        });
//    }
    expandToDepth(1);
    setStyle(global_style);
    setViewportMargins(8, 4, 4, 4);

    pDebug << "columndffffffffffffffff";
//    setColumnHidden(1, true);
}

FileDialogSideBar::~FileDialogSideBar()
{
    if(m_proxyModel){
        m_proxyModel->deleteLater();
        m_proxyModel = nullptr;
    }
    if(m_model){
        m_model->deleteLater();
        m_model = nullptr;
    }
    if(m_delegate){
        m_delegate->deleteLater();
        m_delegate = nullptr;
    }
}

void FileDialogSideBar::tableModeChanged(bool isTableMode)
{
    pDebug << "tableModeChanged........";
//    setStyle(SideBarStyle::getStyle());
}

void FileDialogSideBar::resizeEvent(QResizeEvent *e)
{
    setViewportMargins(8, 4, 4, 4);

//    this->setGeometry(this->x(), this->y(), m_siderWidth, this->height());
    QTreeView::resizeEvent(e);
    pDebug << "FileDialogSideBar resizeEvent header count......:" << header()->count() << this->viewport()->width() << this->columnWidth(0) << this->columnWidth(1);
    if (header()->count() > 0) {
        this->setColumnWidth(1, 20);
        header()->resizeSection(0, this->viewport()->width() - this->columnWidth(1));
    }
}

QSize FileDialogSideBar::sizeHint() const
{
    return QTreeView::sizeHint();
}

void FileDialogSideBar::menuRequest(const QPoint &pos)
{
//    auto index = indexAt(pos);
//    auto item = proxyModel->itemFromIndex(index);
//    if (item) {
//        pDebug << "sider bar menu00000" << item->type() << index;
//        if (item->type() != Peony::SideBarAbstractItem::SeparatorItem) {
//            pDebug << "sider bar menu11111";
////            Peony::SideBarMenu *menu = new Peony::SideBarMenu(item, this);
//            pDebug << "sider bar menu22222222";
////            menu->exec(QCursor::pos());
//            pDebug << "sider bar menu3333333";
//        }
//    }
}

void FileDialogSideBar::paintEvent(QPaintEvent *event)
{
    QPalette pal = qApp->palette();
    pal.setColor(QPalette::Base, QColor(Qt::transparent));
    setPalette(pal);
    viewport()->setPalette(pal);
    QTreeView::paintEvent(event);
}

//void FileDialogSideBar::paintEvent(QPaintEvent *e)
//{
//    QColor color = this->palette().window().color();
//    QColor colorBase = QColor(Qt::red); //this->palette().base().color();

//    int R1 = color.red();
//    int G1 = color.green();
//    int B1 = color.blue();
//    qreal a1 = 0.3;

//    int R2 = colorBase.red();
//    int G2 = colorBase.green();
//    int B2 = colorBase.blue();
//    qreal a2 = 1;

//    qreal a = 1 - (1 - a1)*(1 - a2);

//    qreal R = (a1*R1 + (1 - a1)*a2*R2) / a;
//    qreal G = (a1*G1 + (1 - a1)*a2*G2) / a;
//    qreal B = (a1*B1 + (1 - a1)*a2*B2) / a;

//    colorBase.setRed(R);
//    colorBase.setGreen(G);
//    colorBase.setBlue(B);
//    colorBase.setAlphaF(1);

////    QPainter p(this);
////    QPainterPath sidebarPath;
////    sidebarPath.addRoundedRect(this->geometry(), 6, 6);
////    p.fillPath(sidebarPath, colorBase);
////    viewport()->setObjectName("viewport");
////    viewport()->setStyleSheet("QWidget#viewport{background-color:rgba(255,255,255,0.5)");////" + QString::number(colorBase.red()) + "," + QString::number(colorBase.green()) + "," + QString::number(colorBase.blue()) + "," + QString::number(colorBase.alpha()) + "}");
//    QTreeView::paintEvent(e);
//}


SideBarItemDelegate::SideBarItemDelegate(QObject *parent)
{
//    if (QGSettings::isSchemaInstalled("org.ukui.style")) {
//        auto settings = UKUIStyleSettings::globalInstance();
//        connect(settings, &QGSettings::changed, this, [=](const QString &key){
//            pDebug << "key changed:" << key;
//            if (key == "styleName") {
//                pDebug << "key changed....";
//                this->paint();
//                this->update();
//            }
//        });
//    }
}

QSize SideBarItemDelegate::sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const
{
    auto size = QStyledItemDelegate::sizeHint(option, index);
    size.setHeight(36);
    return size;
}


void SideBarItemDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
{
//    painter->save();
//    if (index.column() == 1) {
//        QPainterPath rightRoundedRegion;
//        rightRoundedRegion.setFillRule(Qt::WindingFill);
//        auto rect = option.rect;
//        auto view = qobject_cast<const QAbstractItemView *>(option.widget);
//        if (view) {
//            rect.setRight(view->viewport()->rect().right());
//        }
//        rightRoundedRegion.addRoundedRect(rect, 4, 4);
//        rightRoundedRegion.addRect(rect.adjusted(0, 0, -4, 0));
//        painter->setClipPath(rightRoundedRegion);
//    }

//    painter->setRenderHint(QPainter::Antialiasing);
//    QStyledItemDelegate::paint(painter, option, index);
//    painter->restore();

    QStyledItemDelegate::paint(painter, option, index);
}

SideBarStyle::SideBarStyle()
{

}

void SideBarStyle::drawPrimitive(QStyle::PrimitiveElement element, const QStyleOption *option, QPainter *painter, const QWidget *widget) const
{
    painter->save();
    switch (element) {
    case QStyle::PE_IndicatorItemViewItemDrop: {
        painter->setRenderHint(QPainter::Antialiasing, true);/* 反锯齿 */
        /* 按设计要求，边框颜色为调色板highlight值，圆角为6px */
        QColor color = option->palette.color(QPalette::Highlight);
        painter->setPen(color);
        painter->drawRoundedRect(option->rect, 6, 6);
        painter->restore();
        return;
    }

    case QStyle::PE_IndicatorBranch: {
        if (option->rect.x() == 0) {
            QPainterPath leftRoundedRegion;
            leftRoundedRegion.setFillRule(Qt::WindingFill);
            leftRoundedRegion.addRoundedRect(option->rect, 4, 4);
            leftRoundedRegion.addRect(option->rect.adjusted(4, 0, 0, 0));
            painter->setClipPath(leftRoundedRegion);
        }
        const QStyleOptionViewItem *tmp = qstyleoption_cast<const QStyleOptionViewItem *>(option);
        QStyleOptionViewItem opt = *tmp;
        if (!opt.state.testFlag(QStyle::State_Selected)) {
            if (opt.state & QStyle::State_Sunken) {
                opt.palette.setColor(QPalette::Highlight, opt.palette.button().color());
//                opt.palette.setColor(QPalette::Highlight, Qt::red);
            }
            if (opt.state & QStyle::State_MouseOver) {
                opt.palette.setColor(QPalette::Highlight, opt.palette.mid().color());
//                opt.palette.setColor(QPalette::Highlight, Qt::green);
            }
        }
        qApp->style()->drawPrimitive(element, &opt, painter, widget);
        painter->restore();
        return;
    }
    case QStyle::PE_PanelItemViewRow: {
        painter->restore();
        return;
        break;
    }
    case QStyle::PE_PanelItemViewItem: {
        /*
        const QStyleOptionViewItem *vi = qstyleoption_cast<const QStyleOptionViewItem *>(option);
        QStyleOptionViewItem opt = *vi;
        painter->save();
        painter->setPen(Qt::NoPen);
        QPainterPath path;
        if (qobject_cast<const QTreeView*>(widget) || qobject_cast<const QTreeWidget*>(widget)) {
            path.addRoundedRect(vi->rect, 6, 6);
        }
        else {
            path.addRect(vi->rect);
        }
//                pDebug << "vi->rect:" << vi->rect;

        if (!opt.state.testFlag(QStyle::State_Selected)) {
            if (opt.state & QStyle::State_Sunken) {
                opt.palette.setColor(QPalette::Highlight, opt.palette.button().color());
            }
            if (opt.state & QStyle::State_MouseOver) {
                opt.palette.setColor(QPalette::Highlight, opt.palette.mid().color());
            }
        }
        painter->drawPath(path);
        */
        break;
    }

    default:
        break;
    }

    qApp->style()->drawPrimitive(element, option, painter, widget);
    painter->restore();
}

void SideBarStyle::drawControl(QStyle::ControlElement element, const QStyleOption *option, QPainter *painter, const QWidget *widget) const
{
    if (element == QStyle::CE_ItemViewItem) {
        const QStyleOptionViewItem *tmp = qstyleoption_cast<const QStyleOptionViewItem *>(option);
        QStyleOptionViewItem opt = *tmp;
        if (!opt.state.testFlag(QStyle::State_Selected)) {
            if (opt.state & QStyle::State_Sunken) {
                opt.palette.setColor(QPalette::Highlight, opt.palette.button().color());
            }
            if (opt.state & QStyle::State_MouseOver) {
                opt.palette.setColor(QPalette::Highlight, opt.palette.mid().color());
            }
        }
        return qApp->style()->drawControl(element, &opt, painter, widget);
    }
}

