"use strict";

function countEvidenceRecords(db) {
  return countRecordsInStores(db, VENDORGET_EVIDENCE_STORE_NAMES);
}

function countLockedEvidenceRecords(db) {
  return countRecordsMatching(db, VENDORGET_EVIDENCE_STORE_NAMES, (record) => {
    return record?.bolRecordLock === true;
  });
}

function getEvidenceStoreCounts(db) {
  return new Promise((resolve, reject) => {
    const storeCounts = {};
    const tx = db.transaction(VENDORGET_EVIDENCE_STORE_NAMES, "readonly");

    tx.onerror = () => reject(tx.error);
    tx.onabort = () => reject(tx.error);
    tx.oncomplete = () => resolve(storeCounts);

    for (const storeName of VENDORGET_EVIDENCE_STORE_NAMES) {
      const countRequest = tx.objectStore(storeName).count();

      countRequest.onsuccess = () => {
        storeCounts[storeName] = countRequest.result;
      };
    }
  });
}

function purgeUnlockedEvidenceRecords(db) {
  return new Promise((resolve, reject) => {
    let deletedCount = 0;
    let keptLockedCount = 0;
    const tx = db.transaction(VENDORGET_EVIDENCE_STORE_NAMES, "readwrite");

    tx.onerror = () => reject(tx.error);
    tx.onabort = () => reject(tx.error);
    tx.oncomplete = () => {
      resolve({
        success: true,
        deletedCount,
        keptLockedCount
      });
    };

    for (const storeName of VENDORGET_EVIDENCE_STORE_NAMES) {
      const cursorRequest = tx.objectStore(storeName).openCursor();

      cursorRequest.onsuccess = () => {
        const cursor = cursorRequest.result;

        if (!cursor) {
          return;
        }

        if (cursor.value?.bolRecordLock === true) {
          keptLockedCount += 1;
          cursor.continue();
          return;
        }

        deletedCount += 1;
        cursor.delete();
        cursor.continue();
      };
    }
  });
}

function countRecordsInStores(db, storeNames) {
  return new Promise((resolve, reject) => {
    let totalCount = 0;
    const tx = db.transaction(storeNames, "readonly");

    tx.onerror = () => reject(tx.error);
    tx.onabort = () => reject(tx.error);
    tx.oncomplete = () => resolve(totalCount);

    for (const storeName of storeNames) {
      const countRequest = tx.objectStore(storeName).count();

      countRequest.onsuccess = () => {
        totalCount += countRequest.result;
      };
    }
  });
}

function countRecordsMatching(db, storeNames, predicate) {
  return new Promise((resolve, reject) => {
    let totalCount = 0;
    const tx = db.transaction(storeNames, "readonly");

    tx.onerror = () => reject(tx.error);
    tx.onabort = () => reject(tx.error);
    tx.oncomplete = () => resolve(totalCount);

    for (const storeName of storeNames) {
      const cursorRequest = tx.objectStore(storeName).openCursor();

      cursorRequest.onsuccess = () => {
        const cursor = cursorRequest.result;

        if (!cursor) {
          return;
        }

        if (predicate(cursor.value)) {
          totalCount += 1;
        }

        cursor.continue();
      };
    }
  });
}
