import {openDB} from 'idb';

const dbName = 'TWPTAvatarsDB';
const threadListLoadEvent = 'TWPT_ViewForumResponse';
const createMessageLoadEvent = 'TWPT_CreateMessageRequest';
// Time after the last use when a cache entry should be deleted (in s):
const cacheExpirationTime = 4 * 24 * 60 * 60;  // 4 days
// Probability of running the piece of code to remove unused cache entries after
// loading the thread list.
const probRemoveUnusedCacheEntries = 0.10;  // 10%

// Time after which an unauthorized forum entry expires (in s).
const unauthorizedForumExpirationTime = 1 * 24 * 60 * 60;  // 1 day

export default class AvatarsDB {
  constructor() {
    this.dbPromise = undefined;
    this.openDB();
    this.setUpInvalidationsHandlers();
  }

  openDB() {
    if (this.dbPromise === undefined)
      this.dbPromise = openDB(dbName, 1, {
        upgrade: (udb, oldVersion, newVersion, transaction) => {
          switch (oldVersion) {
            case 0:
              var cache = udb.createObjectStore('avatarsCache', {
                keyPath: 'threadId',
              });
              cache.createIndex(
                  'lastUsedTimestamp', 'lastUsedTimestamp', {unique: false});

              var unauthedForums = udb.createObjectStore('unauthorizedForums', {
                keyPath: 'forumId',
              });
              unauthedForums.createIndex(
                  'expirationTimestamp', 'expirationTimestamp',
                  {unique: false});
          }
        },
      });
  }

  // avatarsCache methods:
  getCacheEntry(threadId) {
    return this.dbPromise.then(db => db.get('avatarsCache', threadId));
  }

  putCacheEntry(entry) {
    return this.dbPromise.then(db => db.put('avatarsCache', entry));
  }

  invalidateCacheEntryIfExists(threadId) {
    return this.dbPromise.then(db => db.delete('avatarsCache', threadId));
  }

  removeUnusedCacheEntries() {
    console.debug('[threadListAvatars] Removing unused cache entries...');
    return this.dbPromise
        .then(db => {
          var upperBoundTimestamp =
              Math.floor(Date.now() / 1000) - cacheExpirationTime;
          var range = IDBKeyRange.upperBound(upperBoundTimestamp);

          var tx = db.transaction('avatarsCache', 'readwrite');
          var index = tx.store.index('lastUsedTimestamp');
          return index.openCursor(range);
        })
        .then(function iterateCursor(cursor) {
          if (!cursor) return;
          cursor.delete();
          return cursor.continue().then(iterateCursor);
        });
  }

  setUpInvalidationsHandlers() {
    window.addEventListener(threadListLoadEvent, e => {
      // Ignore ViewForum requests made by the chat feature and the "Mark as
      // duplicate" dialog.
      //
      // All those requests have |maxNum| set to 10 and 20 respectively, while
      // the requests that we want to handle are the ones to initially load the
      // thread list (which currently requests 100 threads) and the ones to load
      // more threads (which request 50 threads).
      var maxNum = e.detail.body?.['2']?.['1']?.['2'];
      if (maxNum == 10 || maxNum == 20) return;

      this.handleInvalidationsByListLoad(e);
    });
    window.addEventListener(
        createMessageLoadEvent, e => this.handleInvalidationByNewMessage(e));
  }

  handleInvalidationsByListLoad(e) {
    var response = e?.detail?.body;
    var threads = response?.['1']?.['2'];
    if (threads === undefined) {
      console.warn(
          '[threadListAvatars] The thread list doesn\'t contain any threads.');
      return;
    }

    var promises = [];
    threads.forEach(t => {
      var id = t?.['2']?.['1']?.['1'];
      var currentLastMessageId = t?.['2']?.['10'];

      if (id === undefined) return;

      promises.push(this.getCacheEntry(id).then(entry => {
        if (entry === undefined) return;

        // If the cache entry is still valid.
        if (currentLastMessageId !== undefined &&
            currentLastMessageId == entry.lastMessageId) {
          entry.lastUsedTimestamp = Math.floor(Date.now() / 1000);
          return this.putCacheEntry(entry).catch(err => {
            console.error(
                '[threadListAvatars] Error while updating lastUsedTimestamp from thread in cache:',
                err);
          });
        }

        console.debug(
            '[threadListAvatars] Invalidating thread', entry.threadId);
        return this.invalidateCacheEntryIfExists(entry.threadId).catch(err => {
          console.error(
              '[threadListAvatars] Error while invalidating thread from cache:',
              err);
        });
      }));
    });

    Promise.allSettled(promises).then(() => {
      if (Math.random() < probRemoveUnusedCacheEntries)
        this.removeUnusedCacheEntries().catch(err => {
          console.error(
              '[threadListAvatars] Error while removing unused cache entries:',
              err);
        });
    });
  }

  handleInvalidationByNewMessage(e) {
    var request = e?.detail?.body;
    var threadId = request?.['2'];
    if (threadId === undefined) {
      console.warn(
          '[threadListAvatars] Thread ID couldn\'t be parsed from the CreateMessage request.');
      return;
    }

    console.debug(
        '[threadListAvatars] Invalidating thread', threadId,
        'due to intercepting a CreateMessage request for that thread.');
    return this.invalidateCacheEntryIfExists(threadId);
  }

  // unauthorizedForums methods:
  isForumUnauthorized(forumId) {
    return this.dbPromise.then(db => db.get('unauthorizedForums', forumId))
        .then(entry => {
          if (entry === undefined) return false;

          var now = Math.floor(Date.now() / 1000);
          if (entry.expirationTimestamp > now) return true;

          this.invalidateUnauthorizedForum(forumId);
          return false;
        });
  }

  putUnauthorizedForum(forumId) {
    return this.dbPromise.then(db => db.put('unauthorizedForums', {
      forumId,
      expirationTimestamp:
          Math.floor(Date.now() / 1000) + unauthorizedForumExpirationTime,
    }));
  }

  invalidateUnauthorizedForum(forumId) {
    return this.dbPromise.then(db => db.delete('unauthorizedForums', forumId));
  }
};
