//
//  CachedImageView.swift
//  Tusker
//
//  Created by Shadowfacts on 10/4/22.
//  Copyright © 2022 Shadowfacts. All rights reserved.
//

import UIKit

class CachedImageView: UIImageView {
    
    var cache: ImageCache!
    private var url: URL?
    private var isGrayscale = false
    private var fetchTask: Task<Void, Error>?
    private var blurHashTask: DispatchWorkItem?
    
    override var image: UIImage? {
        didSet {
            blurHashTask?.cancel()
        }
    }
    
    init(cache: ImageCache) {
        self.cache = cache
        super.init(frame: .zero)
        commonInit()
    }
    
    required init?(coder: NSCoder) {
        super.init(coder: coder)
        commonInit()
    }
    
    private func commonInit() {
        NotificationCenter.default.addObserver(self, selector: #selector(preferencesChanged), name: .preferencesChanged, object: nil)
    }
    
    func update(for url: URL?, blurhash: String? = nil, placeholder: UIImage? = nil) {
        if url != self.url || (url != nil && self.image == nil) {
            self.url = url
            super.image = placeholder
            updateBlurhash(blurhash, for: url)
            updateImage()
        }
    }
    
    func showOnlyBlurHash(_ blurhash: String, for url: URL) {
        if url != self.url {
            self.url = url
            updateBlurhash(blurhash, for: url)
        }
    }
    
    @objc private func preferencesChanged() {
        if isGrayscale != Preferences.shared.grayscaleImages {
            updateImage()
        }
    }
    
    private func updateBlurhash(_ blurhash: String?, for url: URL?) {
        blurHashTask?.cancel()
        
        if let blurhash {
            let aspectRatio = self.bounds.width > 0 ? self.bounds.height / self.bounds.width : 1
            blurHashTask = DispatchWorkItem {
                let size = CGSize(width: 60, height: aspectRatio * 60)
                let image = UIImage(blurHash: blurhash, size: size)
                DispatchQueue.main.async {
                    if self.image == nil && self.url == url && self.blurHashTask?.isCancelled == false {
                        self.image = image
                    }
                }
            }
            AttachmentView.queue.async(execute: blurHashTask!)
        }
    }
    
    private func updateImage() {
        fetchTask?.cancel()
        
        guard let url else {
            return
        }
        
        fetchTask = Task(priority: .high) {
            let (_, image) = await cache.get(url)
            guard let image else {
                return
            }
            try Task.checkCancellation()
            // TODO: check that this isn't on the main thread
            guard let transformedImage = ImageGrayscalifier.convertIfNecessary(url: url, image: image) else {
                return
            }
            try Task.checkCancellation()
            super.image = transformedImage
            self.isGrayscale = Preferences.shared.grayscaleImages
            self.blurHashTask?.cancel()
        }
    }
    
}
