//
//  PhotoAsset.swift
//  
//  Copyright © 2016-2019 Apple Inc. All rights reserved.
//

import Foundation
import Photos
import PlaygroundSupport
import SPCCore

typealias PhotoAssetType = PHAssetMediaType

/// A photo asset represents a **Photos** photo.
///
/// - localizationKey: PhotoAsset
public class PhotoAsset {
    private var _asset: PHAsset?
    private var asset: PHAsset? {
        if _asset == nil {
            guard let identifier = identifier else { return nil }
            let fetchedAssets = PHAsset.fetchAssets(withLocalIdentifiers: [identifier], options: nil)
            _asset = fetchedAssets.firstObject
        }
        return _asset
    }
    
    /// The photo asset collection identifier, if it has one.
    ///
    /// - localizationKey: PhotoAsset.identifier
    public var identifier: String?
    
    /// Creates an empty photo asset.
    ///
    /// - localizationKey: PhotoAsset()
    public init() { }
    
    init(asset: PHAsset) {
        self._asset = asset
        self.identifier = asset.localIdentifier
    }
    
    init(identifier: String) {
        self.identifier = identifier
    }
    
    public var image: Image {
        var requestedImage = Image()
        guard let asset = self.asset else { return requestedImage }
        
        let targetSize = CGSize(width: 800, height: 800)
        let requestOptions = PHImageRequestOptions()
        requestOptions.deliveryMode = .highQualityFormat
        requestOptions.resizeMode = .fast
        requestOptions.isSynchronous = true
        
        PHImageManager.default().requestImage(for: asset,
                                              targetSize: targetSize,
                                              contentMode: .aspectFit,
                                              options: requestOptions,
                                              resultHandler: { (image, info) in
                                                
// Excluded for compilation optimization.
//                                                if let infoDict = info {
//                                                    if let error = infoDict[PHImageErrorKey] as? NSError {
//                                                        PBLog("requestImage error = \(error.localizedDescription)")
//                                                    }
//                                                    if let value = infoDict[PHImageResultIsInCloudKey] as? Bool {
//                                                        PBLog("requestImage in the cloud: \(value)")
//                                                    }
//                                                }
                                                
                                                if let image = image {
                                                    requestedImage = image
                                                }
        })
        
        return requestedImage
    }
    
    public func fetchImage(targetSize: Size, completion: @escaping (_ image: Image) -> ()) {
        
        DispatchQueue.global(qos: .background).async {
            
            guard let asset = self.asset else {
                DispatchQueue.main.async {
                    completion(Image())
                }
                return
            }
            
            let requestOptions = PHImageRequestOptions()
            requestOptions.deliveryMode = .highQualityFormat
            requestOptions.resizeMode = .fast
            requestOptions.isSynchronous = true
            
            PHImageManager.default().requestImage(for: asset,
                                                  targetSize: targetSize.cgSize,
                                                  contentMode: .aspectFit,
                                                  options: requestOptions,
                                                  resultHandler: { (image, info) in
                                                    DispatchQueue.main.async {
                                                        completion(image ?? Image())
                                                    }
            })
        }
    }
}

extension PhotoAsset: PlaygroundValueTransformable {
    
    public var playgroundValue: PlaygroundValue? {
        guard let identifier = self.identifier else { return nil }
        return .string(identifier)
    }
    
    public static func from(_ playgroundValue: PlaygroundValue) -> PlaygroundValueTransformable? {
        guard case .string(let identifier) = playgroundValue, !identifier.isEmpty else { return nil }
        
        return PhotoAsset(identifier: identifier)
    }
}
