#!/usr/bin/env python3

import os
import contextlib

from PyQt5 import QtCore, QtWidgets

from dsrlib.settings import Settings


class LayoutBuilder:
    def __init__(self, target):
        self.target = target
        self._stack = []

    @contextlib.contextmanager
    def _layout(self, cls, *args, **kwargs):
        layout = cls()
        self._stack.append(layout)
        try:
            yield layout
        finally:
            self._pop(*args, **kwargs)

    def _pop(self, *args, **kwargs):
        layout = self._stack.pop()
        if self._stack:
            parent = self._stack[-1]
            if isinstance(layout, QtWidgets.QSplitter):
                parent.addWidget(layout)
            else:
                if isinstance(parent, QtWidgets.QSplitter):
                    container = QtWidgets.QWidget(parent)
                    container.setLayout(layout)
                    parent.addWidget(container)
                else:
                    parent.addLayout(layout, *args, **kwargs)
        elif isinstance(self.target, QtWidgets.QMainWindow):
            if isinstance(layout, QtWidgets.QSplitter):
                self.target.setCentralWidget(layout)
            else:
                container = QtWidgets.QWidget(self.target)
                container.setLayout(layout)
                self.target.setCentralWidget(container)
        else:
            if isinstance(layout, QtWidgets.QSplitter):
                layout2 = QtWidgets.QHBoxLayout()
                layout2.setContentsMargins(0, 0, 0, 0)
                layout2.addWidget(layout)
                self.target.setLayout(layout2)
            else:
                self.target.setLayout(layout)

    @contextlib.contextmanager
    def hbox(self, *args, **kwargs): # pragma: no cover
        with self._layout(QtWidgets.QHBoxLayout, *args, **kwargs) as layout:
            layout.setContentsMargins(1, 1, 1, 1)
            layout.setSpacing(1)
            yield layout

    @contextlib.contextmanager
    def vbox(self, *args, **kwargs): # pragma: no cover
        with self._layout(QtWidgets.QVBoxLayout, *args, **kwargs) as layout:
            layout.setContentsMargins(1, 1, 1, 1)
            layout.setSpacing(1)
            yield layout

    def stack(self, *args, **kwargs): # pragma: no cover
        return self._layout(QtWidgets.QStackedLayout, *args, **kwargs)

    def form(self, *args, **kwargs):
        class _FormLayout(QtWidgets.QFormLayout):
            def addLayout(self, layout):
                self.addRow(layout)

            def addRow(self, label, widget=None): # pylint: disable=C0111
                if isinstance(label, str):
                    label = QtWidgets.QLabel(label)
                    label.setSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Expanding)
                    label.setAlignment(QtCore.Qt.AlignVCenter)
                if widget is None:
                    super().addRow(label)
                else:
                    super().addRow(label, widget)

        return self._layout(_FormLayout, *args, **kwargs)

    def split(self, *args, **kwargs): # pragma: no cover
        return self._layout(QtWidgets.QSplitter, *args, **kwargs)


def getSaveFilename(parent, domain, extension):
    with Settings().grouped('Paths') as settings:
        path = QtCore.QStandardPaths.writableLocation(QtCore.QStandardPaths.DocumentsLocation)
        sname = 'save_%s' % domain
        if settings.contains(sname):
            path = settings.value(sname)

        while True:
            name, dummy = QtWidgets.QFileDialog.getSaveFileName(parent, _('Save'), path, '*.%s' % extension, options=QtWidgets.QFileDialog.DontConfirmOverwrite)
            if not name:
                return None
            if not name.endswith('.%s' % extension):
                name = '%s.%s' % (name, extension)
            if os.path.exists(name):
                resp = QtWidgets.QMessageBox.question(parent,
                                                      _('Overwrite file?'),
                                                      _('This file already exists. Overwrite?'),
                                                      QtWidgets.QMessageBox.Yes|QtWidgets.QMessageBox.No|QtWidgets.QMessageBox.Cancel)
                if resp == QtWidgets.QMessageBox.Yes:
                    settings.setValue(sname, os.path.dirname(name))
                    return name
                if resp == QtWidgets.QMessageBox.No:
                    continue
                return None
            settings.setValue(sname, os.path.dirname(name))
            return name


def getOpenFilename(parent, domain, extension):
    with Settings().grouped('Paths') as settings:
        path = QtCore.QStandardPaths.writableLocation(QtCore.QStandardPaths.DocumentsLocation)
        sname = 'open_%s' % domain
        if settings.contains(sname):
            path = settings.value(sname)

        name, dummy = QtWidgets.QFileDialog.getOpenFileName(parent, _('Open file'), path, '*.%s' % extension if extension else '')
        if name:
            settings.setValue(sname, os.path.dirname(name))
            return name
        return None


class EnumComboBox(QtWidgets.QComboBox):
    valueChanged = QtCore.pyqtSignal(object)

    def __init__(self, *args, enum, value=None, **kwargs):
        super().__init__(*args, **kwargs)
        self._enum = enum
        for item in enum:
            self.addItem(enum.label(item), item)
        if value is not None:
            self.setValue(value)
        self.currentIndexChanged.connect(self._emit)

    def setValue(self, value):
        for index, item in enumerate(self._enum):
            if value == item:
                self.setCurrentIndex(index)
                break
        else:
            raise ValueError('Value "%s" not found in enum' % str(value))

    def _emit(self, _):
        self.valueChanged.emit(self.currentData())

[((135, 19, 135, 44), 'PyQt5.QtCore.pyqtSignal', 'QtCore.pyqtSignal', ({(135, 37, 135, 43): 'object'}, {}), '(object)', False, 'from PyQt5 import QtCore, QtWidgets\n'), ((94, 15, 94, 94), 'PyQt5.QtCore.QStandardPaths.writableLocation', 'QtCore.QStandardPaths.writableLocation', ({(94, 54, 94, 93): 'QtCore.QStandardPaths.DocumentsLocation'}, {}), '(QtCore.QStandardPaths.DocumentsLocation)', False, 'from PyQt5 import QtCore, QtWidgets\n'), ((122, 15, 122, 94), 'PyQt5.QtCore.QStandardPaths.writableLocation', 'QtCore.QStandardPaths.writableLocation', ({(122, 54, 122, 93): 'QtCore.QStandardPaths.DocumentsLocation'}, {}), '(QtCore.QStandardPaths.DocumentsLocation)', False, 'from PyQt5 import QtCore, QtWidgets\n'), ((105, 15, 105, 35), 'os.path.exists', 'os.path.exists', ({(105, 30, 105, 34): 'name'}, {}), '(name)', False, 'import os\n'), ((93, 9, 93, 19), 'dsrlib.settings.Settings', 'Settings', ({}, {}), '()', False, 'from dsrlib.settings import Settings\n'), ((116, 37, 116, 58), 'os.path.dirname', 'os.path.dirname', ({(116, 53, 116, 57): 'name'}, {}), '(name)', False, 'import os\n'), ((121, 9, 121, 19), 'dsrlib.settings.Settings', 'Settings', ({}, {}), '()', False, 'from dsrlib.settings import Settings\n'), ((129, 37, 129, 58), 'os.path.dirname', 'os.path.dirname', ({(129, 53, 129, 57): 'name'}, {}), '(name)', False, 'import os\n'), ((33, 32, 33, 57), 'PyQt5.QtWidgets.QWidget', 'QtWidgets.QWidget', ({(33, 50, 33, 56): 'parent'}, {}), '(parent)', False, 'from PyQt5 import QtCore, QtWidgets\n'), ((42, 28, 42, 58), 'PyQt5.QtWidgets.QWidget', 'QtWidgets.QWidget', ({(42, 46, 42, 57): 'self.target'}, {}), '(self.target)', False, 'from PyQt5 import QtCore, QtWidgets\n'), ((47, 26, 47, 49), 'PyQt5.QtWidgets.QHBoxLayout', 'QtWidgets.QHBoxLayout', ({}, {}), '()', False, 'from PyQt5 import QtCore, QtWidgets\n'), ((78, 28, 78, 51), 'PyQt5.QtWidgets.QLabel', 'QtWidgets.QLabel', ({(78, 45, 78, 50): 'label'}, {}), '(label)', False, 'from PyQt5 import QtCore, QtWidgets\n'), ((111, 45, 111, 66), 'os.path.dirname', 'os.path.dirname', ({(111, 61, 111, 65): 'name'}, {}), '(name)', False, 'import os\n')]