import {timestamp} from '@configs/types';
import MyUserManager from '@user/MyUserManager';
import Realm from 'realm';
Realm.flags.THROW_ON_GLOBAL_REALM = true;
import {getKey} from './encryption';
import {
  databaseConf,
  databaseNames,
  databaseNameSuffix,
  mergeDBName,
} from './types';

import RNFS from 'react-native-fs';
import {databaseConfType} from './schemas';

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: string;
  schema: databaseConfType;
  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: databaseConfType,
  nameObj: databaseNameSuffix,
): Promise<DBType> {
  const folderPath = MyUserManager.getSelectedUserAccount();
  const path =
    folderPath +
    '/' +
    schema.filePath +
    (nameObj.suffix !== undefined ? '_' + nameObj.suffix : '');

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

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

  console.log('schema.details', schema.details);

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

  console.log('path', path);
  return realm;
}

export async function getDatabase(
  _name: databaseNameSuffix,
  init?: boolean,
): Promise<DBType> {
  const name = mergeDBName(_name);
  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, _name);
      dbObj.lastUsedTimestamp = getTime();
      dbObj.db = db;
      return db;
    }
  } else {
    throw "Database '" + name + "' is not initialized";
  }
}
