// Copyright 2023-present 650 Industries. All rights reserved.

import Foundation

@objc(EXFileSystemLegacyUtilities)
public class FileSystemLegacyUtilities: NSObject, EXInternalModule, EXFileSystemInterface, EXFilePermissionModuleInterface {
  @objc
  public var documentDirectory: String

  @objc
  public var cachesDirectory: String

  @objc
  public var applicationSupportDirectory: String

  var appGroupSharedDirectories: [String]?

  var isScoped: Bool = false

  @objc
  public init(documentDirectory: String, cachesDirectory: String, applicationSupportDirectory: String) {
    self.documentDirectory = documentDirectory
    self.cachesDirectory = cachesDirectory
    self.applicationSupportDirectory = applicationSupportDirectory
    self.isScoped = true

    super.init()
    ensureDirExists(withPath: self.cachesDirectory)
    ensureDirExists(withPath: self.documentDirectory)
    ensureDirExists(withPath: self.applicationSupportDirectory)
  }

  required public override init() {
    let documentPaths = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)
    self.documentDirectory = documentPaths[0]

    let cachesPaths = NSSearchPathForDirectoriesInDomains(.cachesDirectory, .userDomainMask, true)
    self.cachesDirectory = cachesPaths[0]

    let applicationSupportDirectoryPaths =
    NSSearchPathForDirectoriesInDomains(.applicationSupportDirectory, .userDomainMask, true)
    self.applicationSupportDirectory = applicationSupportDirectoryPaths[0]

    super.init()
    ensureDirExists(withPath: self.cachesDirectory)
    ensureDirExists(withPath: self.documentDirectory)
    ensureDirExists(withPath: self.applicationSupportDirectory)
  }

  public static func exportedInterfaces() -> [Protocol] {
    return [EXFileSystemInterface.self, EXFilePermissionModuleInterface.self]
  }

  @objc
  public func permissions(forURI uri: URL) -> EXFileSystemPermissionFlags {
    let validSchemas = [
      "assets-library",
      "http",
      "https",
      "ph"
    ]

    if validSchemas.contains(uri.scheme ?? "") {
      return EXFileSystemPermissionFlags.read
    }
    if uri.scheme == "file" {
      return getPathPermissions(uri.absoluteString)
    }
    return []
  }

  @objc
  public func generatePath(inDirectory directory: String, withExtension ext: String) -> String {
    let fileName = "\(UUID().uuidString)\(ext)"
    ensureDirExists(withPath: directory)
    return (directory as NSString).appendingPathComponent(fileName)
  }

  @objc
  @discardableResult
  public func ensureDirExists(withPath path: String) -> Bool {
    let url = URL(fileURLWithPath: path)
    return FileSystemUtilities.ensureDirExists(at: url)
  }

  @objc
  public func getPathPermissions(_ path: String) -> EXFileSystemPermissionFlags {
    guard let url = convertToUrl(string: path) else {
      return []
    }
    let permissionsForInternalDirectories = getInternalPathPermissions(url)
    if !permissionsForInternalDirectories.isEmpty {
      return permissionsForInternalDirectories
    }
    return getExternalPathPermissions(url)
  }

  @objc
  public func getInternalPathPermissions(_ url: URL) -> EXFileSystemPermissionFlags {
    let appGroupSharedDirectories: [String] = self.appGroupSharedDirectories ?? []
    let scopedDirs: [String] = [cachesDirectory, documentDirectory, applicationSupportDirectory] + appGroupSharedDirectories
    let standardizedPath = url.standardized.path
    for scopedDirectory in scopedDirs {
      if standardizedPath.hasPrefix(scopedDirectory + "/") || standardizedPath == scopedDirectory {
        return [.read, .write]
      }
    }
    return []
  }

  @objc
  public func getExternalPathPermissions(_ url: URL) -> EXFileSystemPermissionFlags {
    if self.isScoped && url.path.contains("ExponentExperienceData") {
      return []
    }
    var filePermissions: EXFileSystemPermissionFlags = []
    if FileManager.default.isReadableFile(atPath: url.path) {
      filePermissions.insert(.read)
    }
    if FileManager.default.isWritableFile(atPath: url.path) {
      filePermissions.insert(.write)
    }
    return filePermissions
  }

  internal func maybeInitAppGroupSharedDirectories(_ directories: [URL]) {
    if appGroupSharedDirectories != nil {
      return
    }
    var appGroupSharedDirectories: [String] = []
    for directory in directories {
      appGroupSharedDirectories.append(directory.standardized.path)
    }
    self.appGroupSharedDirectories = appGroupSharedDirectories
  }
}
