//
//  ProfileFieldCollectionViewCell.swift
//  Mastodon
//
//  Created by MainasuK Cirno on 2021-5-25.
//

import os.log
import UIKit
import Combine
import MetaTextKit
import MastodonAsset
import MastodonLocalization

protocol ProfileFieldCollectionViewCellDelegate: AnyObject {
    func profileFieldCollectionViewCell(_ cell: ProfileFieldCollectionViewCell, metaLabel: MetaLabel, didSelectMeta meta: Meta)
}

final class ProfileFieldCollectionViewCell: UICollectionViewCell {
    
    var disposeBag = Set<AnyCancellable>()
    
    weak var delegate: ProfileFieldCollectionViewCellDelegate?

    // for custom emoji display
    let keyMetaLabel = MetaLabel(style: .profileFieldName)
    let valueMetaLabel = MetaLabel(style: .profileFieldValue)
    
    let checkmark = UIImageView(image: Asset.Editing.checkmark.image.withRenderingMode(.alwaysTemplate))
    var checkmarkPopoverString: String? = nil;
    let tapGesture = UITapGestureRecognizer();
    private var _editMenuInteraction: Any? = nil
    @available(iOS 16, *)
    fileprivate var editMenuInteraction: UIEditMenuInteraction {
        _editMenuInteraction = _editMenuInteraction ?? UIEditMenuInteraction(delegate: self)
        return _editMenuInteraction as! UIEditMenuInteraction
    }
    
    override func prepareForReuse() {
        super.prepareForReuse()
        
        disposeBag.removeAll()
    }

    override init(frame: CGRect) {
        super.init(frame: frame)
        _init()
    }
    
    required init?(coder: NSCoder) {
        super.init(coder: coder)
        _init()
    }
    
}

extension ProfileFieldCollectionViewCell {
    
    private func _init() {
        // Setup colors
        checkmark.tintColor = Asset.Scene.Profile.About.bioAboutFieldVerifiedText.color;
        
        // Setup gestures
        tapGesture.addTarget(self, action: #selector(ProfileFieldCollectionViewCell.didTapCheckmark(_:)))
        checkmark.addGestureRecognizer(tapGesture)
        checkmark.isUserInteractionEnabled = true
        if #available(iOS 16, *) {
            checkmark.addInteraction(editMenuInteraction)
        }
        
        // Setup Accessibility
        checkmark.isAccessibilityElement = true
        checkmark.accessibilityTraits = .none
        keyMetaLabel.accessibilityTraits = .none

        // containerStackView: V - [ metaContainer | plainContainer ]
        let containerStackView = UIStackView()
        containerStackView.axis = .vertical
        
        contentView.preservesSuperviewLayoutMargins = true
        containerStackView.preservesSuperviewLayoutMargins = true
        containerStackView.isLayoutMarginsRelativeArrangement = true
        containerStackView.translatesAutoresizingMaskIntoConstraints = false
        addSubview(containerStackView)
        NSLayoutConstraint.activate([
            containerStackView.topAnchor.constraint(equalTo: topAnchor, constant: 11),
            containerStackView.leadingAnchor.constraint(equalTo: leadingAnchor),
            containerStackView.trailingAnchor.constraint(equalTo: trailingAnchor),
            bottomAnchor.constraint(equalTo: containerStackView.bottomAnchor, constant: 11),
        ])
        
        // metaContainer: V - [ keyMetaLabel | valueContainer ]
        let metaContainer = UIStackView()
        metaContainer.axis = .vertical
        metaContainer.spacing = 2
        containerStackView.addArrangedSubview(metaContainer)
        
        // valueContainer: H - [ valueMetaLabel | checkmark ]
        let valueContainer = UIStackView()
        valueContainer.axis = .horizontal
        valueContainer.spacing = 2
        
        metaContainer.addArrangedSubview(keyMetaLabel)
        valueContainer.addArrangedSubview(valueMetaLabel)
        valueContainer.addArrangedSubview(checkmark)
        metaContainer.addArrangedSubview(valueContainer)
        
        keyMetaLabel.linkDelegate = self
        valueMetaLabel.linkDelegate = self

        isAccessibilityElement = true
    }
    
    @objc public func didTapCheckmark(_ recognizer: UITapGestureRecognizer) {
        if #available(iOS 16, *) {
            editMenuInteraction.presentEditMenu(with: UIEditMenuConfiguration(identifier: nil, sourcePoint: recognizer.location(in: checkmark)))
        } else {
            guard let editMenuLabel = checkmarkPopoverString else { return }

            self.isUserInteractionEnabled = true
            self.becomeFirstResponder()

            UIMenuController.shared.menuItems = [
                UIMenuItem(
                    title: editMenuLabel,
                    action: #selector(dismissVerifiedMenu)
                )
            ]
            UIMenuController.shared.showMenu(from: checkmark, rect: checkmark.bounds)
        }
    }

    private var valueMetas: [(title: String, Meta)] {
        var result: [(title: String, Meta)] = []
        valueMetaLabel.textStorage.enumerateAttribute(NSAttributedString.Key("MetaAttributeKey.meta"), in: NSMakeRange(0, valueMetaLabel.textStorage.length)) { value, range, _ in
            if let value = value as? Meta {
                result.append((valueMetaLabel.textStorage.string.substring(with: range), value))
            }
        }
        return result
    }

    override func accessibilityActivate() -> Bool {
        if let (_, meta) = valueMetas.first {
            delegate?.profileFieldCollectionViewCell(self, metaLabel: valueMetaLabel, didSelectMeta: meta)
            return true
        }
        return false
    }

    override var accessibilityCustomActions: [UIAccessibilityCustomAction]? {
        get {
            let valueMetas = valueMetas
            if valueMetas.count < 2 { return nil }
            return valueMetas.compactMap { title, meta in
                guard let name = meta.accessibilityLabel else { return nil }
                return UIAccessibilityCustomAction(name: name) { [weak self] _ in
                    guard let self, let delegate = self.delegate else { return false }
                    delegate.profileFieldCollectionViewCell(self, metaLabel: self.valueMetaLabel, didSelectMeta: meta)
                    return true
                }
            }
        }
        set {}
    }
}

// UIMenuController boilerplate
@available(iOS, deprecated: 16, message: "Can be removed when target version is >=16 -- boilerplate to maintain compatibility with UIMenuController")
extension ProfileFieldCollectionViewCell {
    override var canBecomeFirstResponder: Bool { true }
    
    override func canPerformAction(_ action: Selector, withSender sender: Any?) -> Bool {
        if action == #selector(dismissVerifiedMenu) {
            return true
        }
        
        return super.canPerformAction(action, withSender: sender)
    }
    
    @objc public func dismissVerifiedMenu() {
        UIMenuController.shared.hideMenu()
    }
}

// MARK: - MetaLabelDelegate
extension ProfileFieldCollectionViewCell: MetaLabelDelegate {
    func metaLabel(_ metaLabel: MetaLabel, didSelectMeta meta: Meta) {
        os_log(.info, log: .debug, "%{public}s[%{public}ld], %{public}s", ((#file as NSString).lastPathComponent), #line, #function)
        delegate?.profileFieldCollectionViewCell(self, metaLabel: metaLabel, didSelectMeta: meta)
    }
}

// MARK: UIEditMenuInteractionDelegate
@available(iOS 16.0, *)
extension ProfileFieldCollectionViewCell: UIEditMenuInteractionDelegate {
    func editMenuInteraction(_ interaction: UIEditMenuInteraction, menuFor configuration: UIEditMenuConfiguration, suggestedActions: [UIMenuElement]) -> UIMenu? {
        guard let editMenuLabel = checkmarkPopoverString else { return UIMenu(children: []) }
        return UIMenu(children: [UIAction(title: editMenuLabel) { _ in return }])
    }
    
    func editMenuInteraction(_ interaction: UIEditMenuInteraction, targetRectFor configuration: UIEditMenuConfiguration) -> CGRect {
        return checkmark.frame
    }
}
