import os
import sys
import traceback
import glob
import os.path
import configparser
import warnings
import codecs
import time

#######################
# PLUGINS

# list of plugin paths. it gets filled in by the QGIS python library
plugin_paths = []

# dictionary of plugins
plugins = {}

available_plugins = []

plugins_metadata_parser = {}

def findPlugins(path):
    """ for internal use: return list of plugins in given path """
    for plugin in glob.glob(path + "/*"):
        if not os.path.isdir(plugin):
            continue
        if not os.path.exists(os.path.join(plugin, '__init__.py')):
            continue

        metadataFile = os.path.join(plugin, 'metadata.txt')
        if not os.path.exists(metadataFile):
            continue

        cp = configparser.ConfigParser()

        try:
            with codecs.open(metadataFile, "r", "utf8") as f:
                cp.read_file(f)
        except:
            cp = None

        pluginName = os.path.basename(plugin)
        yield (pluginName, cp)


def metadataParser():
    """Used by other modules to access the local parser object"""
    return plugins_metadata_parser


def updateAvailablePlugins():
    """ Go through the plugin_paths list and find out what plugins are available. """
    # merge the lists
    plugins = []
    metadata_parser = {}
    for pluginpath in plugin_paths:
        for pluginName, parser in findPlugins(pluginpath):
            if parser is None:
                continue
            if pluginName not in plugins:
                plugins.append(pluginName)
                metadata_parser[pluginName] = parser

    global available_plugins
    available_plugins = plugins
    global plugins_metadata_parser
    plugins_metadata_parser = metadata_parser


def pluginMetadata(packageName, fct):
    """ fetch metadata from a plugin - use values from metadata.txt """
    try:
        return plugins_metadata_parser[packageName].get('general', fct)
    except Exception:
        return "__error__"


def loadPlugin(packageName):
    """ load plugin's package """

    try:
        __import__(packageName)
        return True
    except:
        pass  # continue...

    # snake in the grass, we know it's there
    sys.path_importer_cache.clear()

    # retry
    try:
        __import__(packageName)
        return True
    except:
        print("Couldn't load plugin '%s'" % (packageName))
        return False


def _unloadPluginModules(packageName):
    """ unload plugin package with all its modules (files) """
    global _plugin_modules
    mods = _plugin_modules[packageName]

    for mod in mods:
        if not mod in sys.modules:
            continue

        # try removing path
        if hasattr(sys.modules[mod], '__path__'):
            for path in sys.modules[mod].__path__:
                try:
                    sys.path.remove(path)
                except ValueError:
                    # Discard if path is not there
                    pass

        # try to remove the module from python
        try:
            del sys.modules[mod]
        except:
            print("Error when removing module:\n%s" % traceback.format_exc())
    # remove the plugin entry
    del _plugin_modules[packageName]

#######################
# SERVER PLUGINS
#

# list of plugin paths. it gets filled in by the QGIS python library
server_plugin_paths = []

# dictionary of plugins
server_plugins = {}

# list of active (started) plugins
server_active_plugins = []

# initialize 'serverIface' object
serverIface = None

def initServerInterface(serverIface_):
    #from qgis.server import DmpServerInterface
    #from sip import wrapinstance
    #sys.excepthook = sys.__excepthook__
    global serverIface
    serverIface = serverIface_


def startServerPlugin(packageName):
    """ initialize the plugin """
    global server_plugins, server_active_plugins, serverIface

    if packageName in server_active_plugins:
        return False
    if packageName not in sys.modules:
        return False

    package = sys.modules[packageName]
    errMsg = "Couldn't load server plugin: %s" %(packageName)

    # create an instance of the plugin
    try:
        server_plugins[packageName] = package.serverClassFactory(serverIface)
    except:
        _unloadPluginModules(packageName)
        print("%s ,due to an error when calling its serverClassFactory() method." %(errMsg))
        return False

    # add to active plugins
    server_active_plugins.append(packageName)
    return True