# 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

import sys

import bzrlib
import bzrlib.api
from bzrlib.commands import Command, register_command
from bzrlib.option import Option, ListOption, RegistryOption

from bzrlib.lazy_import import lazy_import
lazy_import(globals(), '''
from PyQt4 import QtGui, QtCore

from bzrlib import bzrdir, debug, ui

from bzrlib.plugins.explorer.lib import (
    checkout_dialog,
    explorer,
    parameter_parser,
    workspace_dialogs,
    workspace_models,
    )
''')

# These can't be lazily imported currently
try:
    from bzrlib.plugins.qbzr.lib.commands import (
        simple_revision_option,
        )
except ImportError:
    raise bzrlib.errors.BzrError("Bazaar Explorer requires QBzr. "
        "Please install QBzr (https://launchpad.net/qbzr).")

if getattr(sys, "frozen", None):
    # Add our required extra libraries for the standalone bzr.exe to path
    import bzrlib.plugins.qbzr.lib


def _init_explorer_command(zzz=False, experimental=False):
    # Set up global exception handling.
    from bzrlib.plugins.qbzr.lib.trace import excepthook
    if 'error' not in debug.debug_flags:
        sys.excepthook = excepthook

    try:
        from bzrlib.plugins.qbzr.lib.trace import set_file_bugs_url
        set_file_bugs_url(
                    "https://bugs.launchpad.net/bzr-explorer/+filebug")
    except ImportError:
        # This function is only availible from qbzr 0.13
        pass

    from bzrlib.plugins.explorer.lib import i18n
    if not zzz:
        i18n.install()
        # enable translations for qbzr widgets too
        import bzrlib.plugins.qbzr.lib.i18n
        bzrlib.plugins.qbzr.lib.i18n.install()
    else:
        i18n.install_zzz()
    if experimental:
        from bzrlib.plugins.explorer import lib
        lib.set_experimental_mode(True)


class cmd_explorer(Command):
    """Desktop application for Bazaar.

    If a location is given, that location is opened. Otherwise,
    Bazaar Explorer is started with a "Welcome" page.

    See http://doc.bazaar.canonical.com/explorer/en/ for our vision,
    an overview of features, a visual tour and additional
    documentation.

    :Troubleshooting:

     A diagnostic mode is supported where commands are displayed
     in a dialog instead of being executed. This can be enabled from
     the command line by using the --dry-run option and toggled from
     within the application using View --> Diagnostic Mode.

     If started with -Derror, exceptions are displayed on the console
     instead of being trapped and converted to an error dialog. This
     can be useful when providing additional information for bug
     reports.
    """

    takes_options = [
        Option("hat", type=str,
            help="Additional set of bookmarks and tools to load.",
            ),
        Option("dry-run",
            help="Start with diagnostic mode enabled.",
            ),
        RegistryOption.from_kwargs("desktop",
            help="Desktop environment to use.",
            gnome="GNOME",
            kde="K Desktop Environment",
            windows="Windows",
            osx="Mac OS X",
            value_switches=True,
            ),
        ]
    if bzrlib.api.get_minimum_api_version(bzrlib) >= (1,14):
        takes_options.extend([
            Option("zzz", hidden=True,
                help="Special zzz translation used for debugging i18n stuff.",
                ),
            Option("experimental", hidden=True,
                help="Enable experimental features.",
                ),
            Option("screenshots", hidden=True,
                help="Take screenshots.",
                ),
            ])
    takes_args = ['location?']
    aliases = ['explore']

    def run(self, location=None, hat=None, dry_run=False,
            desktop=None, zzz=False, experimental=False, screenshots=False):
        
        required_qbzr_version = (0, 19)
        from bzrlib.plugins import qbzr
        if qbzr.version_info < required_qbzr_version:
            from bzrlib.errors import IncompatibleAPI
            raise IncompatibleAPI(qbzr, required_qbzr_version,
                                  qbzr.version_info, qbzr.version_info)
        
        from bzrlib.plugins.qbzr.lib import uifactory
        _init_explorer_command(zzz, experimental)

        # Select the script to run
        if screenshots:
            # Magic internal script to generate screenshots
            script = ":screenshots:"
        else:
            script = None

        # Start the application
        app = QtGui.QApplication(sys.argv)
        ui.ui_factory = uifactory.QUIFactory()
        if location is None:
            location_list = None
        else:
            location_list = [location]
        window = explorer.QExplorerMainWindow(location_list=location_list,
            hat=hat, desktop=desktop, dry_run=dry_run, _script=script)
        window.show()
        app.exec_()


# Define options shared across commands below
_model_option = RegistryOption("model",
     help="How to setup the repository, branch and tree.",
     lazy_registry=('bzrlib.plugins.explorer.lib.workspace_models',
         'workspace_model_registry'),
     value_switches=True,
     )
_create_prefix_option = Option('create-prefix',
     help='Create the path leading up to the location '
         'if it does not already exist.')
_parameter_option = ListOption('parameter', type=str, short_name="P",
     help="Specify a model-specific parameter in the format "
         "key=[value]. Use ? to view supported parameters.")


def _parse_model_parameters(model, parameter_list):
    """Parse and validate a list of model parameters to a dictionary."""
    if parameter_list is None:
        return None
    else:
        if model is None:
            model = workspace_models.workspace_model_registry.get()
        parser = parameter_parser.ParameterParser(model.parameters)
        return parser.parse_list(parameter_list)


class cmd_init_workspace(Command):
    """Start a new workspace."""
    takes_options = [_model_option, _create_prefix_option, _parameter_option,
        RegistryOption('format',
                help='Specify a format for the repository, etc. '
                'See "help formats".',
                lazy_registry=('bzrlib.bzrdir', 'format_registry'),
                converter=lambda name: bzrdir.format_registry.make_bzrdir(name),
                value_switches=True,
                title="Storage Format",
                ),
        ]
    takes_args = ['location?']
    aliases = ['new']
    def run(self, location=u'.', model=None, create_prefix=False, format=None,
        parameter=None):
        workspace_models.init_workspace(location, model=model, format=format,
            create_parent_dirs=create_prefix, outf=self.outf,
            model_params=_parse_model_parameters(model, parameter))


class cmd_qinit_workspace(Command):
    """Start a new workspace using a GUI."""
    # TODO: add ui_mode option
    takes_options = [_model_option, _create_prefix_option, _parameter_option]
    if bzrlib.api.get_minimum_api_version(bzrlib) >= (1,14):
        takes_options.extend([
            Option("zzz", hidden=True,
                help="Special zzz translation used for debugging i18n stuff.",
                ),
            Option("experimental", hidden=True,
                help="Enable experimental features.",
                ),
            ])
    takes_args = ['location?']
    aliases = ['qnew']
    def run(self, location=u'.', model=None, create_prefix=False,
        ui_mode=True, zzz=None, experimental=False, parameter=None):
        _init_explorer_command(zzz, experimental)

        # Start the application
        app = QtGui.QApplication(sys.argv)
        window = workspace_dialogs.QInitWorkspaceDialog(location=location,
            model=model, create_parent_dirs=create_prefix, ui_mode=ui_mode,
            model_params=_parse_model_parameters(model, parameter))
        window.show()
        app.exec_()


class cmd_qcheckout_ala_explorer(Command):
    """Checkout a branch. The checkout is always lightweight."""
    # TODO: add ui_mode option
    takes_options = [simple_revision_option]
    if bzrlib.api.get_minimum_api_version(bzrlib) >= (1,14):
        takes_options.extend([
            Option("zzz", hidden=True,
                help="Special zzz translation used for debugging i18n stuff.",
                ),
            ])
    takes_args = ['branch_location?', 'to_location?']
    aliases = []
    hidden=True
    def run(self, branch_location=None, to_location=None, revision=None,
        ui_mode=True, zzz=None):
        _init_explorer_command(zzz)

        # Start the application
        app = QtGui.QApplication(sys.argv)
        window = checkout_dialog.QCheckoutExplorerStyleDialog(
            branch_location=branch_location, to_location=to_location,
            revision=revision, ui_mode=ui_mode)
        window.show()
        app.exec_()
