# -*- Mode: python; coding: utf-8; tab-width: 4; indent-tabs-mode: nil; -*-
#
# GNOME Activity Journal
#
# Copyright © 2009-2010 Seif Lotfy <seif@lotfy.com>
# Copyright © 2009-2010 Siegfried Gevatter <siegfried@gevatter.com>
# Copyright © 2007 Alex Graveley <alex@beatniksoftware.com>
# Copyright © 2010 Markus Korn <thekorn@gmx.de>
# Copyright © 2010 Randal Barlow <email.tehk@gmail.com>
# Copyright © 2020 The GNOME Activity Journal developers
#
# 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 pickle
import gettext
import os
import sys
import urllib.request, urllib.parse, urllib.error
from xdg import BaseDirectory

from zeitgeist.datamodel import Event, Subject, Interpretation, Manifestation, \
    ResultType

import gi
from gi.repository import Gio, GObject

# Installation details
BASE_PATH = os.path.abspath(os.path.join(os.path.dirname(__file__), ".."))
DATA_PATH = os.path.join(BASE_PATH, "data")
NAME = "GNOME Activity Journal"
VERSION = "1.0.0"
ZEITGEIST_REQUIRED_VERSION=[1, 0, 3]
GETTEXT_PATH = os.path.join(BASE_PATH, "../locale")

USER_DATA_PATH = BaseDirectory.save_data_path("gnome-activity-journal")

PLUGIN_PATH = os.path.join(BASE_PATH, "src/plugins")
if not os.path.exists(PLUGIN_PATH) or not os.path.isdir(PLUGIN_PATH):
    PLUGIN_PATH = None
USER_PLUGIN_PATH = os.path.join(USER_DATA_PATH, "plugins")
if not os.path.exists(USER_PLUGIN_PATH) or not os.path.isdir(USER_PLUGIN_PATH):
    USER_PLUGIN_PATH = None

settings = Gio.Settings.new("org.gnome.ActivityJournal")
preference_settings = Gio.Settings.new("org.gnome.ActivityJournal.preferences")

DEBUG = False
SCALE_TO_CENTER = preference_settings["scale-to-center-thumbnail"]
SHOW_THUMBNAILS_IN_TIMELINE = preference_settings["show-thumbnails-in-timeline"]
SHOW_DAY_NIGHT_GRADIENT_IN_TIMELINE = preference_settings["show-day-night-gradient-in-timeline"]
CONFIRM_ITEM_DELETION = preference_settings["confirm-item-deletion"]
HIDE_EMPTY_DAY_LABELS = preference_settings["hide-empty-day-labels"]
SEPARATE_ZOOM_PER_VIEW = preference_settings["separate-zoom-per-view"]

SEARCH_IN_SUBJECT_URI = preference_settings["search-in-subject-uri"]
SEARCH_IGNORE_SINGLE_CHAR = preference_settings["search-ignore-single-char"]
SEARCH_IS_CASE_SENSITIVE = preference_settings["search-is-case-sensitive"]
SEARCH_RESULTS_USE_BOLD_STYLE = preference_settings["search-results-use-bold-style"]
SEARCH_RESULTS_USE_LARGE_STYLE = preference_settings["search-results-use-large-style"]
SEARCH_RESULTS_USE_DEFAULT_COLOR = preference_settings["search-results-use-default-color"]
SEARCH_RESULTS_TEXT_COLOR = preference_settings["search-results-text-color"]
SEARCH_RESULTS_HISTOGRAM_COLOR = preference_settings["search-results-histogram-color"]
SEARCH_RESULTS_TEXT_COLOR_UPDATED = preference_settings["search-results-text-color-updated"]
SEARCH_RESULTS_HISTOGRAM_COLOR_UPDATED = preference_settings["search-results-histogram-color-updated"]

SHOW_AUDIO_PREVIEW = preference_settings["show-audio-preview"]
SHOW_VIDEO_PREVIEW = preference_settings["show-video-preview"]

# day parts
CHANGEHOURS = [ 0 ]
CHANGEHOURS.append(preference_settings["day-part-early-morning-to"])
CHANGEHOURS.append(preference_settings["day-part-morning-to"])
CHANGEHOURS.append(preference_settings["day-part-afternoon-to"])
CHANGEHOURS.append(preference_settings["day-part-evening-to"])

#FIXME i know it's ugly. Btw this is only a temp solution. It will be removed
# when we'll revamp the Multiview view.----sorry----cando
IN_ERASE_MODE = False

def _get_path(path):
    return os.path.join(BASE_PATH, path)

def get_data_path(path=None):
    return os.path.join(DATA_PATH, path) if path else DATA_PATH

def get_icon_path(path):
    for basepath in (DATA_PATH, "/usr/share/", "/usr/local/share",
        os.path.expanduser("~/.local/share")):
        newpath = os.path.join(basepath, "icons", path)
        if os.path.exists(newpath):
            return newpath
    return None

def event_exists(uri):
    # TODO: Move this into Zeitgeist's datamodel.py
    return not uri.startswith("file://") or os.path.exists(
        urllib.parse.unquote(str(uri[7:])))

# When running from Bazaar, give priority to local translations
if os.path.isdir(_get_path("build/mo")):
    GETTEXT_PATH = _get_path("build/mo")


class Bookmarker(GObject.GObject):

    __gsignals__ = {
        "reload" : (GObject.SignalFlags.RUN_FIRST,
                    None,
                    (GObject.TYPE_PYOBJECT,))
        }
    # PUBLIC!
    bookmarks = []
    def __init__(self):
        GObject.GObject.__init__(self)
        self.bookmarks_file = os.path.join(USER_DATA_PATH, "bookmarks.pickled")
        self._load()

    def _load(self):
        if os.path.isfile(self.bookmarks_file):
            try:
                with open(self.bookmarks_file, "rb") as f:
                    self.bookmarks = pickle.load(f)
                    removable = []
                    for bookmark in self.bookmarks:
                        if not event_exists(bookmark):
                            removable.append(bookmark)
                    for uri in removable:
                        self.bookmarks.remove(uri)
            except Exception:
                print("Pin database is corrupt.")

    def _save(self):
        with open(self.bookmarks_file, "wb") as f:
            pickle.dump(self.bookmarks, f)

    def bookmark(self, uri):
        if not uri in self.bookmarks and event_exists(uri):
            self.bookmarks.append(uri)
        self._save()
        self.emit("reload", self.bookmarks)

    def unbookmark(self, uri):
        if uri in self.bookmarks:
            self.bookmarks.remove(uri)
        self._save()
        self.emit("reload", self.bookmarks)

    def is_bookmarked(self, uri):
        return uri in self.bookmarks

class PluginManager(object):
    """
    Loads a module and calls the module's activate(client, store, window) function

    Where:
    client is a zeitgeist client
    store is a the backing Store which controls journal
    window is the Journal window

    All plugins must have:
    func activate(client, store, window): build up when the plugin is enabled
    func deactivate(client, store, window): tear down when the plugin is disabled
    str __plugin_name__: plugin name
    str __description__: description of the plugin
    """
    plugin_settings = Gio.Settings.new("org.gnome.ActivityJournal.plugins")

    def __init__(self, client, store, window):
        self.plugins = {}
        self.client = client
        self.store = store
        self.window = window
        # Base plugins
        self.load_path(PLUGIN_PATH)
        self.load_path(USER_PLUGIN_PATH)

    def load_path(self, path):
        if path:
            sys.path.append(path)
            plugs = []
            for module_file in os.listdir(path):
                if module_file.endswith(".py") and module_file != "__init__.py":
                    modname = module_file.replace(".py", "").replace("-", "_")
                    plugs.append(modname)
            self.get_plugins(plugs, level=0)

    def get_plugins(self, plugin_names, prefix="", level=-1):
        plugs = self.import_plugins(plugin_names, prefix=prefix, level=level)
        self.load_plugins(plugs)

    def import_plugins(self, plugs, prefix="", level=-1):
        plugins = []
        for plugin_name in plugs:
            try:
                plugin_module = __import__(prefix + plugin_name, level=level, fromlist=[plugin_name])
                plugins.append((plugin_name, plugin_module))
                self.plugins[plugin_name] = plugin_module
                # print  plugin_module.__plugin_name__ + " has been imported"
            except Exception as e:
                print(" Importing %s failed." % plugin_name, e)
        return plugins

    def load_plugins(self, plugins):
        for plugin_name, plugin_module in plugins:
            try:
                # FixMe: plugin code is very primitive. Replace with
                # libpeas / libpeasgtk, and remove all plugin code
                # later.

                # state = self.plugin_settings[plugin_name]
                # if not state: continue # If the plugin is not True it will not be loaded
                self.activate(plugin_module)
            except Exception as e:
                print("Loading %s failed." % plugin_name, e)

    def __get_plugin_from_name(self, plugin=None, name=None):
        if not plugin:
            plugin = self.plugins[name]
        elif not plugin and not name:
            raise TypeError("You must pass either a plugin or a plugin_name")
        return plugin

    def activate(self, plugin=None, name=None):
        plugin = self.__get_plugin_from_name(plugin, name)
        plugin.activate(self.client, self.store, self.window)
        print("Activating %s" % plugin.__plugin_name__)

    def deactivate(self, plugin=None, name=None):
        plugin = self.__get_plugin_from_name(plugin, name)
        plugin.deactivate(self.client, self.store, self.window)
        print("Deactivating %s" % plugin.__plugin_name__)



# Singletons and constants
bookmarker = Bookmarker()
