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

"""
#    Copyright(C) 2011  Stefano Palazzo <stefano.palazzo@gmail.com>
#                  2011  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 gettext

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

import askubuntu_bridge

_ = gettext.gettext

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

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


class Daemon(object):
    """ Askubuntu Daemon searches askubuntu.com for answers
    to questions
    """
    special_searches = ["me", "chat", "meta", "au", "help", "lens"]

    def __init__(self):
        """ Sets up the askubuntu scope
        """
        self.scope = Unity.Scope.new("/net/launchpad/scope/help/askubuntu")

        # 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 add_default_results(self, search, model):
        """ Adds specific results to the model based on the search string
        """
        if not search.startswith("@"):

            if search.lower() not in self.special_searches:
                model.append("http://askubuntu.com/questions/ask",
                            Gio.ThemedIcon.new("help-faq").to_string(),
                            EVERYTHING,
                            "text/html",
                            _("Ask your own question"),
                            _("Ask a Question"),
                "")

            if search and search.lower() not in self.special_searches:
                model.append("http://askubuntu.com/search?q=" + search.strip(),
                            Gio.ThemedIcon.new("search").to_string(),
                            EVERYTHING,
                            "text/html",
                            _("Search on Ask Ubuntu"),
                            _("Find '%s' on Ask Ubuntu" % search),
                "")

            if "chat" in search.lower():
                model.append("http://chat.stackexchange.com/rooms/201/",
                        Gio.ThemedIcon.new("applications-chat").to_string(),
                            EVERYTHING,
                            "text/html",
                            _("Join the Ask Ubuntu Chat"),
                            _("Join the Ask Ubuntu General Chat Room"),
                "")

            if "meta" in search.lower():
                model.append("http://meta.askubuntu.com/",
                        Gio.ThemedIcon.new("gnome-fs-bookmark-missing").to_string(),
                            EVERYTHING,
                            "text/html",
                            _("Visit Ask Ubuntu - Meta"),
                            _("Visit Ask Ubuntu - Meta"),
                "")

            if(any(i in search.lower() for i in ["askubuntu", "ask"]) or
                search.lower() == "au"):
                model.append("http://askubuntu.com/",
                            Gio.ThemedIcon.new("distributor-logo").to_string(),
                            EVERYTHING,
                            "text/html",
                            _("Ask Ubuntu"),
                            _("Ask Ubuntu"),
                "")

            if(any(i in search.lower() for i in ["profile", "recent"]) or
                search.lower() == "me"):
                model.append("http://askubuntu.com/users/recent",
                            Gio.ThemedIcon.new("user-info").to_string(),
                            EVERYTHING,
                            "text/html",
                            _("Your Responses"),
                            _("Your Responses"),
                "")

            if("askubuntu" in search.lower() and "lens" in search.lower() or
                search.lower() == "help" or search.lower() == "wtf"):
                model.append("http://askubuntu.com/questions/31712",
                            Gio.ThemedIcon.new("help").to_string(),
                            EVERYTHING,
                            "text/html",
                            _("Help about this Lens"),
                            "",
                            "")

    def add_questions_results(self, search, model):
        """ Searches a specific stackexchange site for questions and adds
        results to the questions categories based on the solved
        state of the result  solved, answered or not answered
        Args:
          search: the search string
          model: the model object that results are added to
        """
        for url, icon, title, text, category in askubuntu_bridge.get_questions(search):
            # No need to be including questions marked as [closed] in the results
            if title.lower().find("[closed]") == -1:
                model.append(url, icon, category, "text/html", title, text, url)

    def add_tags_results(self, search, model, _max=None):
        """ Searches a specific stackexchange site for tags and adds
        results to the tags category
        Args:
          search: the search string
          model: the model object that results are added to
        """
        icon_hint = Gio.ThemedIcon.new("tag-new").to_string()  # Tags Icon
        try:
            for n, (url, title) in enumerate(askubuntu_bridge.get_tags(search)):
                model.append(url, icon_hint, TAGS, "text/html", title, title, url)
                if _max and n + 1 == _max:
                    break
        except:
            pass

    def update_results_model(self, search, model, _global=False):
        """ Takes the search string and determines the active filters, then
        gets questions, tags, badges and users for the search
        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()

        f = self.scope.get_filter("sites")
        o = None
        if f != None:
            o = f.get_active_option()
        if o != None:
            search = o.props.id + " " + search

        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 == "askubuntu":
                if source.props.active:
                    scope_active = True

        if scope_active:
            if _global == False or search in self.special_searches:
                self.add_default_results(search, model)

            if search and not search.lower() in self.special_searches:
                self.add_questions_results(search, model)
                self.add_tags_results(search, model)

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()
