public static SmsMessage createSmsMessage(Contact contact, String content)
      throws FailedToCreateSmsMessageException {
    // TODO: Set message direction
    Calendar calendar;
    long dateNumber;
    DataManager dm;
    String messageId;
    String contactId;
    int messageCount;
    SmsMessage smsMessage;

    try {
      // Get sms message information from calendar and manager
      calendar = new GregorianCalendar(TimeZone.getDefault());
      // dateNumber = calendar.getTime().getTime();
      dateNumber = calendar.getTimeInMillis();

      // Create sms message into storage
      dm = DataManager.getInstance();

      // get key to encrypt messages
      byte[] salt = Cryptography.decodeFromStorage(dm.getAttributeString(dm.USER, dm.SALT));
      byte[] iv = Cryptography.decodeFromStorage(dm.getAttributeString(dm.USER, dm.IV));
      SecretKey key = KeyManager.getInstance().generateStorageKey(salt);

      // setup message id
      contactId = contact.getId();
      messageCount = dm.getAttributeInt(contactId, dm.MESSAGE_COUNT);
      messageId = contactId + dm.MESSAGE_CLASS + String.format("%04d", messageCount);
      messageCount++;

      smsMessage = new SmsMessage(messageId, contact, dateNumber, content);
      String encryptedContent = smsMessage.encryptToStore(key, iv);

      // set attributes
      dm.setAttribute(contactId, dm.MESSAGE_COUNT, messageCount);
      dm.addAttribute(contactId, dm.MESSAGE_TABLE, messageId);
      dm.setAttribute(messageId, dm.MESSAGE_DATE_NUMBER, dateNumber);
      dm.setAttribute(messageId, dm.ENCRYPTED_CONTENT, encryptedContent);

      return smsMessage;
    } catch (FailedToLoadDataBaseException
        | KeyStoreIsLockedException
        | FailedToGenerateKeyException
        | FailedToStoreException
        | FailedToEncryptSmsMessageException
        | FailedToGetAttributeException
        | FailedToAddAttributeException exception) {
      throw new FailedToCreateSmsMessageException(exception);
    }
  }
  public static ArrayList<SmsMessage> retrieveAllSmsMessages(Contact contact)
      throws FailedToRetrieveAllSmsMessagesException {

    ArrayList<SmsMessage> messages;
    Set<String> messageIds;
    DataManager dm;
    long dateNumber;
    String contactId;
    String encryptedContent, decryptedContent;
    SmsMessage sms;

    try {
      messages = new ArrayList<>();

      dm = DataManager.getInstance();

      // get key to decrypt messages
      byte[] salt = Cryptography.decodeFromStorage(dm.getAttributeString(dm.USER, dm.SALT));
      byte[] iv = Cryptography.decodeFromStorage(dm.getAttributeString(dm.USER, dm.IV));
      SecretKey key = KeyManager.getInstance().generateStorageKey(salt);

      contactId = contact.getId();
      messageIds = dm.getAttributeSet(contactId, dm.MESSAGE_TABLE);

      // For each sms message id
      for (String messageId : messageIds) {
        // Get sms message information from storage
        dateNumber = dm.getAttributeLong(messageId, dm.MESSAGE_DATE_NUMBER);
        encryptedContent = dm.getAttributeString(messageId, dm.ENCRYPTED_CONTENT);
        // decrypt
        sms = new SmsMessage(contact, encryptedContent);
        decryptedContent = sms.decryptFromStorage(key, iv);
        sms = new SmsMessage(messageId, contact, dateNumber, decryptedContent);
        messages.add(sms);
      }

      // Return array list of contacts
      return messages;
    } catch (FailedToDecryptSmsMessageException
        | FailedToGenerateKeyException
        | FailedToStoreException
        | KeyStoreIsLockedException
        | FailedToLoadDataBaseException
        | FailedToGetAttributeException exception) {
      throw new FailedToRetrieveAllSmsMessagesException(exception);
    }
  }
  public static void deleteSmsMessage(Contact contact, SmsMessage message)
      throws FailedToDeleteSmsMessageException {
    String contactId;
    String messageId;
    DataManager dm;

    try {
      // Remove sms message from storage
      dm = DataManager.getInstance();

      contactId = contact.getId();
      messageId = message.getId();
      dm.cleanAttribute(messageId);
      dm.removeAttribute(contactId, dm.MESSAGE_TABLE, messageId);
    } catch (FailedToLoadDataBaseException | FailedToRemoveAttributeException exception) {
      throw new FailedToDeleteSmsMessageException(exception);
    }
  }