# Copyright (C) 2010 Canonical 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
# of the License, 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 Street, Fifth Floor, Boston, MA 02110-1301, USA.

"""Generic panel construction, given a list of options.

TODO: move this into the QBzr layer and use it in qrun.
"""

from PyQt4 import QtCore, QtGui

from bzrlib.option import Option, RegistryOption
from bzrlib.trace import mutter

from bzrlib.plugins.explorer.lib import helpers
from bzrlib.plugins.explorer.lib.i18n import gettext

from bzrlib.plugins.explorer.widgets.filesystem_browser import DirectoryBrowser


class OptionsPanel(QtGui.QWidget):
    """A widget for editing an arbitary list of options."""

    def __init__(self, opts, *args):
        QtGui.QWidget.__init__(self, *args)
        self._widget_by_opt_name = {}
        if opts:
            self.setLayout(self._build_layout(opts))

    def _build_layout(self, opts):
        layout = QtGui.QFormLayout()
        layout.setContentsMargins(0, 0, 0, 0)
        # Keep it simple for now, adding parameters in the order given.
        # Widgets are mapped as follows:
        # * Registry options => combo-boxes
        # * Boolean options => checkboxes
        # * String options => text fields
        for o in opts:
            if isinstance(o, RegistryOption):
                label = self._name_as_label(o.name)
                reg = o.registry
                data_values = [(k, reg.get_help(k))
                    for k in sorted(reg.keys())]
                widget = helpers.build_combo_with_labels(data_values)
                # Set the default value
                default_index = widget.findData(QtCore.QVariant(reg.default_key))
                widget.setCurrentIndex(default_index)
                # TODO: make the combo box the minimum size
                layout.addRow(label, widget)
            elif o.type is None:
                # Strip the trailing full-stop from the help
                label = gettext(o.help.rstrip('.'))
                widget = QtGui.QCheckBox(label)
                layout.addRow(widget)
            elif o.type == "location":
                label = self._name_as_label(o.name)
                widget = DirectoryBrowser()
                layout.addRow(label, widget)
            else:
                label = self._name_as_label(o.name)
                widget = QtGui.QLineEdit()
                layout.addRow(label, widget)
            self._widget_by_opt_name[o.name] = widget
        return layout

    def _name_as_label(self, name):
        text = name.capitalize()
        text = text.replace("-", " ")
        return gettext(text + ":")

    def set_values(self, dict):
        """Set option values.

        :param dict: a map from option names to values.
        """
        for k, v in dict.items():
            try:
                widget = self._widget_by_opt_name[k]
            except KeyError:
                continue
            if isinstance(widget, QtGui.QCheckBox):
                widget.setChecked(v)
            elif isinstance(widget, QtGui.QLineEdit):
                widget.setText(v)
            elif isinstance(widget, DirectoryBrowser):
                widget.setText(v)
            elif isinstance(widget, QtGui.QComboBox):
                index = widget.findData(QtCore.QVariant(v))
                widget.setCurrentIndex(index)
            else:
                mutter("Cannot set a value for %s widgets yet",
                    widget.__class_)

    def get_values(self):
        """Get option values.

        :return: a map from option names to values.
        """
        result = {}
        for k, widget in self._widget_by_opt_name.items():
            if isinstance(widget, QtGui.QCheckBox):
                result[k] = widget.isChecked()
            elif isinstance(widget, QtGui.QLineEdit):
                result[k] = unicode(widget.text())
            elif isinstance(widget, DirectoryBrowser):
                result[k] = unicode(widget.text())
            elif isinstance(widget, QtGui.QComboBox):
                index = widget.currentIndex()
                result[k] = unicode(widget.itemData(index).toString())
            else:
                mutter("Cannot get a value for %s widgets yet",
                    widget.__class_)
        return result
