#!/usr/bin/env python

import sys
import traceback

import taurus
from taurus.qt import Qt
from taurus.qt.qtgui.application import TaurusApplication
from taurus.qt.qtgui.container import QGroupWidget
from taurus.qt.qtgui.display import TaurusLabel, TaurusLed
from taurus.qt.qtgui.input import TaurusValueSpinBox, TaurusValueSpinBoxEx
from taurus.qt.qtgui.resource import getIcon, getThemeIcon
from taurus.qt.qtgui.console import TaurusConsole
from taurus.qt.qtgui.panel import TaurusAttrForm
from taurus.qt.qtgui.button import TaurusCommandButton, TaurusLockButton, \
    TaurusLauncherButton

Spin = TaurusValueSpinBox


class CmdButton(TaurusCommandButton):

    def getDisplayValue(self):
        return ""


class CfgButton(TaurusLauncherButton):

    def getDisplayValue(self):
        return ""

DFT_STATE_ICON_SIZE = Qt.QSize(24, 24)
DFT_BTN_ICON_SIZE = Qt.QSize(20, 20)
LS_ICON_SIZE = Qt.QSize(16, 16)
DFT_BTN_STYLE = "QPushButton {margin: 0px; padding: 0px;}"


def createPoolPanel(name):
    panel = QGroupWidget()
    panel.titleIcon = getIcon(":/applications-system.svg")
    content = panel.content()
    panel_l = Qt.QGridLayout()
    content.setLayout(panel_l)

    stop = TaurusCommandButton(parent=content, command='Stop')
    stop.setIcon(getIcon(":/stop_sign.svg"))
    stop.setIconSize(Qt.QSize(48, 48))
    # stop.setStyleSheet(DFT_BTN_STYLE)
    # stop.setFlat(True)
    stop.Model = name
    panel_l.addWidget(stop, 0, 0)

    abort = TaurusCommandButton(parent=content, command='Abort')
    abort.setIcon(getIcon(":/panic_button.png"))
    abort.setIconSize(Qt.QSize(48, 48))
    # abort.setStyleSheet(DFT_BTN_STYLE)
    # abort.setFlat(True)
    abort.Model = name
    panel_l.addWidget(abort, 0, 1)

    return panel


def createMotorPanel(*names):
    m_panel = QGroupWidget()
    m_panel.titleIcon = getIcon(":/designer/extra_motor.png")
    content = m_panel.content()
    m_panel_l = createMotorLayout(content, *names)
    content.setLayout(m_panel_l)
    return m_panel


def createMotorLayout(content, *names):
    m_panel_l = Qt.QGridLayout()
    m_panel_l.setMargin(4)
    m_panel_l.setHorizontalSpacing(2)
    m_panel_l.setVerticalSpacing(2)
    monospace = Qt.QFont("Monospace", 10)
    monospace_small = Qt.QFont("Monospace", 8)
    for i, name in enumerate(names):
        row = i * 2
        motor = taurus.Device(name)
        motor_attrs = [attr.lower() for attr in motor.get_attribute_list()]

        state = TaurusLed(content)
        state.setMinimumSize(DFT_STATE_ICON_SIZE)
        state.setMaximumSize(DFT_STATE_ICON_SIZE)
        state.model = motor.getNormalName() + "/state"
        m_panel_l.addWidget(state, row, 0)

        label = TaurusLabel(content)
        label.model = name + "/position?configuration=dev_alias"
        label.bgRole = None
        m_panel_l.addWidget(label, row, 1)

        r_value = TaurusLabel(content)
        r_value.setMinimumWidth(80)
        r_value.model = name + "/position"
        m_panel_l.addWidget(r_value, row, 2)

        w_value = Spin(content)
        w_value.setMinimumWidth(100)
        w_value.model = name + "/position"
        m_panel_l.addWidget(w_value, row, 3)

        unit = TaurusLabel(content)
        unit.model = name + "/position?configuration=unit"
        unit.bgRole = None
        m_panel_l.addWidget(unit, row, 4)

        stop = CmdButton(parent=content, command='stop')
        stop.setIcon(getIcon(":/stop_sign.svg"))
        stop.setIconSize(DFT_BTN_ICON_SIZE)
        stop.setStyleSheet(DFT_BTN_STYLE)
        stop.setFlat(True)
        stop.Model = name
        m_panel_l.addWidget(stop, row, 5)

        abort = CmdButton(parent=content, command='abort')
        abort.setIcon(getIcon(":/panic_button.png"))
        abort.setIconSize(DFT_BTN_ICON_SIZE)
        abort.setStyleSheet(DFT_BTN_STYLE)
        abort.setFlat(True)
        abort.Model = name
        m_panel_l.addWidget(abort, row, 6)

        lock = TaurusLockButton(content)
        lock.setIconSize(DFT_BTN_ICON_SIZE)
        lock.setStyleSheet(DFT_BTN_STYLE)
        lock.setFlat(True)
        lock.model = name
        m_panel_l.addWidget(lock, row, 7)

        w = TaurusAttrForm()
        w.setMinimumSize(Qt.QSize(500, 700))
        cfg = CfgButton(widget=w, icon=":/categories/preferences-system.svg")
        cfg.setIconSize(DFT_BTN_ICON_SIZE)
        cfg.setStyleSheet(DFT_BTN_STYLE)
        cfg.setModel(name)
        m_panel_l.addWidget(cfg, row, 8)

        status = TaurusLabel(content)
        font = Qt.QFont(status.font())
        font.setPointSize(8)
        status.setFont(font)
        status.model = name + "/status"
        status.bgRole = None
        m_panel_l.addWidget(status, row + 1, 3, 1, 6)

        if "dialposition" in motor_attrs:
            dial = TaurusLabel(content)
            dial.model = name + "/dialposition"
            m_panel_l.addWidget(dial, row + 1, 2)

        if "limit_switches" in motor_attrs:
            limitswitches = TaurusLed(content), TaurusLed(
                content), TaurusLed(content)
            lmswtch_l = Qt.QVBoxLayout()
            for n, lm_swtch_w in enumerate(limitswitches):
                lm_swtch_w.setMinimumSize(LS_ICON_SIZE)
                lm_swtch_w.setMaximumSize(LS_ICON_SIZE)
                lmswtch_l.addWidget(lm_swtch_w)
                lm_swtch_w.model = name + "/limit_switches"
                lm_swtch_w.modelIndex = n
                lm_swtch_w.onColor = "red"
            m_panel_l.addItem(lmswtch_l, row, 9, 2, 1)

        m_panel_l.setRowStretch(row, 0)
        m_panel_l.setRowStretch(row + 1, 0)

    m_panel_l.setRowStretch(row + 2, 1)
    m_panel_l.setColumnStretch(0, 0)
    m_panel_l.setColumnStretch(1, 0)
    m_panel_l.setColumnStretch(2, 1)
    m_panel_l.setColumnStretch(3, 1)
    m_panel_l.setColumnStretch(4, 0)
    m_panel_l.setColumnStretch(5, 0)
    m_panel_l.setColumnStretch(6, 0)
    return m_panel_l


def createMotorGroupPanel(*names):
    m_panel = QGroupWidget()
    m_panel.titleIcon = getIcon(":/designer/extra_motor.png")
    m_panel_l = Qt.QGridLayout()
    content = m_panel.content()
    content.setLayout(m_panel_l)

    name = names[0]
    mg = taurus.Device(name)
    elements = mg.elementlist
    state = TaurusLed(content)
    state.setMinimumSize(24, 24)
    label = TaurusLabel(content)
    m_panel_l.addWidget(state, 0, 0)
    m_panel_l.addWidget(label, 0, 1)
    go = Qt.QPushButton("Go")
    m_panel_l.addWidget(go, 0, 2)
    m_panel_l.setRowStretch(0, 0)
    w_pos_widgets = []
    for i, element in enumerate(elements):
        row = i + 1
        m_label = Qt.QLabel(element, content)
        m_panel_l.addWidget(m_label, row, 0)
        r_value = TaurusLabel(content)
        r_value.model = name + "/position"
        r_value.modelIndex = str(i)
        m_panel_l.addWidget(r_value, row, 1)
        w_value = Qt.QDoubleSpinBox()
        w_value.setMinimum(float("-inf"))
        w_value.setMaximum(float("+inf"))
        m_panel_l.addWidget(w_value, row, 2)
        m_panel_l.setRowStretch(row, 0)
        w_pos_widgets.append(w_value)
    state.model = name + "/state"
    label.model = name + "/position?configuration=dev_alias"
    label.bgRole = None

    go._mg = state.getModelObj().getParentObj()
    go._positions = w_pos_widgets

    class MoveIt(Qt.QObject):

        def move(self):
            try:
                button = self.sender()
                positions = [w.value() for w in button._positions]
                button._mg.write_attribute("position", positions)
            except:
                traceback.print_exc()
    go._move = MoveIt()
    Qt.QObject.connect(go, Qt.SIGNAL("clicked()"), go._move.move)
    m_panel_l.setRowStretch(i + 2, 1)
    m_panel_l.setColumnStretch(0, 0)
    m_panel_l.setColumnStretch(1, 0)
    m_panel_l.setColumnStretch(2, 1)
    m_panel_l.setColumnStretch(3, 1)
    return m_panel

app = TaurusApplication()
app.setTaurusStyle("nebula")
panel = Qt.QMainWindow()
panel.setWindowTitle("Pool Motor Test GUI")

dock1 = Qt.QDockWidget("Motors Panel")
panel.addDockWidget(Qt.Qt.LeftDockWidgetArea, dock1)
dock1_w = Qt.QWidget()
dock1.setWidget(dock1_w)

dock2 = Qt.QDockWidget("Motor Groups Panel")
panel.addDockWidget(Qt.Qt.LeftDockWidgetArea, dock2)
dock2_w = Qt.QWidget()
dock2.setWidget(dock2_w)

# MOTOR PANEL ------------------------------------------------------------

panel1_l = Qt.QGridLayout()
panel1_l.setContentsMargins(4, 4, 4, 4)
panel1_l.setSpacing(4)
dock1_w.setLayout(panel1_l)

pool_panel = createPoolPanel("Pool_V3_1")
pool_panel.title = "Main Control Panel"
panel1_l.addWidget(pool_panel, 0, 0)

motors = ["motor%02d" % i for i in range(1, 5)]
m1_panel = createMotorPanel(*motors)
m1_panel.title = "Motors on motorctrl01"
panel1_l.addWidget(m1_panel, 1, 0)

pm1_panel = createMotorPanel("GAP01", "OFFSET01")
pm1_panel.title = "Pseudo motors"
panel1_l.addWidget(pm1_panel, 2, 0, 1, 1)

panel1_l.setRowStretch(0, 0)
panel1_l.setRowStretch(1, 1)

# MOTOR GROUP PANEL ------------------------------------------------------

mg_panel_style = {
    'start_color': 'rgb(255, 60, 60)',
    'stop_color': 'rgb(200, 0, 0)',
    'font_color': 'rgb(0, 0, 0)',
    #'border_radius': '10px',
}

panel2_l = Qt.QGridLayout()
panel2_l.setContentsMargins(4, 4, 4, 4)
panel2_l.setSpacing(4)
dock2_w.setLayout(panel2_l)

mg1_panel = createMotorGroupPanel("motgrp01")
mg1_panel.title = "Motor Group 1"
mg1_panel.setTitleStyle(mg_panel_style)
panel2_l.addWidget(mg1_panel, 0, 0)

mg2_panel = createMotorGroupPanel("motgrp02")
mg2_panel.title = "Motor Group 2"
mg2_panel.setTitleStyle(mg_panel_style)
panel2_l.addWidget(mg2_panel, 0, 1)

panel2_l.setRowStretch(0, 0)
panel2_l.setRowStretch(1, 1)

# MAIN -------------------------------------------------------------------

panel.show()
sys.exit(app.exec_())
