# 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 St, Fifth Floor, Boston, MA 02110-1301  USA


from PyQt4 import QtCore, QtGui

from bzrlib.plugins.explorer.lib import (
    kinds,
    location,
    )
from bzrlib.plugins.explorer.lib.i18n import gettext, N_
from bzrlib.plugins.qbzr.lib.help import QBzrHelpWindow


# Help text for the various tasks
_SETUP_HELP_TEMPLATE = gettext(
"""
<p>Configure your identity and preferred text editor using the
%(Configuration)s action. The settings configured here apply to
all Bazaar programs, including the command line tool (bzr).</p>
<p>Use the %(Preferences)s action to personalize Bazaar Explorer.
The settings configured here only apply to this application.</p>
""")
_DOWNLOAD_HELP_TEMPLATE = gettext(
"""
<p>Fetch a copy of a project using the %(Branch)s action.
A branch requires a little more disk space than a checkout but
operations are faster and you can work offline.</p>

<p>To fetch just a snapshot of a project, use the %(Checkout)s action.
A checkout is useful for in-house development where you have
reliable and high speed network access to the server.
If in doubt, use %(Branch)s instead of %(Checkout)s.</p>

<p>See also: <a href="help bound-branches">bound branches</a>.</p>
""")
_START_HELP_TEMPLATE = gettext(
"""
<p>To begin a new project from scratch, use the %(Initialize)s action.</p>
<p>To migrate a project from another tool, see the
<a href="help migration">Data Migration Guide</a>.
""")
_OPEN_HELP_TEMPLATE = gettext(
"""
<p>Use the %(Open)s action to work on repositories and branches
you already have locally.</p>
<p>To open and browse a remote repository or branch, use %(Open_Location)s instead.
</p>
""")

_BOUND_BRANCHES_TOPIC = gettext(
"""
<p>In a normal branch, you can commit changes locally
and only publish them to a central location when you are ready.</p>
<p>If you want changes automatically committed to both the central
and local location at the same time, create a branch and <i>bind</i>
it. The <i>Bind Branch</i> action is available under the Work menu.</p>
""")


# Formatting of an action inside text
def html_action(action, url):
    # Note: We can't get the icon path directly from the action
    # so we need to look it up in a separate table. The kinds
    # module manages that btw.
    label = action.iconText()
    icon = kinds.path_for_icon(url.lower())
    return '<a href="%s"><img src="%s" /></a>&nbsp;<b>%s</b>' % (
        url, icon, label)


class WelcomeModel(location._AbstractLocationModel):
    """A welcome page."""

    def __init__(self, location, action_callback, location_sets,
        action_provider, start_index=-1):
        """Create a welcome page model.

        :param location_sets: a list of (label, LocationSetBrowser) tuples
        :param start_index: index of the panel to open, -1 for the last one
        """
        self.location = location
        self._action_callback = action_callback
        self._location_sets = location_sets
        self._action_provider = action_provider
        self._start_index = start_index

    def kind(self):
        """What's the kind of this location?"""
        return kinds.WELCOME_PAGE

    def display_name(self):
        """Return a name suitable for displaying in a tab or title bar."""
        return self.location

    def display_icon(self):
        return kinds.icon_for_kind(self.kind())

    def view(self):
        """Return the widget to display for this location.

        :result: a QWidget
        """
        # Build the header
        header_layout = QtGui.QHBoxLayout()
        welcome_text = gettext("What would you like to do?")
        welcome_label = QtGui.QLabel()
        welcome_label.setText("<b>%s</b>" % welcome_text)
        header_layout.addWidget(welcome_label)

        # Build the action panels
        self.action_panels = QtGui.QToolBox()
        self._build_panel(self.action_panels, gettext(
            "Setup and personalize Bazaar"),
            kinds.icon_for_kind(kinds.CONFIGURATION_ACTION),
            ['Configuration', 'Preferences'],
            help=_SETUP_HELP_TEMPLATE)
        self._build_panel(self.action_panels, gettext(
           "Get project source from elsewhere"),
            kinds.icon_for_kind(kinds.DOWNLOAD_ACTION),
            ['Branch', 'Checkout'],
            help=_DOWNLOAD_HELP_TEMPLATE)
        self._build_panel(self.action_panels, gettext(
           "Start a new project"),
            kinds.icon_for_kind(kinds.START_ACTION),
           #['Initialize' 'Import'],
            ['Initialize'],
            help=_START_HELP_TEMPLATE)
        self._open_tabs = self._build_panel(self.action_panels, gettext(
           "Open an existing location"),
            kinds.icon_for_kind(kinds.OPEN_ACTION),
            ['Open', 'Open_Location'],
            help=_OPEN_HELP_TEMPLATE,
            extras=self._location_sets)

        # Start with the requested panel open
        if self._start_index == -1:
            self._start_index = self.action_panels.count() - 1
        self.action_panels.setCurrentIndex(self._start_index)

        # Put them all together
        layout = QtGui.QVBoxLayout()
        layout.addLayout(header_layout)
        layout.addWidget(self.action_panels)
        widget = QtGui.QWidget()
        widget.setLayout(layout)

        # Populate the location set browsers
        self.refresh_view()
        return widget

    def _build_panel(self, container, label, icon, action_names, help=None,
        extras=None):
        actions = [self._action_provider(a) for a in action_names]
        toolbar = self._build_actions_toolbar(actions)
        layout = QtGui.QHBoxLayout()
        layout.addWidget(toolbar)
        rh_tabs = None
        if help:
            browser = self._build_help_browser(help, action_names, actions)
            if extras:
                rh_tabs = QtGui.QTabWidget()
                rh_tabs.addTab(browser, gettext("Help"))
                for tab_label, widget in extras:
                    rh_tabs.addTab(widget, tab_label)
                layout.addWidget(rh_tabs)
            else:
                layout.addWidget(browser)
        view = QtGui.QWidget()
        view.setLayout(layout)
        container.addItem(view, icon, label)
        return rh_tabs

    def _build_actions_toolbar(self, actions):
        actions_bar = QtGui.QToolBar()
        actions_bar.setToolButtonStyle(QtCore.Qt.ToolButtonTextUnderIcon)
        actions_bar.setOrientation(QtCore.Qt.Vertical)
        for a in actions:
            if a is None:
                actions_bar.addSeparator()
            else:
                actions_bar.addAction(a)
        return actions_bar

    def _build_help_browser(self, help, action_names, actions):
        action_texts = [html_action(a, url) for a, url in
            zip(actions, action_names)]
        params = dict(zip(action_names, action_texts))
        text = help % params
        browser = QtGui.QTextBrowser()
        browser.setOpenLinks(False)
        browser.connect(browser, QtCore.SIGNAL("anchorClicked(QUrl)"),
            self._do_link_action)
        browser.setText(text)
        return browser

    def _do_link_action(self, url):
        action_name = unicode(url.toString())
        if action_name.startswith("help "):
            self._do_view_help(action_name[len("help "):])
        else:
            action = self._action_provider(action_name)
            action.trigger()

    def _do_view_help(self, topic):
        # TODO: delegate help lookup to the layer below so it can display
        # using native OS features if available
        if topic == 'bound-branches':
            window = QBzrHelpWindow(self.action_panels)
            window.centralwidget.setHtml(_BOUND_BRANCHES_TOPIC)
            window.show()
        elif topic == 'migration':
            self._action_callback("link",
                "http://doc.bazaar.canonical.com/migration/en/data-migration/index.html")

    def refresh_view(self):
        if not self._location_sets:
            return

        # Refresh the location sets and open the last interesting set
        last_interesting_tab = 0
        for i, (label, browser) in enumerate(self._location_sets):
            browser.refresh_view()
            count = browser.count()
            if count:
                last_interesting_tab = i + 1
            self._open_tabs.setTabEnabled(i + 1, count != 0)
        self._open_tabs.setCurrentIndex(last_interesting_tab)
