import Foundation

enum CacheItemMigrationPolicyError: Error {
    case unrecognizedSourceAttributeTypes
}

class CacheItemMigrationPolicy: NSEntityMigrationPolicy {
    
    private let fetcher = ImageFetcher()
    
    override func createDestinationInstances(forSource sInstance: NSManagedObject, in mapping: NSEntityMapping, manager: NSMigrationManager) throws {
        
        if sInstance.entity.name == "CacheItem" {
            
            guard let key = sInstance.primitiveValue(forKey: "key") as? String,
                let variant = sInstance.primitiveValue(forKey: "variant") as? Int64,
                let date = sInstance.primitiveValue(forKey: "date") as? Date else {
                    throw CacheItemMigrationPolicyError.unrecognizedSourceAttributeTypes
            }
            
            let destinationItem = NSEntityDescription.insertNewObject(forEntityName: "CacheItem", into: manager.destinationContext)
            
            destinationItem.setValue(key, forKey: "key")
            
            let newVariant = String(variant)
            destinationItem.setValue(newVariant, forKey: "variant")
            destinationItem.setValue(date, forKey: "date")
            var isDownloaded = false
            autoreleasepool { () -> Void in
                guard
                    let fileName = fetcher.uniqueFileNameForItemKey(key, variant: newVariant),
                    let headerFileName = fetcher.uniqueHeaderFileNameForItemKey(key, variant: newVariant) else {
                        return
                }
                let fileURL = CacheFileWriterHelper.fileURL(for: fileName)
                let filePath = fileURL.path
                // artifically create and save image response header
                var headers: [String: String] = [:]
                headers["Content-Type"] = FileManager.default.getValueForExtendedFileAttributeNamed(WMFExtendedFileAttributeNameMIMEType, forFileAtPath: filePath)
                let values = try? fileURL.resourceValues(forKeys: [URLResourceKey.fileSizeKey])
                if let fileSize = values?.fileSize {
                    headers["Content-Length"] = String(fileSize)
                }
                guard !headers.isEmpty else {
                    return
                }
                CacheFileWriterHelper.saveResponseHeader(headerFields: headers, toNewFileName: headerFileName) { (result) in
                    switch result {
                    case .success, .exists:
                        isDownloaded = true
                    case .failure:
                        break
                    }
                }
            }
            destinationItem.setValue(isDownloaded, forKey: "isDownloaded")
            destinationItem.setValue(nil, forKey: "url")
            manager.associate(sourceInstance: sInstance, withDestinationInstance: destinationItem, for: mapping)
            
        }
    }
}
