/* powerwindow.cpp
 * Copyright (C) 2018 Tianjin KYLIN Information Technology Co., Ltd.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2, or (at your option)
 * any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
 * 02110-1301, USA.
**/

#include <QLabel>
#include <QVBoxLayout>
#include <QPixmap>
#include <QListWidgetItem>
#include <QListWidget>
#include <QEvent>
#include <QException>
#include <QDebug>
#include <QDBusReply>
#include <QDBusInterface>
#include "powerwindow.h"

PowerManager::PowerManager(QWidget *parent)
 : QListWidget(parent),
   m_power(new QLightDM::PowerInterface(this)),
   lasttime(QTime::currentTime())
{
    setFlow(QListWidget::LeftToRight);
    setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
    setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
    setSelectionMode(QListWidget::NoSelection);

    //QObject::connect(this,SIGNAL(itemClicked(QListWidgetItem*)),this,SLOT(powerClicked(QListWidgetItem*)));
    initUI();

    connect(XEventMonitor::instance(), SIGNAL(keyPress(const QString &)), this,
            SLOT(onGlobalKeyPress(const QString &)));
    connect(XEventMonitor::instance(), SIGNAL(keyRelease(const QString &)), this,
            SLOT(onGlobalkeyRelease(const QString &)));

}

QSize PowerManager::windowSize()
{
    return QSize((ITEM_WIDTH+ITEM_SPACING*2)*this->count()-ITEM_SPACING*2, ITEM_HEIGHT+ITEM_SPACING*2);
}


void PowerManager::powerClicked(QListWidgetItem *item)
{
    int interval = lasttime.msecsTo(QTime::currentTime());
    if(interval < 200 && interval > -200)
        return ;
    lasttime = QTime::currentTime();
/*
    int x = row(item);

    switch (x) {
    case 0:
        switchWidgetClicked();
        break;
    case 1:
        rebootWidgetClicked();
        break;
    case 2:
        shutdownWidgetClicked();
        break;
    case 3:
        if(m_power->canSuspend())
            suspendWidgetCliced();
        else if(m_power->canHibernate())
            hibernateWidgetClicked();
        break;
    case 4:
        if(m_power->canHibernate())
            hibernateWidgetClicked();
    default:
        break;
    }
*/
    QString name = itemWidget(item)->objectName();
    if(switchWidget && name == switchWidget->objectName())
        switchWidgetClicked();
    else if(name == rebootWidget->objectName())
        rebootWidgetClicked();
    else if(name == shutdownWidget->objectName())
        shutdownWidgetClicked();
    else if(suspendWidget &&  name == suspendWidget->objectName())
        suspendWidgetClicked();
    else if(hibernateWidget && name == hibernateWidget->objectName())
        hibernateWidgetClicked();

}

bool PowerManager::eventFilter(QObject *obj, QEvent *event)
{
    if(event->type() != QEvent::MouseButtonPress){
        return false;
    }

    QString name = obj->objectName();

    if(name == "switchFace")
        switchWidgetClicked();
    else if(name == "rebootFace")
        rebootWidgetClicked();
    else if(name == "shutdownFace")
        shutdownWidgetClicked();
    else if(name == "suspendFace")
        suspendWidgetClicked();
    else if(name == "hibernateFace")
        hibernateWidgetClicked();

    return QListWidget::eventFilter(obj, event);
}

QStringList PowerManager::getLoginedUsers()
{
    QStringList m_loginedUser;
    QDBusInterface *loginInterface = new QDBusInterface("org.freedesktop.login1",
                                        "/org/freedesktop/login1",
                                        "org.freedesktop.login1.Manager",
                                        QDBusConnection::systemBus(),
                                        this);
    QDBusMessage result = loginInterface->call("ListUsers");
    QList<QVariant> outArgs = result.arguments();
    QVariant first = outArgs.at(0);
    QDBusArgument dbvFirst = first.value<QDBusArgument>();
    QVariant vFirst = dbvFirst.asVariant();
    const QDBusArgument &dbusArgs = vFirst.value<QDBusArgument>();


    QVector<usersInfo> loginedUsers;

    dbusArgs.beginArray();
    while (!dbusArgs.atEnd()) {
        usersInfo user;
        dbusArgs >> user;
        loginedUsers.push_back(user);
    }

    for (usersInfo user: loginedUsers) {

        QDBusInterface userPertyInterface("org.freedesktop.login1", user.usersPath.path(),
                                          "org.freedesktop.DBus.Properties",
                                          QDBusConnection::systemBus());

        QDBusReply<QVariant> reply =
            userPertyInterface.call("Get", "org.freedesktop.login1.User", "State");
        if (reply.isValid()) {
            QString status = reply.value().toString();
            if ("closing" != status) {
                m_loginedUser.append(user.usersName);
            }
        }
    }
    return m_loginedUser;
}

QDBusArgument &operator <<(QDBusArgument &arg, const usersInfo &userInfo)
{
    arg.beginStructure();
    arg << userInfo.usersId
        << userInfo.usersName
        << userInfo.usersPath;
    arg.endStructure();
    return arg;
}
const QDBusArgument &operator >>(const QDBusArgument &arg, usersInfo &userInfo)
{
    arg.beginStructure();
    arg >> userInfo.usersId
        >> userInfo.usersName
        >> userInfo.usersPath;
    arg.endStructure();
    return arg;
}

void PowerManager::onGlobalKeyPress(const QString &key)
{
}

void PowerManager::onGlobalkeyRelease(const QString &key)
{
    if (key == "Escape") {
        this->hide();
    } else if (key == "Left" || key == "Right" || key == "Return" || key == "KP_Enter") {
        keyBdRelease(key);
    }
}

void PowerManager::keyBdRelease(QString key)
{
    QString focus = "focus";
    QString normal = "normal";
    if(key == "Right"){
        if(nowAt == -1){
            nowAt = 0;
            setButtonStyle(focus);
        } else if(nowAt == 0){
            setButtonStyle(normal);
            nowAt = 1;
            setButtonStyle(focus);
        } else if(nowAt == 1){
            setButtonStyle(normal);
            nowAt = 2;
            setButtonStyle(focus);
        } else if(nowAt == 2){
            setButtonStyle(normal);
            nowAt = 3;
            setButtonStyle(focus);
        } else if(nowAt == 3){
            setButtonStyle(normal);
            nowAt = 0;
            setButtonStyle(focus);
        }
    } else if(key == "Left") {
        if(nowAt == -1){
            nowAt = 3;
            setButtonStyle(focus);
        } else if(nowAt == 3){
            setButtonStyle(normal);
            nowAt = 2;
            setButtonStyle(focus);
        } else if(nowAt == 2){
            setButtonStyle(normal);
            nowAt = 1;
            setButtonStyle(focus);
        } else if(nowAt == 1){
            setButtonStyle(normal);
            nowAt = 0;
            setButtonStyle(focus);
        } else if(nowAt == 0){
            setButtonStyle(normal);
            nowAt = 3;
            setButtonStyle(focus);
        }
    } else if(key == "Return" || key == "KP_Enter"){
        if(nowAt == 0 && this->isVisible())
            hibernateWidgetClicked();
        else if(nowAt == 1 && this->isVisible())
            suspendWidgetClicked();
        else if(nowAt == 2 && this->isVisible())
            rebootWidgetClicked();
        else if(nowAt == 3 && this->isVisible())
            shutdownWidgetClicked();
    }
}


void::PowerManager::setButtonStyle(QString Style)
{
    if(Style == "normal")
        listLabel.at(nowAt)->setStyleSheet("background-color: rgba(255, 255, 255, 15%);QLabel:hover{background-color: rgba(255, 255, 255, 40%)}");
    else if(Style == "focus")
        listLabel.at(nowAt)->setStyleSheet("background-color: rgba(255, 255, 255, 20%);border: 1px solid #296CD9; border-radius: 64px;");
}

void PowerManager::doEvent(int type)
{
    switch (type) {
    case REBOOT:
        try{
            m_power->restart();
            close();
        }catch(QException &e) {
            qWarning() << e.what();
        }
    case SHOTDOWN:
        try{
            qDebug() << "shutdown";
            m_power->shutdown();
            close();
        }catch(QException &e) {
            qWarning() << e.what();
        }
    default:
        break;
    }
}

void PowerManager::switchWidgetClicked()
{
    emit switchToUser();
}

void PowerManager::shutdownWidgetClicked()
{
    if(getLoginedUsers().count() > 1){
        Q_EMIT mulUsersLogined(SHOTDOWN);
        return;
    }
    try{
        qDebug() << "shutdown";
        m_power->shutdown();
        close();
    }catch(QException &e) {
        qWarning() << e.what();
    }
}

void PowerManager::rebootWidgetClicked()
{
    if(getLoginedUsers().count() > 1){
        Q_EMIT mulUsersLogined(REBOOT);
        return;
    }
    try{
        m_power->restart();
        close();
    }catch(QException &e) {
        qWarning() << e.what();
    }
}

void PowerManager::suspendWidgetClicked()
{
    try{
        emit switchToUser();
	m_power->suspend();
    }catch(QException &e) {
        qWarning() << e.what();
    }
}

void PowerManager::hibernateWidgetClicked()
{
    try{
        emit switchToUser();
    m_power->hibernate();
    }catch(QException &e) {
        qWarning() << e.what();
    }
}

void PowerManager::refreshTranslate()
{
      switchLabel->setText(tr("Switch User"));
      rebootLabel->setText(tr("Restart"));
      shutdownLabel->setText(tr("Power Off"));
}

void PowerManager::initUI()
{
    setSpacing(30);

//    actService = new QDBusInterface("org.freedesktop.Accounts",
//                                    "/org/freedesktop/Accounts",
//                                    "org.freedesktop.Accounts",
//                                    QDBusConnection::systemBus());

//    QDBusMessage ret = actService->call("ListCachedUsers");
//    QList<QVariant> outArgs = ret.arguments();
//    QVariant first = outArgs.at(0);
//    const QDBusArgument &dbusArgs = first.value<QDBusArgument>();
//    dbusArgs.beginArray();
//    QDBusObjectPath path;
//    int userCount =0;
//    while (!dbusArgs.atEnd())
//    {
//        userCount++;
//        dbusArgs >> path;
//    }
//    dbusArgs.endArray();
//    if(userCount > 1){
//        switchWidget = new QWidget(this);
//        switchWidget->setObjectName("switchWidget");
//        QLabel *switchFace = new QLabel(this);
//        switchLabel =  new QLabel(this);
//        switchFace->setAlignment(Qt::AlignCenter);
//	switchFace->setObjectName("switchFace");
//	switchFace->installEventFilter(this);
//        switchLabel->setAlignment(Qt::AlignCenter);
//        switchFace->setPixmap(QPixmap(":/images/avatar.png").scaled(58,58));
//        switchLabel->setText(tr("Switch User"));
//        switchWidget->setFixedSize(ITEM_WIDTH,ITEM_HEIGHT);
//        QVBoxLayout *switchlayout = new QVBoxLayout(switchWidget);
//        switchlayout->addWidget(switchFace);
//        switchlayout->addWidget(switchLabel);
//    }
    rebootWidget = new QWidget(this);
    rebootWidget->setObjectName("rebootWidget");
    QWidget *rbLabelWidget = new QWidget(this);
    rbLabelWidget->setFixedSize(130, 130);
    QLabel *rebootFace = new QLabel(rbLabelWidget);
    rebootLabel = new QLabel(this);
    rebootFace->setAlignment(Qt::AlignCenter);
    rebootFace->setObjectName("rebootFace");
    rebootFace->installEventFilter(this);
    rebootLabel->setAlignment(Qt::AlignCenter);
    rebootFace->setPixmap(QPixmap(":/images/reboot.png").scaled(58,58));
    rebootLabel->setText(tr("Restart"));
    rebootWidget->setFixedSize(ITEM_WIDTH,ITEM_HEIGHT);
    QVBoxLayout *rebootlayout = new QVBoxLayout(rebootWidget);
    rebootlayout->addWidget(rbLabelWidget);
    rebootlayout->addWidget(rebootLabel);
    
    shutdownWidget = new QWidget(this);
    shutdownWidget->setObjectName("shutdownWidget");
    QWidget *shLabelWidget = new QWidget(this);
    shLabelWidget->setFixedSize(130, 130);
    QLabel *shutdownFace  = new QLabel(shLabelWidget);
    shutdownLabel = new QLabel(this);
    shutdownLabel->setAlignment(Qt::AlignCenter);
    shutdownFace->setAlignment(Qt::AlignCenter);
    shutdownFace->setObjectName("shutdownFace");
    shutdownFace->installEventFilter(this);
    shutdownFace->setPixmap(QPixmap(":/images/shutdown.png").scaled(58,58));
    shutdownLabel->setText(tr("Shut Down"));
    shutdownWidget->setFixedSize(ITEM_WIDTH,ITEM_HEIGHT);
    QVBoxLayout *shutdownlayout = new QVBoxLayout(shutdownWidget);
    shutdownlayout->addWidget(shLabelWidget);
    shutdownlayout->addWidget(shutdownLabel);

    if(m_power->canHibernate()) {
        hibernateWidget = new QWidget(this);
        hibernateWidget->setObjectName("hibernateWidget");
        QWidget *hbLabelWidget = new QWidget(this);
        hbLabelWidget->setFixedSize(130, 130);
        QLabel *hibernateFace = new QLabel(hbLabelWidget);
        QLabel *hibernateLabel = new QLabel(this);
        hibernateFace->setAlignment(Qt::AlignCenter);
    hibernateFace->setObjectName("hibernateFace");
        hibernateFace->installEventFilter(this);
        hibernateLabel->setAlignment(Qt::AlignCenter);
        hibernateFace->setPixmap(QPixmap(":/images/hibernate.png").scaled(48,48));
        hibernateLabel->setText(tr("Hibernate"));
        hibernateWidget->setFixedSize(ITEM_WIDTH,ITEM_HEIGHT);
        QVBoxLayout *hibernatelayout = new QVBoxLayout(hibernateWidget);
        hibernatelayout->addWidget(hbLabelWidget);
        hibernatelayout->addWidget(hibernateLabel);
        listLabel.append(hibernateFace);
    }

    if(m_power->canSuspend()){
        suspendWidget = new QWidget(this);
        suspendWidget->setObjectName("suspendWidget");
        QWidget *spLabelWidget = new QWidget(this);
        spLabelWidget->setFixedSize(130, 130);
        QLabel *suspendFace = new QLabel(spLabelWidget);
    	QLabel *suspendLabel = new QLabel(this);
    	suspendFace->setAlignment(Qt::AlignCenter);
	suspendFace->setObjectName("suspendFace");
        suspendFace->installEventFilter(this);
        suspendLabel->setAlignment(Qt::AlignCenter);
        suspendFace->setPixmap(QPixmap(":/images/suspend.png").scaled(48,48));
        suspendLabel->setText(tr("Suspend"));
    	suspendWidget->setFixedSize(ITEM_WIDTH,ITEM_HEIGHT);
    	QVBoxLayout *suspendlayout = new QVBoxLayout(suspendWidget);
        suspendlayout->addWidget(spLabelWidget);
    	suspendlayout->addWidget(suspendLabel);
        listLabel.append(suspendFace);
    }


//   if(userCount>1){
//        QListWidgetItem *item0 = new QListWidgetItem();
//        item0->setSizeHint(QSize(ITEM_WIDTH, ITEM_HEIGHT));
//        insertItem(this->count(), item0);
//        setItemWidget(item0, switchWidget);
//    }
    if(m_power->canHibernate()){
        QListWidgetItem *item1 = new QListWidgetItem();
        item1->setSizeHint(QSize(ITEM_WIDTH, ITEM_HEIGHT));
        insertItem(this->count(), item1);
        setItemWidget(item1, hibernateWidget);
    }

    if(m_power->canSuspend()){
        QListWidgetItem *item0 = new QListWidgetItem();
        item0->setSizeHint(QSize(ITEM_WIDTH, ITEM_HEIGHT));
        insertItem(this->count(), item0);
        setItemWidget(item0, suspendWidget);
    }

    QListWidgetItem *item2 = new QListWidgetItem();
    item2->setSizeHint(QSize(ITEM_WIDTH, ITEM_HEIGHT));
    insertItem(this->count(), item2);
    setItemWidget(item2, rebootWidget);
    listLabel.append(rebootFace);

    QListWidgetItem *item3 = new QListWidgetItem();
    item3->setSizeHint(QSize(ITEM_WIDTH, ITEM_HEIGHT));
    insertItem(this->count(), item3);
    setItemWidget(item3, shutdownWidget);
    listLabel.append(shutdownFace);

    adjustSize();

}
