# -*- coding: utf-8 -*-
#
# QBrz - Qt frontend to Breezy commands
# Copyright (C) 2009 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.

from PyQt5 import QtCore, QtGui, QtWidgets

from breezy import controldir, errors, log
from breezy.revisionspec import RevisionSpec

from breezy.plugins.qbrz.lib.html_log import log_as_html
from breezy.plugins.qbrz.lib.i18n import gettext
from breezy.plugins.qbrz.lib.subprocess import SubProcessDialog
from breezy.plugins.qbrz.lib.trace import reports_exception, SUB_LOAD_METHOD
from breezy.plugins.qbrz.lib.util import url_for_display


class QBzrUncommitWindow(SubProcessDialog):

    def __init__(self, location, dialog=True, ui_mode=True, parent=None,
            local=None, message=None):
        super(QBzrUncommitWindow, self).__init__(
                                  gettext("Uncommit"),
                                  name="uncommit",
                                  default_size=(400, 400),
                                  ui_mode=ui_mode,
                                  dialog=dialog,
                                  parent=parent,
                                  hide_progress=True,
                                  )
        self.tree, self.branch = controldir.ControlDir.open_tree_or_branch(location)

        # Display the branch
        branch_label = QtWidgets.QLabel(gettext("Branch: %s") % url_for_display(self.branch.base))

        # Display the revision selection section. We nearly always
        # want to just uncommit the last revision (to tweak the
        # commit message say) so we make that the default.
        groupbox = QtWidgets.QGroupBox(gettext("Move tip to"), self)
        self.last_radio = QtWidgets.QRadioButton(gettext("Parent of current tip revision"))
        self.last_radio.setChecked(QtCore.Qt.Checked)
        self.other_radio = QtWidgets.QRadioButton(gettext("Other revision:"))
        self.other_revision = QtWidgets.QLineEdit()
        other = QtWidgets.QHBoxLayout()
        other.addWidget(self.other_radio)
        other.addWidget(self.other_revision)
        vbox = QtWidgets.QVBoxLayout(groupbox)
        vbox.addWidget(self.last_radio)
        vbox.addLayout(other)

        # If the user starts entering a value in the 'other revision' field,
        # set the matching radio button implicitly
        self.other_revision.textChanged['QString'].connect(self.do_other_revision_changed)

        # groupbox gets disabled as we are executing.
        self.subprocessStarted[bool].connect(groupbox.setDisabled)

        # Put the form together
        layout = QtWidgets.QVBoxLayout(self)
        layout.addWidget(branch_label)
        layout.addWidget(groupbox)
        layout.addWidget(self.make_default_status_box())
        layout.addWidget(self.buttonbox)

    def do_other_revision_changed(self, text):
        if text and not self.other_radio.isChecked():
            self.other_radio.setChecked(True)

    def _revision_identifier(self):
        """What revision did the user select?

        :return: None for the last revision.
          Otherwise the revision identifier as a string.
        """
        if self.other_radio.isChecked():
            result = str(self.other_revision.text())
            if result:
                return result
            else:
                msg = gettext("No other revision specified.")
                raise errors.BzrError(msg)
        # Default is the tip revision
        return None

    @reports_exception(type=SUB_LOAD_METHOD)
    def validate(self):
        """Check that the user really wants to uncommit the given revisions."""
        revision = self._revision_identifier()
        if revision is None:
            log_rqst = log.make_log_request_dict(limit=1)
        else:
            rev_spec = RevisionSpec.from_string(revision)
            revno = rev_spec.in_history(self.branch).revno
            # We need to offset the revno by +1 because we'll be uncommitting
            # *back* to revno, meaning those after it are 'deleted'
            log_rqst = log.make_log_request_dict(start_revision=revno + 1)
        log_data = log_as_html(self.branch, log_rqst)
        question = gettext("Do you really want to uncommit these revisions?")
        if self.ask_confirmation('<font color="red">%s</font><br/>%s' % (question, log_data),type='warning'):
            return True
        return False

    def do_start(self):
        args = ['--force']
        revision = self._revision_identifier()
        if revision:
            args.append('--revision')
            args.append(revision)
        if self.tree:
            dest = self.tree.basedir
        else:
            dest = self.branch.base
        args.append(dest)
        self.process_widget.do_start(None, 'uncommit', *args)
