import { Platform } from "react-native";
import RNFetchBlob from "rn-fetch-blob";
import { dlog } from "react-native-digitcamera/src/common/DLogger";
import Database from "../../../../Components/common/DAsyncStorage";

/**
 * To make cache files names consistent accross application
 * we can use constants to store internal storage path of the file
 *
 * for ex.
 * PI_DEMO_VIDEO - name for pre inspection demo video
 *
 * usage :
 *
 * cacheFile(CACHE_CONSTANTS.PI_DEMO_VIDEO, remoteUri)
 *
 * const piCachedFiles = await Database.get("PICachedFiles");
 *
 * Now, we can directly access PI_DEMO_VIDEO internal storage path like this
 *
 * const localUri = piCachedFiles[CACHE_CONSTANTS.PI_DEMO_VIDEO]
 *
 * */

export const CACHE_CONSTANTS = {
  PI_DEMO_VIDEO: "PI_DEMO_VIDEO",
  PAYD_DEMO_VIDEO: "PAYD_DEMO_VIDEO",
  CAR_START: "CAR_START",
};

function cacheFileLog() {
  dlog("[CACHE FILE] [INFO] ", ...arguments);
}

function cacheFileError() {
  dlog("[CACHE FILE] [ERROR] ", ...arguments);
}

/**
 * cacheFile(fileName,remoteUri) - store/cache remote files into devices internal storage
 * fileName - name against which internal storage file path is stored in the DB PICachedFiles
 * remoteUri - uri to download data of
 */

export const cacheFile = (fileName, remoteUri) => {
  cacheFileLog(`Caching ${fileName} ${remoteUri}`);
  RNFetchBlob.config({
    fileCache: true,
  })
    .fetch("GET", remoteUri)
    .progress((received, total) => {
      cacheFileLog("progress", received / total);
    })
    .then((res) => {
      const filePath = res.path();
      cacheFileLog(" file path ", filePath);
      const storageFilePath = getAbsolutePath(filePath);
      cacheFileLog(" absolute file path ", storageFilePath);
      saveCacheFile(fileName, storageFilePath);
    })
    .catch((e) => {
      cacheFileError("error in cacheFile", e?.message);
    });
};

/**
 * saveeCacheFile(fileName,filePath) - saves file's internal storage path into DB PICachedFiles
 * fileName - name against which internal storage file path is stored in the DB PICachedFiles
 * filePath - absolute internal storage file path
 */

const saveCacheFile = async (fileName, filePath) => {
  /**
   * find if cacheFiles are there
   * if its empty add new
   *
   * this is to prevent overriding of existing files
   *
   */
  const piCacheFiles = await Database.get("PICachedFiles");
  if (piCacheFiles) {
    cacheFileLog(" exisiting piCacheFiles ", piCacheFiles);
    const newObject = { ...piCacheFiles };
    newObject[fileName] = filePath;
    cacheFileLog(" new piCacheFiles ", newObject);
    await Database.set("PICachedFiles", newObject);
  } else {
    const newObject = {};
    newObject[fileName] = filePath;
    cacheFileLog(" new piCacheFiles ", newObject);
    await Database.set("PICachedFiles", newObject);
  }
};

/**
 * removeAllCacheFiles() - removes cached files from the storage
 * */

const removeAllCacheFiles = async () => {
  const piCacheFiles = await Database.get("PICachedFiles");
  if (piCacheFiles) {
    for (let file in piCacheFiles) {
      if (file) {
        RNFetchBlob.fs
          .unlink(piCacheFiles[file])
          .then(() => {
            cacheFileLog("Deleted cache files");
          })
          .catch((e) => {
            cacheFileError(
              " error in removeAllCacheFiles . message ",
              e.message
            );
          });
      } else {
        cacheFileLog(`fileName does not exist in cache`);
      }
    }
  }
};

/**
 * removeCacheFile(fileName) - removes cached file named *fileName* from the storage
 * */
const removeCacheFile = async (fileName) => {
  const piCacheFiles = await Database.get("PICachedFiles");
  if (piCacheFiles) {
    if (piCacheFiles[fileName]) {
      RNFetchBlob.fs
        .unlink(piCacheFiles[fileName])
        .then(() => {
          cacheFileLog(`Deleted ${fileName} from cache`);
        })
        .catch((e) => {
          cacheFileError(" error in removeCacheFile . message ", e.message);
        });
    } else {
      cacheFileLog(`fileName does not exist in cache`);
    }
  }
};

/**
 * rnFetch does not provide absolute path of the file present inside internal storage
 * for android you have to append prefix file:// before the rnFetch generated path
 */

const getAbsolutePath = (path) => {
  return Platform.OS === "android" ? "file://" + path : "" + path;
};
