import Foundation

extension URL {

    func createParentFolderIfNeeded() throws {
        try deletingLastPathComponent().createIfNeeded()
    }

    func createIfNeeded() throws {
        guard !exists else {
            return
        }
        try FileManager.default.createDirectory(at: self, withIntermediateDirectories: true)
    }

    var isDirectory: Bool {
        do {
            let resources = try resourceValues(forKeys: [.isDirectoryKey])
            guard let isDirectory = resources.isDirectory else {
                print("No isDirectory info for \(path)")
                return false
            }
            return isDirectory
        } catch {
            print("Failed to get directory information from \(path): \(error)")
            return false
        }
    }

    var exists: Bool {
        FileManager.default.fileExists(atPath: path)
    }

    /**
     Delete the file at the url.
     */
    func delete() throws {
        try FileManager.default.removeItem(at: self)
    }

    func copy(to url: URL) throws {
        if url.exists {
            try url.delete()
        }
        try url.createParentFolderIfNeeded()
        try FileManager.default.copyItem(at: self, to: url)
    }

    var size: Int? {
        let attributes = try? FileManager.default.attributesOfItem(atPath: path)
        return (attributes?[.size] as? NSNumber)?.intValue
    }

    func resolvingFolderTraversal() -> URL? {
        var components = [String]()
        absoluteString.components(separatedBy: "/").forEach { part in
            if part == ".." {
                if !components.isEmpty {
                    _ = components.popLast()
                } else {
                    components.append("..")
                }
                return
            }
            if part == "." {
                return
            }
            components.append(part)
        }
        return URL(string: components.joined(separator: "/"))
    }

    func containedFiles() throws -> [URL] {
        try FileManager.default.contentsOfDirectory(at: self, includingPropertiesForKeys: nil, options: [])
            .filter { !$0.hasDirectoryPath }
    }

    func containedFileNames() throws -> [String] {
        try FileManager.default.contentsOfDirectory(atPath: path())
            .filter { !$0.hasPrefix(".") }
    }
}
