text: var fs = require('fs-extra')
  var path = require('path')
  var utils = require('./utils')
  const { uuid } = require('uuidv4');
  const config_api = require('./config');
  
  var logger = null;
  var db = null;
  var users_db = null;
  function setDB(input_db, input_users_db) { db = input_db; users_db = input_users_db }
  function setLogger(input_logger) { logger = input_logger; }
  
  function initialize(input_db, input_users_db, input_logger) {
      setDB(input_db, input_users_db);
      setLogger(input_logger);
  }
  
  function registerFileDB(file_path, type, multiUserMode = null, sub = null) {
      let db_path = null;
      const file_id = file_path.substring(0, file_path.length-4);
      const file_object = generateFileObject(file_id, type, multiUserMode && multiUserMode.file_path, sub);
      if (!file_object) {
          logger.error(`Could not find associated JSON file for ${type} file ${file_id}`);
          return false;
      }
  
      utils.fixVideoMetadataPerms(file_id, type, multiUserMode && multiUserMode.file_path);
  
      // add thumbnail path
      file_object['thumbnailPath'] = utils.getDownloadedThumbnail(file_id, type, multiUserMode && multiUserMode.file_path);
  
      if (!sub) {
          if (multiUserMode) {
              const user_uid = multiUserMode.user;
              db_path = users_db.get('users').find({uid: user_uid}).get(`files.${type}`);
          } else {
              db_path = db.get(`files.${type}`)
          }
      } else {
          if (multiUserMode) {
              const user_uid = multiUserMode.user;
              db_path = users_db.get('users').find({uid: user_uid}).get('subscriptions').find({id: sub.id}).get('videos');
          } else {
              db_path = db.get('subscriptions').find({id: sub.id}).get('videos');
          }
      }
  
      const file_uid = registerFileDBManual(db_path, file_object);
  
      // remove metadata JSON if needed
      if (!config_api.getConfigItem('ytdl_include_metadata')) {
          utils.deleteJSONFile(file_id, type, multiUserMode && multiUserMode.file_path)
      }
  
      return file_uid;
  }
  
  function registerFileDBManual(db_path, file_object) {
      // add additional info
      file_object['uid'] = uuid();
      file_object['registered'] = Date.now();
      path_object = path.parse(file_object['path']);
      file_object['path'] = path.format(path_object);
  
      // remove duplicate(s)
      db_path.remove({path: file_object['path']}).write();
  
      // add new file to db
      db_path.push(file_object).write();
      return file_object['uid'];
  }
  
  function generateFileObject(id, type, customPath = null, sub = null) {
      if (!customPath && sub) {
          customPath = getAppendedBasePathSub(sub, config_api.getConfigItem('ytdl_subscriptions_base_path'));
      }
      var jsonobj = (type === 'audio') ? utils.getJSONMp3(id, customPath, true) : utils.getJSONMp4(id, customPath, true);
      if (!jsonobj) {
          return null;
      }
      const ext = (type === 'audio') ? '.mp3' : '.mp4'
      const file_path = utils.getTrueFileName(jsonobj['_filename'], type); // path.join(type === 'audio' ? audioFolderPath : videoFolderPath, id + ext);
      // console.
      var stats = fs.statSync(path.join(__dirname, file_path));
  
      var title = jsonobj.title;
      var url = jsonobj.webpage_url;
      var uploader = jsonobj.uploader;
      var upload_date = jsonobj.upload_date;
      upload_date = upload_date ? `${upload_date.substring(0, 4)}-${upload_date.substring(4, 6)}-${upload_date.substring(6, 8)}` : 'N/A';
  
      var size = stats.size;
  
      var thumbnail = jsonobj.thumbnail;
      var duration = jsonobj.duration;
      var isaudio = type === 'audio';
      var file_obj = new utils.File(id, title, thumbnail, isaudio, duration, url, uploader, size, file_path, upload_date);
      return file_obj;
  }
  
  function updatePlaylist(playlist, user_uid) {
      let playlistID = playlist.id;
      let type = playlist.type;
      let db_loc = null;
      if (user_uid) {
          db_loc = users_db.get('users').find({uid: user_uid}).get(`playlists.${type}`).find({id: playlistID});
      } else {
          db_loc = db.get(`playlists.${type}`).find({id: playlistID});
      }
      db_loc.assign(playlist).write();
      return true;
  }
  
  function getAppendedBasePathSub(sub, base_path) {
      return path.join(base_path, (sub.isPlaylist ? 'playlists/' : 'channels/'), sub.name);
  }
  
  async function importUnregisteredFiles() {
      let dirs_to_check = [];
      let subscriptions_to_check = [];
      const subscriptions_base_path = config_api.getConfigItem('ytdl_subscriptions_base_path'); // only for single-user mode
      const multi_user_mode = config_api.getConfigItem('ytdl_multi_user_mode');
      const usersFileFolder = config_api.getConfigItem('ytdl_users_base_path');
      const subscriptions_enabled = config_api.getConfigItem('ytdl_allow_subscriptions');
      if (multi_user_mode) {
          let users = users_db.get('users').value();
          for (let i = 0; i < users.length; i++) {
              const user = users[i];
  
              if (subscriptions_enabled) subscriptions_to_check = subscriptions_to_check.concat(users[i]['subscriptions']);
  
              // add user's audio dir to check list
              dirs_to_check.push({
                  basePath: path.join(usersFileFolder, user.uid, 'audio'),
                  dbPath: users_db.get('users').find({uid: user.uid}).get('files.audio'),
                  type: 'audio'
              });
  
              // add user's video dir to check list
              dirs_to_check.push({
                  basePath: path.join(usersFileFolder, user.uid, 'video'),
                  dbPath: users_db.get('users').find({uid: user.uid}).get('files.video'),
                  type: 'video'
              });
          }
      } else {
          const audioFolderPath = config_api.getConfigItem('ytdl_audio_folder_path');
          const videoFolderPath = config_api.getConfigItem('ytdl_video_folder_path');
          const subscriptions = db.get('subscriptions').value();
  
          if (subscriptions_enabled && subscriptions) subscriptions_to_check = subscriptions_to_check.concat(subscriptions);
  
          // add audio dir to check list
          dirs_to_check.push({
              basePath: audioFolderPath,
              dbPath: db.get('files.audio'),
              type: 'audio'
          });
  
          // add video dir to check list
          dirs_to_check.push({
              basePath: videoFolderPath,
              dbPath: db.get('files.video'),
              type: 'video'
          });
      }
  
      // add subscriptions to check list
      for (let i = 0; i < subscriptions_to_check.length; i++) {
          let subscription_to_check = subscriptions_to_check[i];
          if (!subscription_to_check.name) {
              // TODO: Remove subscription as it'll never complete
              continue;
          }
          dirs_to_check.push({
              basePath: multi_user_mode ? path.join(usersFileFolder, subscription_to_check.user_uid, 'subscriptions', subscription_to_check.isPlaylist ? 'playlists/' : 'channels/', subscription_to_check.name)
                                        : path.join(subscriptions_base_path, subscription_to_check.isPlaylist ? 'playlists/' : 'channels/', subscription_to_check.name),
              dbPath: multi_user_mode ? users_db.get('users').find({uid: subscription_to_check.user_uid}).get('subscriptions').find({id: subscription_to_check.id}).get('videos')
                                      : db.get('subscriptions').find({id: subscription_to_check.id}).get('videos'),
              type: subscription_to_check.type
          });
      }
  
      // run through check list and check each file to see if it's missing from the db
      dirs_to_check.forEach(dir_to_check => {
          // recursively get all files in dir's path
          const files = utils.getDownloadedFilesByType(dir_to_check.basePath, dir_to_check.type);
  
          files.forEach(file => {
              // check if file exists in db, if not add it
              const file_is_registered = !!(dir_to_check.dbPath.find({id: file.id}).value())
              if (!file_is_registered) {
                  // add additional info
                  registerFileDBManual(dir_to_check.dbPath, file);
                  logger.verbose(`Added discovered file to the database: ${file.id}`);
              }
          });
      });
  
  }
  
  module.exports = {
      initialize: initialize,
      registerFileDB: registerFileDB,
      updatePlaylist: updatePlaylist,
      importUnregisteredFiles: importUnregisteredFiles
  }
  