//
//  TrendingLinkCardCollectionViewCell.swift
//  Tusker
//
//  Created by Shadowfacts on 6/29/22.
//  Copyright © 2022 Shadowfacts. All rights reserved.
//

import UIKit
import Pachyderm
import WebURLFoundationExtras
import SwiftSoup

class TrendingLinkCardCollectionViewCell: UICollectionViewCell {
    
    private var card: Card?
    
    @IBOutlet weak var thumbnailView: CachedImageView!
    @IBOutlet weak var titleLabel: UILabel!
    @IBOutlet weak var descriptionLabel: UILabel!
    @IBOutlet weak var providerLabel: UILabel!
    @IBOutlet weak var activityLabel: UILabel!
    @IBOutlet weak var historyView: TrendHistoryView!
    private var thumbnailAspectRatioConstraint: NSLayoutConstraint?
    
    var verticalSize: VerticalSize! {
        didSet {
            guard oldValue != verticalSize else {
                return
            }
            switch verticalSize {
            case nil:
                fatalError()
            case .regular:
                thumbnailAspectRatioConstraint?.isActive = false
                thumbnailAspectRatioConstraint = thumbnailView.widthAnchor.constraint(equalTo: thumbnailView.heightAnchor, multiplier: 4/3)
                thumbnailAspectRatioConstraint!.isActive = true
                descriptionLabel.numberOfLines = 3
            case .compact:
                thumbnailAspectRatioConstraint?.isActive = false
                thumbnailAspectRatioConstraint = thumbnailView.widthAnchor.constraint(equalTo: thumbnailView.heightAnchor, multiplier: 2/1)
                thumbnailAspectRatioConstraint!.isActive = true
                descriptionLabel.numberOfLines = 5
            }
        }
    }
    
    private var hoverGestureAnimator: UIViewPropertyAnimator?
    
    override func awakeFromNib() {
        super.awakeFromNib()
        
        thumbnailView.cache = .attachments
        
        layer.shadowOpacity = 0.2
        layer.shadowRadius = 8
        layer.shadowOffset = .zero
        layer.masksToBounds = false
        contentView.layer.cornerRadius = 12.5
        contentView.layer.cornerCurve = .continuous
        contentView.backgroundColor = .appGroupedCellBackground
        updateLayerColors()
        
        verticalSize = .regular
        
        addGestureRecognizer(UIHoverGestureRecognizer(target: self, action: #selector(hoverRecognized)))
    }
    
    func updateUI(card: Card) {
        self.card = card
        self.thumbnailView.image = nil
        
        thumbnailView.update(for: card.image.flatMap { URL($0) }, blurhash: card.blurhash)
        
        let title = card.title.trimmingCharacters(in: .whitespacesAndNewlines)
        titleLabel.text = title
        
        let provider = card.providerName!.trimmingCharacters(in: .whitespacesAndNewlines)
        providerLabel.text = provider
        
        let description = try! SwiftSoup.parseBodyFragment(card.description).text()
        descriptionLabel.text = description
        descriptionLabel.isHidden = description.isEmpty
        
        let sorted = card.history!.sorted(by: { $0.day < $1.day })
        let lastTwo = sorted[(sorted.count - 2)...]
        let accounts = lastTwo.map(\.accounts).reduce(0, +)
        let uses = lastTwo.map(\.uses).reduce(0, +)
        
        // U+2009 THIN SPACE
        let activityStr = NSMutableAttributedString(string: "\(accounts.formatted())\u{2009}")
        activityStr.append(NSAttributedString(attachment: NSTextAttachment(image: UIImage(systemName: "person")!)))
        activityStr.append(NSAttributedString(string: ", \(uses.formatted())\u{2009}"))
        activityStr.append(NSAttributedString(attachment: NSTextAttachment(image: UIImage(systemName: "square.text.square")!)))
        activityLabel.attributedText = activityStr
        
        historyView.setHistory(card.history)
        historyView.isHidden = card.history == nil || card.history!.count < 2
    }
    
    private func loadBlurHash(card: Card) {
        guard let hash = card.blurhash else {
            return
        }
        AttachmentView.queue.async { [weak self] in
            let size: CGSize
            if let width = card.width, let height = card.height {
                let aspectRatio = CGFloat(width) / CGFloat(height)
                if aspectRatio > 1 {
                    size = CGSize(width: 32, height: 32 / aspectRatio)
                } else {
                    size = CGSize(width: 32 * aspectRatio, height: 32)
                }
            } else {
                size = CGSize(width: 32, height: 32)
            }

            guard let preview = UIImage(blurHash: hash, size: size) else {
                return
            }
            DispatchQueue.main.async { [weak self] in
                guard let self,
                      self.card?.url == card.url,
                      self.thumbnailView.image == nil else {
                    return
                }
                self.thumbnailView.image = preview
            }
        }
    }
    
    override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) {
        super.traitCollectionDidChange(previousTraitCollection)
        updateLayerColors()
    }
    
    private func updateLayerColors() {
        if traitCollection.userInterfaceStyle == .dark {
            layer.shadowColor = UIColor.darkGray.cgColor
        } else {
            layer.shadowColor = UIColor.black.cgColor
        }
    }
    
    // MARK: Interaction
    
    @objc private func hoverRecognized(_ recognizer: UIHoverGestureRecognizer) {
        switch recognizer.state {
        case .began, .changed:
            hoverGestureAnimator = UIViewPropertyAnimator(duration: 0.2, curve: .easeInOut, animations: {
                self.transform = CGAffineTransform(scaleX: 1.05, y: 1.05)
            })
            hoverGestureAnimator!.startAnimation()
        case .ended:
            hoverGestureAnimator?.stopAnimation(true)
            hoverGestureAnimator?.addAnimations {
                self.transform = .identity
            }
            hoverGestureAnimator?.startAnimation()
        default:
            break
        }
    }
    
}

extension TrendingLinkCardCollectionViewCell {
    enum VerticalSize {
        case regular, compact
    }
}
