import {timestamp} from '@caj/configs/types';
import MyUserManager from '@caj/user/MyUserManager';
import Realm from 'realm';
import {getKey} from './encryption';
import {databaseConf, databaseNames} from './types';

import RNFS from 'react-native-fs';

const closeTimeout = 5; // in seconds // when DB read/writes is too long in idle it will be closed

type DBType = Realm;

export interface DBObject {
  name: databaseNames;
  schema: databaseConf<{[key: string]: string}>;
  db: DBType | undefined;
  lastUsedTimestamp?: timestamp; // when timeout is undefined then db is closed
}

export type DBs = {[key: string]: DBObject};
export let databases: DBs = {};

function getTime() {
  return Math.floor(new Date().getTime() / 1000);
}

setInterval(() => {
  const curTime = getTime();

  for (let name in databases) {
    let dbObj = databases[name];

    if (
      dbObj.lastUsedTimestamp !== undefined &&
      dbObj.lastUsedTimestamp + closeTimeout < curTime
    ) {
      dbObj.db?.close();
      dbObj.lastUsedTimestamp = undefined;
      //console.log('Database not used. Closing ' + dbObj.name);
    }
  }
}, 5000);

export function closeAllDatabases() {
  for (let name in databases) {
    let dbObj = databases[name];

    if (dbObj.lastUsedTimestamp !== undefined) {
      dbObj.db?.close();
      dbObj.lastUsedTimestamp = undefined;
    }
  }
}

export async function openMyDatabase(
  schema: databaseConf<{[key: string]: string}>,
): Promise<DBType> {
  const folderPath = MyUserManager.getSelectedUserId();
  const path = folderPath + '/' + schema.filePath;

  const folderExists = await RNFS.exists(
    RNFS.DocumentDirectoryPath + '/' + folderPath,
  );

  if (folderExists === false) {
    await RNFS.mkdir(RNFS.DocumentDirectoryPath + '/' + folderPath);
  }

  return await Realm.open({
    schema: [schema.details as any],
    schemaVersion: schema.version,
    path,
    encryptionKey: getKey(),
  });
}

export async function getDatabase(
  name: databaseNames,
  init?: boolean,
): Promise<DBType> {
  let dbObj = databases[name];
  if (dbObj !== undefined) {
    if (dbObj.lastUsedTimestamp !== undefined && dbObj.db !== undefined) {
      dbObj.lastUsedTimestamp = getTime();
      return dbObj.db;
    } else {
      dbObj.lastUsedTimestamp = undefined;
      const db = await openMyDatabase(dbObj.schema);
      dbObj.lastUsedTimestamp = getTime();
      dbObj.db = db;
      return db;
    }
  } else {
    throw "Database '" + name + "' is not initialized";
  }
}
