//
//  File.swift
//  
//
//  Created by iMac on 01.12.21.
//

import Foundation


protocol DiskWriter: AnyObject {
    
    var storageFile: FileHandle { get set }
    
    var storageFileUrl: URL { get }
}

extension DiskWriter {

    func replaceFile(data: String) throws {
        let data = data.data(using: .utf8)!
        try storageFile.close()
        try data.write(to: storageFileUrl)
        storageFile = try FileHandle(forUpdating: storageFileUrl)
        if #available(macOS 10.15.4, *) {
            try storageFile.seekToEnd()
        } else {
            storageFile.seekToEndOfFile()
        }
    }
    
    static func prepareFile(at url: URL) throws -> FileHandle {
        if !FileManager.default.fileExists(atPath: url.path) {
            try Data().write(to: url)
        }
        return try FileHandle(forUpdating: url)
    }
    
    func writeToDisk(line: String) -> Bool {
        let data = (line + "\n").data(using: .utf8)!
        do {
            if #available(macOS 10.15.4, *) {
                try storageFile.write(contentsOf: data)
            } else {
                storageFile.write(data)
            }
            try storageFile.synchronize()
            return true
        } catch {
            print("Failed to save data to file: \(storageFileUrl.path): \(error)")
            return false
        }
    }
    
    func readDataFromDisk() throws -> Data {
        if #available(macOS 10.15.4, *) {
            guard let data = try storageFile.readToEnd() else {
                try storageFile.seekToEnd()
                return Data()
            }
            return data
        } else {
            return storageFile.readDataToEndOfFile()
        }
    }
    
    func readLinesFromDisk() throws -> [String] {
        let data = try readDataFromDisk()
        return parseLines(data: data)
    }
    
    private func parseLines(data: Data) -> [String] {
        String(data: data, encoding: .utf8)!
            .components(separatedBy: "\n")
            .map { $0.trimmingCharacters(in: .whitespacesAndNewlines) }
            .filter { $0 != "" }
    }
}
