text: # Categories view
  
  import time
  
  from tabulate import tabulate
  
  from ..models.base import get_session
  from ..models.Category import CategoryModel
  from ..models.Secret import SecretModel
  from ..modules.misc import confirm, clear_screen
  from . import menu
  
  
  def all():
      """
          Return a list of all categories
      """
  
      return get_session().query(CategoryModel).filter(CategoryModel.active == 1).order_by(CategoryModel.id).all()
  
  
  def to_table(rows=[]):
      """
          Transform rows in a table
      """
  
      # Retrieve id and name
      cats = [[cat.id, cat.name] for cat in rows]
  
      if len(cats) > 0:
          return tabulate(cats, headers=['Item', 'Category name'])
      else:
          return 'Empty!'
  
  
  def pick(message='Select a category: ', optional=False):
      """
          Ask a user to pick a category
      """
  
      all_categories = all()
  
      if len(all_categories) == 0:
          print()
          print('You did not create any category yet. You can create one from the main menu.')
          return False
  
      # Display available categories
      print()
      print(to_table(all_categories))
      print()
  
      # Ask user input
      id_ = menu.get_input(message=message)
  
      # Cast as int
      try:
          id_int = int(id_)
          if id_int and exists(id_int):
              return id_int
      except ValueError:  # Not a valid number!
          pass
  
      # No category picked
      if optional and id_ == '':
          return None
  
      print()
      print('Invalid category number!')
  
      return False
  
  
  def exists(id_):
      """
          Check if a category ID exists
      """
  
      if get_session().query(CategoryModel).filter(CategoryModel.id == int(id_)).filter(CategoryModel.active == 1).first():
          return True
  
      return False
  
  
  def get_name(id_):
      """
          Get a category name from a category ID
      """
  
      if not id_:
          return ''
  
      cat = get_session().query(CategoryModel).filter(
          CategoryModel.id == int(id_)).filter(CategoryModel.active == 1).first()
  
      if cat:
          return cat.name
  
      return ''
  
  
  def get_id(name):
      """
          Get a category ID from a category name
      """
  
      if not name:
          return None
  
      cat = get_session().query(CategoryModel).filter(
          CategoryModel.name == name).filter(CategoryModel.active == 1).first()
  
      if cat:
          return cat.id
  
      return None
  
  
  def add(name):
      """
          Create a new category
      """
  
      cat = CategoryModel(name=name, active=1)
      get_session().add(cat)
      get_session().commit()
  
      return True
  
  
  def add_input():
      """
          Ask user for a category name and create it
      """
  
      # Ask user input
      name = menu.get_input(message='Category name: ')
  
      # Return false if name is missing
      if not name:
          return False
  
      # Create category
      result = add(name=name)
  
      print()
      print('The category has been created.')
  
      time.sleep(2)
  
      return result
  
  
  def rename(id_, new_name):
      """
          Rename a category
      """
  
      cat = get_session().query(CategoryModel).filter(
          CategoryModel.id == int(id_)).filter(CategoryModel.active == 1).first()
  
      if cat:
          cat.name = new_name
          get_session().add(cat)
          get_session().commit()
  
          return True
  
      return False
  
  
  def rename_input():
      """
          Rename a category
      """
  
      # Get id
      id_ = pick()
  
      # Return false if id is invalid
      if not id_:
          return False
  
      # Ask user input
      name = menu.get_input(message='Category name: ')
  
      # Return false if name is missing
      if not name:
          return False
  
      result = rename(id_, name)
  
      if result is True:
          print()
          print('The category has been renamed.')
  
          time.sleep(2)
  
      return result
  
  
  def delete(id_):
      """
          Disable a category
      """
  
      cat = get_session().query(CategoryModel).filter(
          CategoryModel.id == int(id_)).filter(CategoryModel.active == 1).first()
  
      if cat:
          cat.active = 0
          get_session().add(cat)
          get_session().commit()
  
          return True
  
      return False
  
  
  def delete_input():
      """
          Delete a category
      """
  
      # Get id
      id_ = pick()
  
      # Return false if id is invalid
      if not id_:
          return False
  
      # Return false if the category is used
      if is_used(id_):
          print()
          print(
              'The category cannot be deleted because it is currently used by some secrets.')
          return False
  
      if confirm('Confirm deletion of the category "' + get_name(id_) + '"?', False):
          result = delete(id_)
  
          if result is True:
              print()
              print('The category has been deleted.')
  
              time.sleep(2)
  
          return result
  
      return False
  
  
  def is_used(id_):
      """
          Check if a category ID is used by any secret
      """
  
      if get_session().query(SecretModel).filter(
              SecretModel.category_id == int(id_)).first():
          return True
  
      return False
  
  
  def main_menu():
      """
          Categories menu
      """
  
      while (True):
          # Clear screen
          clear_screen()
  
          # List categories
          print(to_table(all()))
  
          print()
          command = menu.get_input(
              message='Choose a command [(a)dd a category / (r)rename a category / (d)elete a category / (b)ack to Vault]: ',
              lowercase=True,
              non_locking_values=['l', 'q']
          )
  
          if command is False:
              print()
  
          # Action based on command
          if command == 'a':  # Add a category
              add_input()
              return
          elif command == 'r':  # Rename a category
              rename_input()
              return
          elif command == 'd':  # Delete a category
              delete_input()
              return
          elif command == 'b':  # Back to vault menu
              return
  