import web

class Dependency:
    '''
    This class relates a plugin with a version of another. When a plugin
    has a dependency means this plugin NEEDS the specified version of
    the plugin to work. If dependency not unmet the plugin can't be
    installed.
    '''

    def __init__(self, dependon, relation, major, minor, release):
        self.dependon = dependon
        self.version = Version(major, minor, release)
        self.relation = relation

    def __str__(self):
        return "%s (%s%s)" % (self.dependon, self.relation,
                self.version)

    def is_met_by(self, plugin):
        '''
        Returns if the given plugin mets with the requierement of
        the dependency.
        '''
        if not plugin:
            return False

        if self.dependon != plugin.name:
            return False

        if self.relation == ">=":
            return self.version >= plugin.version
        elif self.relation == ">":
            return self.version > plugin.version
        elif self.relation == "=":
            return self.version == plugin.version
        elif self.relation == "<=":
            return self.version <= plugin.version
        elif self.relation == "<":
            return self.version < plugin.version
        return False

    def is_met(self):
        '''
        Return whether there is a plugin that mets with the requirement of the
        dependency. It will NOT check if the plugin is installed or enabled,
        it will only check if the plugin has valid version.
        '''
        plugin = web.ctx.plugin_manager.get_plugin_by_name(self.dependon)

        return self.is_met_by(self, plugin)

    def get_plugin(self):
        '''
        If is_met() returns true, this returns the instance of the plugin.
        '''
        if self.is_met():
            return web.ctx.plugin_manager.get_plugin_by_name(self.dependon)
        return None

class Version:
    '''
    This class represents the version of a plugin.
    It has three numbers (ordered by importance): the major, the minor
    and the release.
    When two plugins have versions with the same major and minor numbers means
    they have the same functions with the same arguments. More bugs have
    been fixed in the plugin with the highest release number.
    When the plugins have different minor number, plugin with highest
    minor number works just like the other, but new features may
    have been added.
    '''
    def __init__(self, major, minor, release):
        self.major = int(major)
        self.minor = int(minor)
        self.release = int(release)

    def __cmp__(self, other):
        if self.major > other.major:
            return 1
        elif self.major < other.major:
            return -1
        if self.minor > other.minor:
            return 1
        elif self.minor < other.minor:
            return -1
        if self.release > other.release:
            return 1
        elif self.release < other.release:
            return -1

        return 0

    def __str__(self):
        return u"%d.%d.%d" % (self.major, self.minor, self.release)

class UnmetDependencyException(Exception):
    def __init__(self, dep):
        self.dep = dep

    def __str__(self):
        return "Unmet Dependency: " + self.dep.__str__()

