// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

import Foundation

#if os(iOS)
import Flutter
#elseif os(macOS)
import FlutterMacOS
#endif

public class PathProviderPlugin: NSObject, FlutterPlugin, PathProviderApi {
  public static func register(with registrar: FlutterPluginRegistrar) {
    let instance = PathProviderPlugin()
    // Workaround for https://github.com/flutter/flutter/issues/118103.
#if os(iOS)
    let messenger = registrar.messenger()
#else
    let messenger = registrar.messenger
#endif
    PathProviderApiSetup.setUp(binaryMessenger: messenger, api: instance)
  }

  func getDirectoryPath(type: DirectoryType) -> String? {
    var path = getDirectory(ofType: fileManagerDirectoryForType(type))
  #if os(macOS)
    // In a non-sandboxed app, these are shared directories where applications are
    // expected to use its bundle ID as a subdirectory. (For non-sandboxed apps,
    // adding the extra path is harmless).
    // This is not done for iOS, for compatibility with older versions of the
    // plugin.
    if type == .applicationSupport || type == .applicationCache {
      if let basePath = path {
        let basePathURL = URL.init(fileURLWithPath: basePath)
        path = basePathURL.appendingPathComponent(Bundle.main.bundleIdentifier!).path
      }
    }
  #endif
    return path
  }

  // Returns the path for the container of the specified app group.
  func getContainerPath(appGroupIdentifier: String) -> String? {
      return FileManager.default.containerURL(forSecurityApplicationGroupIdentifier: appGroupIdentifier)?.path
  }
}

/// Returns the FileManager constant corresponding to the given type.
private func fileManagerDirectoryForType(_ type: DirectoryType) -> FileManager.SearchPathDirectory {
  switch type {
    case .applicationCache:
      return FileManager.SearchPathDirectory.cachesDirectory
    case .applicationDocuments:
      return FileManager.SearchPathDirectory.documentDirectory
    case .applicationSupport:
      return FileManager.SearchPathDirectory.applicationSupportDirectory
    case .downloads:
      return FileManager.SearchPathDirectory.downloadsDirectory
    case .library:
      return FileManager.SearchPathDirectory.libraryDirectory
    case .temp:
      return FileManager.SearchPathDirectory.cachesDirectory
  }
}

/// Returns the user-domain directory of the given type.
private func getDirectory(ofType directory: FileManager.SearchPathDirectory) -> String? {
  let paths = NSSearchPathForDirectoriesInDomains(
    directory,
    FileManager.SearchPathDomainMask.userDomainMask,
    true)
  return paths.first
}
