from app import db

class TagInformation(db.Model):
    """Detailed information about tags, by dot-string tag identifier."""

    __tablename__ = 'tag_information'
    # The ID is the dot-string of the tag (eg. "calc.g35+e2")
    id = db.Column(db.String(64), primary_key=True)

    # List of uses. Note how we load tag information along individual tags, but
    # we don't load uses unless the field is accessed.
    uses = db.relationship('Tag', back_populates='tag', lazy='dynamic')

    # Pretty name
    pretty = db.Column(db.String(64))

    # ... any other static information about tags

    def __init__(self, id):
        self.id = id

    def category(self):
        return self.id.split(".", 1)[0]

    @staticmethod
    def all_tags():
        all_tags = {}
        for ti in TagInformation.query.all():
            ctgy = ti.category()
            if ctgy not in all_tags:
                all_tags[ctgy] = []
            all_tags[ctgy].append(ti)
        return all_tags

class Tag(db.Model):
    """Association between a Post and a dot-string tag identifier."""

    __tablename__ = 'tag'
    id = db.Column(db.Integer, primary_key=True)

    # Tagged post
    post_id = db.Column(db.Integer, db.ForeignKey('post.id'), index=True)
    post = db.relationship('Post', back_populates='tags', foreign_keys=post_id)
    # Tag name. Note how we always load the information along the tag, but not
    # the other way around.
    tag_id = db.Column(db.String(64), db.ForeignKey('tag_information.id'),
        index=True)
    tag = db.relationship('TagInformation', back_populates='uses',
        foreign_keys=tag_id, lazy='joined')

    def __init__(self, post, tag):
        self.post = post

        if isinstance(tag, str):
            tag = TagInformation.query.filter_by(id=tag).one()
        self.tag = tag
