import os

from utils import vfs

class MetaDataRegistry:
    """
    Registry for caching metadata information. By caching metadata, we can
    reduce the startup time of programs. The cache is intelligent enough to
    add uncached items and to remove obsolete ones.


    The data format of the registry file is as follows:

      - lines starting with '#' and empty lines are ignored and may be used
        for comments and formatting

      - every other line contains one item

      - an item consists of a space-separated list

      - the first entry in the list is the path of the cached item, i.e. the
        file which originally contains the metadata

      - the other entries in the list are key-value pairs, where the key and
        value are separated by a ':'

      - the value strings are URL-quoted
    """


    def __init__(self, regfile, repos, find_handler, register_handler):

        self.__regfile = regfile
        self.__repos = repos
        self.__find_handler = find_handler
        self.__register_handler = register_handler

        self.__registry = {}
        self.__loaded = {}

        try:
            self.__load()
        except:
            # don't crash when loading crap
            pass



    #
    # Scans the repositories for items, which have not yet been registered.
    #
    def scan_repositories(self):

        for repo in self.__repos:
            for path in self.__find_handler(repo):
                if (not path in self.__loaded):
                    items = self.__register_handler(path)
                    if (items):
                        self.__registry[path] = items
                        self.__loaded[path] = True
            #end for
        #end for

        # time to save
        self.__save()



    def __load(self):

        try:
            reg = open(self.__regfile).readlines()
        except:
            reg = []

        for line in reg:
            if (not line.strip() or line.startswith("#")): continue

            parts = line[:-1].split(" ")
            path = vfs.unescape_path(parts[0])
            items = parts[1:]
            self.__registry[path] = []
            for i in items:
                k, v = i.split(":")
                self.__registry[path].append((k, vfs.unescape_path(v)))
            self.__loaded[path] = True



    def __save(self):

        fd = open(self.__regfile, "w")
        fd.write(
            "# This autogenerated file acts as a cache. Removing this file "
            "will result in a\n"
            "# longer startup time.\n\n")

        for path, items in self.__registry.items():
            if (not os.path.exists(path)): continue
            data = map(lambda item: "%s:%s" % (item[0],
                                               vfs.escape_path(item[1])),
                       items)
            fd.write("%s %s\n" % (vfs.escape_path(path), " ".join(data)))

        fd.close()



    #
    # Returns a list of all items.
    #
    def get_item_list(self):

        return self.__registry.keys()



    #
    # Returns the item given by its path.
    #
    def get_item(self, path):

        return self.__registry.get(path, [])



    #
    # Sets the given item.
    #
    def set_item(self, path, metadata):

        self.__registry[path] = metadata
        self.__save()
