# 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

"""An abstraction of some platform specific features."""

import os, sys

from bzrlib import osutils
from bzrlib.plugins.explorer.lib.i18n import N_


# What's the default editor in different desktops?
_DEFAULT_EDITORS = {
    "gnome":    "gedit",
    "kde":      "kate",
    "windows":  "wordpad.exe",  # on Windows the path should be absolute,
                                # see below
    "osx":      "open -t",
    "other":    "vi",
    }


# What's the default terminals in different desktops?
_DEFAULT_TERMINALS = {
    "gnome":    "gnome-terminal",
    "kde":      "konsole --workdir .",
    "windows":  "cmd.exe",
    "osx":      """osascript -e 'tell application "Terminal"' -e 'activate' -e 'do script ""' -e 'end tell'""",
    "other":    "xterm",
    }


# Menu and text for application preferences
_PREFERENCES_INFO = {
    "gnome":    ("Edit", N_("Prefere&nces...")),
    "kde":      ("Settings", N_("&Configure Bazaar Explorer...")),
    "windows":  ("Tools", N_("&Options...")),
    # Note: doesn't matter for osx - automatically gets put in the right place
    "osx":      ("Edit", N_("Prefere&nces...")),
    "other":    ("Edit", N_("Prefere&nces...")),
    }

# Tweaks to labels for actions to meet various UI design guidelines (vs GNOME).
_ACTION_LABELS = {
    "kde":      {
        "Contents": N_("Bazaar Explorer &Handbook"),
        "About":    N_("&About Bazaar Explorer"),
        },
    "windows":  {
        # Note that Windows prefers lowercase for menu labels so we
        # could return '%s help' instead of '%s Help' here, but favour
        # consistency instead. (If we do decide to transform menu labels
        # to lower case (bar the very first letter), then it's best to do
        # that as a separate filtering layer over the whole menu I think.)
        "Quit":     N_("E&xit"),
        "Contents": N_("Bazaar Explorer &Help"),
        "About":    N_("&About Bazaar Explorer"),
        },
    "osx":      {
        "Contents":  N_("Bazaar Explorer &Help"),
        },
    }


class DesktopEnvironment(object):
    """An abstraction of some platform specific features."""

    def __init__(self, name=None):
        """ If name is None, the environment is guessed."""
        self._name = name
        self._custom_editors = None

    def name(self):
        """Return gnome, kde, osx, windows or other."""
        if self._name is None:
            self._name = self._guess_name()
        return self._name

    def _guess_name(self):
        if sys.platform == 'win32':
            return "windows"
        elif sys.platform == 'darwin':
            return "osx"
        elif os.path.exists("/usr/bin/gedit"):
            return "gnome"
        elif os.path.exists("/usr/bin/kate"):
            return "kde"
        else:
            return "other"

    def default_editor(self):
        for varname in 'BZR_EDITOR', 'VISUAL', 'EDITOR':
            editor = os.environ.get(varname)
            # Guard against the variable being set but empty
            if editor:
                return editor
        return _DEFAULT_EDITORS.get(self.name(), "vi")

    def default_terminal(self):
        return _DEFAULT_TERMINALS.get(self.name(), "xterm")

    def preferences_info(self):
        """Menu name and text for accessing preferences in an app.
        
        :return (menu name, action label) tuple or None if unknown."""
        return _PREFERENCES_INFO[self.name()]

    def action_labels(self):
        """Labels to use for common actions to meet UI design guidelines.
        
        :return  dictionary mapping action names to custom labels (vs GNOME)
          or None for no changes. Action names are one of Quit, Contents,
          About. The action label may have a %s indicating where the
          application name is placed.
        """
        return _ACTION_LABELS.get(self.name())

    def get_custom_editor_for(self, path):
        """Return the custom editor for a path.

        :return: the path to the custom editing application or None if none.
        """
        if path is not None:
            ext = osutils.splitext(path)[1]
            if ext is not None:
                ext = ext[1:]
                return self.get_custom_editors().get(ext)
        return None

    def set_custom_editors(self, editors):
        """Set the custom editors for this environment.

        :param editors: a dictionary mapping extensions to
          applications to edit files of that type.
        """
        self._custom_editors = editors

    def get_custom_editors(self):
        return self._custom_editors


# windows-specific code
if sys.platform == 'win32':
    from bzrlib.win32utils import get_app_path, _ensure_unicode
    _DEFAULT_EDITORS['windows'] = _ensure_unicode(get_app_path('wordpad.exe'))
