from flask_login import current_user
from flask_socketio import join_room, leave_room
from app import hashids, socketio
from app.decorators import socketio_admin_required, socketio_login_required
from app.models import User


@socketio.on('GET /users')
@socketio_admin_required
def get_users():
    users = User.query.filter_by().all()
    return {
        'body': [user.to_json_serializable() for user in users],
        'options': {
            'status': 200,
            'statusText': 'OK',
            'headers': {'Content-Type: application/json'}
        }
    }


@socketio.on('SUBSCRIBE /users')
@socketio_admin_required
def subscribe_users():
    join_room('/users')
    return {'options': {'status': 200, 'statusText': 'OK'}}


@socketio.on('GET /users/<user_id>')
@socketio_login_required
def get_user(user_hashid):
    user_id = hashids.decode(user_hashid)
    user = User.query.get(user_id)
    if user is None:
        return {'options': {'status': 404, 'statusText': 'Not found'}}
    if not (user == current_user or current_user.is_administrator()):
        return {'options': {'status': 403, 'statusText': 'Forbidden'}}
    return {
        'body': user.to_json_serializable(),
        'options': {
            'status': 200,
            'statusText': 'OK',
            'headers': {'Content-Type: application/json'}
        }
    }


@socketio.on('SUBSCRIBE /users/<user_id>')
@socketio_login_required
def subscribe_user(user_hashid):
    user_id = hashids.decode(user_hashid)
    user = User.query.get(user_id)
    if user is None:
        return {'options': {'status': 404, 'statusText': 'Not found'}}
    if not (user == current_user or current_user.is_administrator()):
        return {'options': {'status': 403, 'statusText': 'Forbidden'}}
    join_room(f'/users/{user.hashid}')
    return {'options': {'status': 200, 'statusText': 'OK'}}


@socketio.on('GET /public_users')
@socketio_login_required
def get_public_users():
    users = User.query.filter_by(is_public=True).all()
    return {
        'body': [
            user.to_json_serializable(filter_by_privacy_settings=True)
            for user in users
        ],
        'options': {
            'status': 200,
            'statusText': 'OK',
            'headers': {'Content-Type: application/json'}
        }
    }


@socketio.on('SUBSCRIBE /users')
@socketio_admin_required
def subscribe_users():
    join_room('/public_users')
    return {'options': {'status': 200, 'statusText': 'OK'}}


@socketio.on('GET /public_users/<user_id>')
@socketio_login_required
def get_user(user_hashid):
    user_id = hashids.decode(user_hashid)
    user = User.query.filter_by(id=user_id, is_public=True).first()
    if user is None:
        return {'options': {'status': 404, 'statusText': 'Not found'}}
    if not (user == current_user or current_user.is_administrator()):
        return {'options': {'status': 403, 'statusText': 'Forbidden'}}
    return {
        'body': user.to_json_serializable(filter_by_privacy_settings=True),
        'options': {
            'status': 200,
            'statusText': 'OK',
            'headers': {'Content-Type: application/json'}
        }
    }


@socketio.on('SUBSCRIBE /public_users/<user_id>')
@socketio_login_required
def subscribe_user(user_hashid):
    user_id = hashids.decode(user_hashid)
    user = User.query.filter_by(id=user_id, is_public=True).first()
    if user is None:
        return {'options': {'status': 404, 'statusText': 'Not found'}}
    if not (user == current_user or current_user.is_administrator()):
        return {'options': {'status': 403, 'statusText': 'Forbidden'}}
    join_room(f'/public_users/{user.hashid}')
    return {'options': {'status': 200, 'statusText': 'OK'}}