#include "MainOverLay.h"

#include <glib.h>
#include <glib/gi18n.h>
#include "ImageButton.h"

#include "config.h"
#include "Common.h"
#include "UserItem.h"
#include "DmGreeterHelper.h"

#define DATE_LABEL_MARKUP_FORMAT "<span foreground=\"#ffffff\" font_desc=\"20\">\%1</span>"
#define DATE_FORMAT_STRING_FOR_24 "%A %x %R"
#define DATE_FORMAT_STRING_FOR_12 "%A %x %p %I:%M"
#define DEFAULT_RELOAD_DATE_TIME_INTERVAL (10000)

#define DEFAULT_SCREEN_WIDTH  (1920.0f)
#define DEFAULT_SCREEN_HEIGHT (1080.0f)

#define KEY_STATE_MASK (GDK_CONTROL_MASK | GDK_SHIFT_MASK)

MainOverLay::MainOverLay(Gtk::Overlay* parent)
    : m_mainlyt(parent)
    , m_toolsLayout(Gtk::ORIENTATION_HORIZONTAL, 0)
    , m_reloadTimeHdl(Glib::TimeoutSource::create(DEFAULT_RELOAD_DATE_TIME_INTERVAL)) {

    Common::getPrimaryScaleFactors(m_scaleX, m_scaleY);

    m_reloadTimeIter = m_reloadTimeHdl->connect(sigc::mem_fun(*this, &MainOverLay::reloadDateTime));

    m_userStack.set_margin_top((int)(194 * m_scaleY));

    m_userStack.add(m_selectView, "select");
    m_userStack.add(m_loginView, "login");

    m_userStack.set_halign(Gtk::ALIGN_CENTER);
    m_userStack.set_valign(Gtk::ALIGN_START);

    m_switchIter = m_loginView.signalSwitchUser().connect(sigc::mem_fun(*this, &MainOverLay::onSwitchUser));
    m_userSelIter = m_selectView.signalUserItemPress().connect(sigc::mem_fun(*this, &MainOverLay::onUserSelected));

    initNecessaryLayout();
    initShutdownBtn();
    initDatetimeArea();

    packLayouts();

    Common::addCssStylePath(m_dateTimeLabel, GLOBAL_RES_DIR"/style/cdos-login.css", G_MAXUINT);
    Common::addCssStylePath(m_userStack, GLOBAL_RES_DIR"/style/cdos-login.css", G_MAXUINT);
    Common::addCssStylePath(m_toolsLayout, GLOBAL_RES_DIR"/style/cdos-login.css", G_MAXUINT);

    m_userStack.set_visible_child("select");

    m_selectView.resetFocus();
}

MainOverLay::~MainOverLay() {
    m_reloadTimeIter.disconnect();
    m_switchIter.disconnect();
    m_userSelIter.disconnect();

    m_rebootOptIter.disconnect();
    m_powerOptIter.disconnect();
    m_suspOptIter.disconnect();
}

bool MainOverLay::doKeyPressed(GdkEventKey* event) {
    if (GDK_KEY_PRESS == event->type) {
        switch (event->keyval) {
        case GDK_KEY_Tab:
        case GDK_KEY_KP_Tab:
            if (m_shutDownButton.is_focus()) {
                Glib::ustring visibleChildName = m_userStack.get_visible_child_name();
                if ("login" == visibleChildName) {
                    m_loginView.resetFocus();
                } else if ("select" == visibleChildName) {
                    m_selectView.resetFocus();
                } else {

                }
                return true;
            }
            break;
        case GDK_KEY_Down:
        case GDK_KEY_Page_Down:
        case GDK_KEY_KP_Down:
        case GDK_KEY_KP_Page_Down:
        case GDK_KEY_Left:
        case GDK_KEY_KP_Left:
            m_selectView.prePage();
            break;
        case GDK_KEY_Up:
        case GDK_KEY_Page_Up:
        case GDK_KEY_KP_Up:
        case GDK_KEY_KP_Page_Up:
        case GDK_KEY_Right:
        case GDK_KEY_KP_Right:
            m_selectView.nextPage();
            break;
        case GDK_KEY_P:
        case GDK_KEY_p:
            if (GDK_CONTROL_MASK != (event->state & KEY_STATE_MASK)) {
                return false;
            }
            m_shutDownButton.requestPopover();
            break;
        case GDK_KEY_Escape:
            if ("login" == m_userStack.get_visible_child_name()) {
                m_loginView.requestSwitchUser();
            }
            break;
        case GDK_KEY_1:
        case GDK_KEY_2:
        case GDK_KEY_3:
        case GDK_KEY_4:
        case GDK_KEY_5:
        case GDK_KEY_6:
        case GDK_KEY_7:
        case GDK_KEY_8:
        case GDK_KEY_9:
            if (GDK_CONTROL_MASK == (event->state & KEY_STATE_MASK)) {
                if ("select" == m_userStack.get_visible_child_name()) {
                    m_selectView.selectUserByNum(event->keyval - GDK_KEY_0); 
                }
            }
            break;
        case GDK_KEY_KP_1:
        case GDK_KEY_KP_2:
        case GDK_KEY_KP_3:
        case GDK_KEY_KP_4:
        case GDK_KEY_KP_5:
        case GDK_KEY_KP_6:
        case GDK_KEY_KP_7:
        case GDK_KEY_KP_8:
        case GDK_KEY_KP_9:
            if (GDK_CONTROL_MASK == (event->state & KEY_STATE_MASK)) {
                if ("select" == m_userStack.get_visible_child_name()) {
                    m_selectView.selectUserByNum(event->keyval - GDK_KEY_KP_0); 
                }
            }
            break;
        default:
            break;
        }
    }
    return false;
}

bool MainOverLay::reloadDateTime() {
    Glib::DateTime now = Glib::DateTime::create_now_local();

    Glib::ustring timeformat = DATE_FORMAT_STRING_FOR_24;

    m_dateTimeLabel.set_markup(Glib::ustring::compose(DATE_LABEL_MARKUP_FORMAT, now.format(timeformat)));
    return true;
}

void MainOverLay::initShutdownBtn() {
    m_powerOptIter = m_shutDownButton.signalPoweroffClicked().connect(sigc::mem_fun(*this, &MainOverLay::onPoweroffClicked));
    m_rebootOptIter = m_shutDownButton.signalRebootClicked().connect(sigc::mem_fun(*this, &MainOverLay::onRestartClicked));
    m_suspOptIter = m_shutDownButton.signalSuspendClicked().connect(sigc::mem_fun(*this, &MainOverLay::onSuspendClicked));
}

void MainOverLay::initNecessaryLayout() {
    m_toolsLayout.set_halign(Gtk::ALIGN_END);
    m_toolsLayout.set_valign(Gtk::ALIGN_END);

    m_toolsLayout.set_margin_bottom((int)(80 * m_scaleY));
    m_toolsLayout.set_margin_right((int)(80 * m_scaleX));
}

void MainOverLay::initDatetimeArea() {
    reloadDateTime();

    m_dateTimeLabel.set_halign (Gtk::ALIGN_START);
    m_dateTimeLabel.set_valign (Gtk::ALIGN_END);
    m_dateTimeLabel.set_margin_bottom((int)(86 * m_scaleY));
    m_dateTimeLabel.set_margin_left((int)(80 * m_scaleX));

    m_reloadTimeHdl->attach();
}

void MainOverLay::packLayouts() {
	m_toolsLayout.pack_end(m_shutDownButton, false, false, 0);

	if (NULL != m_mainlyt) {
        m_mainlyt->add_overlay(m_dateTimeLabel);
        m_mainlyt->add_overlay(m_userStack);

        m_mainlyt->add_overlay(m_toolsLayout);
    }
}

void MainOverLay::onUserSelected(Glib::ustring name) {
    m_loginView.setUserName(name);
    m_userStack.set_visible_child("login");
}

void MainOverLay::onSwitchUser() {
    m_userStack.set_visible_child("select");
}

void MainOverLay::onRestartClicked() {
    DmGreeterHelper::inst()->requestReboot(NULL);
}

void MainOverLay::onPoweroffClicked() {
    DmGreeterHelper::inst()->requestShutdown(NULL);
}

void MainOverLay::onSuspendClicked() {
    DmGreeterHelper::inst()->requestSuspend(NULL);
}