#!/usr/bin/python
# -*- coding: utf-8 -*-

"""
#    Copyright(C) 2012  Mark Tully <markjtully@gmail.com>

#    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 3 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, see <http://www.gnu.org/licenses/>.
"""

import sys
import lxml.html
import gettext

# Unity imports
from gi.repository import GLib
from gi.repository import GObject
from gi.repository import Gio
from gi.repository import Unity

_ = gettext.gettext

BUS_NAME = "net.launchpad.scope.help.sumo"

EVERYTHING = 0
OFFICIAL = 1
COMMUNITY = 2
TECHNICAL = 3
TAGS = 4

MAX = 10


class Daemon(object):
    """ Sumo Daemon searches Firefox's knowledgebase for results
    matching query
    """
    def __init__(self):
        """ Sets up the manpages scope
        """
        self.scope = Unity.Scope.new("/net/launchpad/scope/help/sumo")

        # Listen for changes and requests
        self.scope.props.search_in_global = False
        self.scope.connect("search-changed", self.on_search_changed)
        self.scope.connect("filters-changed", self.on_filters_or_preferences_changed)
        self.scope.connect("notify::active", self.on_lens_active)

        self.preferences = Unity.PreferencesManager.get_default()
        self.preferences.connect("notify::remote-content-search", self.on_filters_or_preferences_changed)

        self.scope.export()

    def on_filters_or_preferences_changed(self, *_):
        """ Called when a filter is clicked.  Queue's a new search
        """
        self.scope.queue_search_changed(Unity.SearchType.DEFAULT)

    def on_lens_active(self, *_):
        """ Called when the lens is activated.  Queue's a new search
        """
        if self.scope.props.active:
            self.scope.queue_search_changed(Unity.SearchType.DEFAULT)

    def on_search_changed(self, scope, search=None, search_type=0, cancellable=None):
        """ Called when the search is changed.  Gets the search string and search
        type and passes it to update_results_model()
        Args:
          scope: a scope object
          search: the search string
          search_type: the search type(global or local)
          cancellable: cancellable object
        """
        if hasattr(search, "props"):
            search_string = search.props.search_string
        else:
            search_string = ""

        # only perform the request if the user has not disabled
        # online results. That will hide the category as well.
        if self.preferences.props.remote_content_search != Unity.PreferencesManagerRemoteContent.ALL:
            scope.props.results_model.clear()
            scope.props.global_results_model.clear()
            search.finished()
            return

        if search_type == Unity.SearchType.DEFAULT:
            results = scope.props.results_model
        else:
            results = scope.props.global_results_model

        print "Search changed to: '%s'" % search_string
        self.update_results_model(search_string, results)
        if hasattr(search, "finished"):
            search.finished()

    def update_results_model(self, search, model, _global=False):
        """ Takes the search string and runs apropos <search string>
        Parses its results and adds them to the model
        Args:
          search: the search string
          model: the model object that results are added to
        """
        if _global and search:
            if search != "au":  # for the "au" search, we *do* show a result
                model.clear()   # in the global dash. Why not? ;-)
                return
        model.clear()

        scope_active = False
        e = self.scope.get_filter("sources")
        if not e.props.filtering:
            scope_active = True
        for source in e.options:
            if source.props.id == "sumo":
                if source.props.active:
                    scope_active = True

        if scope_active:
            if not search == "":
                i = 0
                model.append("http://support.mozilla.org/en-US/search?e=es&q_tags=desktop&product=desktop&q=%s" % search,
                      Gio.ThemedIcon.new("search").to_string(),
                      EVERYTHING,
                      'text/html',
                      _("Search on Firefox Support"),
                      _("Find '%s' on Firefox Support" % search),
                      "http://ask.libreoffice.org/questions/scope:all/sort:relevance-desc/query:%s/page:1/" % search)

                icon_hint = Gio.ThemedIcon.new("firefox").to_string()
                url = "http://support.mozilla.org/en-US/search?e=es&q_tags=desktop&product=desktop&q=%s" % search

                tree = lxml.html.parse(url)
                tree.getroot().make_links_absolute()
                items = tree.xpath("//div[@class='result document']")
                for item in items:
                    title = item.xpath("a/text()")[0]
                    print len(title)
                    if len(title) > 80:
                        title = title[:80] + "…"
                    uri = item.xpath("a/@href")[0]
                    if i < MAX:
                        model.append(uri, icon_hint, OFFICIAL, "text/html", title, "support.mozilla.org", uri)
                        i = i + 1

if __name__ == "__main__":
    session_bus_connection = Gio.bus_get_sync(Gio.BusType.SESSION, None)
    session_bus = Gio.DBusProxy.new_sync(session_bus_connection, 0, None,
        'org.freedesktop.DBus', '/org/freedesktop/DBus',
        'org.freedesktop.DBus', None)
    result = session_bus.call_sync('RequestName',
        GLib.Variant("(su)", (BUS_NAME, 0x4)), 0, -1, None)
    result = result.unpack()[0]
    # We could try to do some automated rescue when this happens:
    if result != 1:
        print >> sys.stderr, "Failed to own name %s. Bailing out." % BUS_NAME
        print >> sys.stderr, "Do you have another instance running?"
        raise SystemExit(1)
    daemon = Daemon()
    print "entering the main loop"
    GObject.MainLoop().run()
