'''
This is the main model for the data base. Here, the main elements
are defined and they can be used by the plugins.
'''
from __future__ import unicode_literals
from db import Base
from sqlalchemy import Integer, Unicode, ForeignKey, Column, Boolean
from sqlalchemy.orm import relation, backref


metadata = Base.metadata

class OrganizativeUnit(Base):
    '''
    This class creates an hierarchical relationship. If it hasn't a parent
    it's a root node. The parent is always another OrganizativeUnit. The
    atribute parent represent it.

    The children can be others OrganizativeUnit (children), but they
    can be computer too (computers). It has an unique name and a description.
    '''
    __tablename__ = 'organizative_unit'

    id = Column(Integer, primary_key=True)
    name = Column(Unicode(120), unique=True)
    parent_id = Column(Integer, ForeignKey('organizative_unit.id'))
    description = Column(Unicode(512))

    children = relation("OrganizativeUnit")
    parent = relation("OrganizativeUnit", remote_side=id,
             primaryjoin="OrganizativeUnit.id==OrganizativeUnit.parent_id")

    def __str__(self):
        return self.name

    @classmethod
    def fields(self):
        return ('name', 'parent', 'description')

    def __repr__(self):
        return "<OrganizativeUnit %s>" % (self.name)

    def get_all_descendant_computers(self):
        '''
        Returns a list containing the computers of all the descendants of this
        ou: children, grand children, etc.
        '''
        descendants = []
        descendants += [i for i in self.computers if not i.repository]
        for child in self.children:
            descendants += child.get_all_descendant_computers()
        return descendants

    def get_repo(self):
        for c in self.computers:
            if c.repository:
                return c

        if self.parent:
            return self.parent.get_repo()
        else:
            return None

    #def get_menu(self):
    #    if menu:
    #        return menu
    #    elif self.parent:
    #        return self.parent.get_menu()
    #    else:
    #        return None

class Computer(Base):
    '''
    This class represents a computer that will be managed by the webconsole.
    It has a unique name to be identify by a human. The mac and the ip
    will be stored too.
    The attribute "repository" is True when is a special computer used
    to do operations that the server can't do.
    The atribute "online" is a boolean and when true means that the computer
    is turned on. When this happens the atribute os contains
    the operative system is running in the computer.
    If the os values is 'opengnsys' the computer is running
    the operative system created specially to be
    booted over the network and ready to make any disk operation.
    '''
    __tablename__ = 'computer'

    id = Column(Integer, primary_key=True)
    name = Column(Unicode(120), unique=True)
    mac = Column(Unicode(12), unique=True)
    ip = Column(Unicode(32))
    port = Column(Integer)
    repository = Column(Boolean)
    online = Column(Boolean)
    so = Column(Unicode(64))

    ou_id = Column(Integer, ForeignKey('organizative_unit.id'))
    ou = relation(OrganizativeUnit, backref=backref('computers',
        cascade='all',
        passive_deletes=False))

    description = Column(Unicode(512))

    def __init__(self, name="", mac="", **kwargs):
        self.online = False
        self.so = ""
        self.name = name
        self.mac = mac

        for k, v in kwargs.items():
            setattr(self, k, v)

    def get_port(self):
        if self.port:
            return self.port
        else:
            import config
            return config.client_daemon_port

    @classmethod
    def fields(self):
        return ('name', 'mac', 'ip', 'ou', 'description')

    def __str__(self):
        return self.name

    def __repr__(self):
        type_computer = 'Computer' if not self.repository else 'Repository'
        return "<%s %s %s %s>" % (type_computer, self.name, self.mac, self.ip)

    def get_img(self):
        if self.repository and self.online:
            return "nav-repo"
        elif self.repository:
            return "nav-repo-off"
        elif self.online:
            return "nav-comp-og"
        else:
            return"nav-comp-off"

    def get_repo(self):
        if self.repository:
            return self

        return self.ou.get_repo()

    #def get_menu(self):
    #    if menu:
    #        return menu
    #    else:
    #        return self.parent.get_menu()

