text: # MIT License
  
  # Copyright (c) 2022 Zenitsu Prjkt™
  
  # Permission is hereby granted, free of charge, to any person obtaining a copy
  # of this software and associated documentation files (the "Software"), to deal
  # in the Software without restriction, including without limitation the rights
  # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  # copies of the Software, and to permit persons to whom the Software is
  # furnished to do so, subject to the following conditions:
  
  # The above copyright notice and this permission notice shall be included in all
  # copies or substantial portions of the Software.
  
  # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  # SOFTWARE.
  
  import threading
  
  from sqlalchemy import BigInteger, Boolean, Column, UnicodeText
  
  from elaina.modules.sql import BASE, SESSION
  
  
  class AFK(BASE):
      __tablename__ = "afk_users"
  
      user_id = Column(BigInteger, primary_key=True)
      is_afk = Column(Boolean)
      reason = Column(UnicodeText)
  
      def __init__(self, user_id, reason="", is_afk=True):
          self.user_id = user_id
          self.reason = reason
          self.is_afk = is_afk
  
      def __repr__(self):
          return "afk_status for {}".format(self.user_id)
  
  
  AFK.__table__.create(checkfirst=True)
  INSERTION_LOCK = threading.RLock()
  
  AFK_USERS = {}
  
  
  def is_afk(user_id):
      return user_id in AFK_USERS
  
  
  def check_afk_status(user_id):
      try:
          return SESSION.query(AFK).get(user_id)
      finally:
          SESSION.close()
  
  
  def set_afk(user_id, reason=""):
      with INSERTION_LOCK:
          curr = SESSION.query(AFK).get(user_id)
          if not curr:
              curr = AFK(user_id, reason, True)
          else:
              curr.is_afk = True
  
          AFK_USERS[user_id] = reason
  
          SESSION.add(curr)
          SESSION.commit()
  
  
  def rm_afk(user_id):
      with INSERTION_LOCK:
          curr = SESSION.query(AFK).get(user_id)
          if curr:
              if user_id in AFK_USERS:  # sanity check
                  del AFK_USERS[user_id]
  
              SESSION.delete(curr)
              SESSION.commit()
              return True
  
          SESSION.close()
          return False
  
  
  def toggle_afk(user_id, reason=""):
      with INSERTION_LOCK:
          curr = SESSION.query(AFK).get(user_id)
          if not curr:
              curr = AFK(user_id, reason, True)
          elif curr.is_afk:
              curr.is_afk = False
          elif not curr.is_afk:
              curr.is_afk = True
          SESSION.add(curr)
          SESSION.commit()
  
  
  def __load_afk_users():
      global AFK_USERS
      try:
          all_afk = SESSION.query(AFK).all()
          AFK_USERS = {user.user_id: user.reason for user in all_afk if user.is_afk}
      finally:
          SESSION.close()
  
  
  __load_afk_users()
  