import sqlalchemy as sa
from szurubooru.model.base import Base
from szurubooru.model.post import Post, PostScore, PostFavorite
from szurubooru.model.comment import Comment


class User(Base):
    __tablename__ = 'user'

    AVATAR_GRAVATAR = 'gravatar'
    AVATAR_MANUAL = 'manual'

    RANK_ANONYMOUS = 'anonymous'
    RANK_RESTRICTED = 'restricted'
    RANK_REGULAR = 'regular'
    RANK_POWER = 'power'
    RANK_MODERATOR = 'moderator'
    RANK_ADMINISTRATOR = 'administrator'
    RANK_NOBODY = 'nobody'  # unattainable, used for privileges

    user_id = sa.Column('id', sa.Integer, primary_key=True)
    creation_time = sa.Column('creation_time', sa.DateTime, nullable=False)
    last_login_time = sa.Column('last_login_time', sa.DateTime)
    version = sa.Column('version', sa.Integer, default=1, nullable=False)
    name = sa.Column('name', sa.Unicode(50), nullable=False, unique=True)
    password_hash = sa.Column('password_hash', sa.Unicode(128), nullable=False)
    password_salt = sa.Column('password_salt', sa.Unicode(32))
    password_revision = sa.Column(
        'password_revision', sa.SmallInteger, default=0, nullable=False)
    email = sa.Column('email', sa.Unicode(64), nullable=True)
    rank = sa.Column('rank', sa.Unicode(32), nullable=False)
    avatar_style = sa.Column(
        'avatar_style', sa.Unicode(32), nullable=False,
        default=AVATAR_GRAVATAR)

    comments = sa.orm.relationship('Comment')

    @property
    def post_count(self) -> int:
        from szurubooru.db import session
        return (
            session
            .query(sa.sql.expression.func.sum(1))
            .filter(Post.user_id == self.user_id)
            .one()[0] or 0)

    @property
    def comment_count(self) -> int:
        from szurubooru.db import session
        return (
            session
            .query(sa.sql.expression.func.sum(1))
            .filter(Comment.user_id == self.user_id)
            .one()[0] or 0)

    @property
    def favorite_post_count(self) -> int:
        from szurubooru.db import session
        return (
            session
            .query(sa.sql.expression.func.sum(1))
            .filter(PostFavorite.user_id == self.user_id)
            .one()[0] or 0)

    @property
    def liked_post_count(self) -> int:
        from szurubooru.db import session
        return (
            session
            .query(sa.sql.expression.func.sum(1))
            .filter(PostScore.user_id == self.user_id)
            .filter(PostScore.score == 1)
            .one()[0] or 0)

    @property
    def disliked_post_count(self) -> int:
        from szurubooru.db import session
        return (
            session
            .query(sa.sql.expression.func.sum(1))
            .filter(PostScore.user_id == self.user_id)
            .filter(PostScore.score == -1)
            .one()[0] or 0)

    __mapper_args__ = {
        'version_id_col': version,
        'version_id_generator': False,
    }


class UserToken(Base):
    __tablename__ = 'user_token'

    user_token_id = sa.Column('id', sa.Integer, primary_key=True)
    user_id = sa.Column(
        'user_id',
        sa.Integer,
        sa.ForeignKey('user.id', ondelete='CASCADE'),
        nullable=False,
        index=True)
    token = sa.Column('token', sa.Unicode(36), nullable=False)
    note = sa.Column('note', sa.Unicode(128), nullable=True)
    enabled = sa.Column('enabled', sa.Boolean, nullable=False, default=True)
    expiration_time = sa.Column('expiration_time', sa.DateTime, nullable=True)
    creation_time = sa.Column('creation_time', sa.DateTime, nullable=False)
    last_edit_time = sa.Column('last_edit_time', sa.DateTime)
    last_usage_time = sa.Column('last_usage_time', sa.DateTime)
    version = sa.Column('version', sa.Integer, default=1, nullable=False)

    user = sa.orm.relationship('User')
