//
//  StatusSwipeActions.swift
//  Tusker
//
//  Created by Shadowfacts on 11/26/22.
//  Copyright © 2022 Shadowfacts. All rights reserved.
//

import UIKit
import Pachyderm
import TuskerPreferences

extension StatusSwipeAction {
    func createAction(status: StatusMO, container: StatusSwipeActionContainer) -> UIContextualAction? {
        switch self {
        case .reply:
            return createReplyAction(status: status, container: container)
        case .favorite:
            return createFavoriteAction(status: status, container: container)
        case .reblog:
            return createReblogAction(status: status, container: container)
        case .share:
            return createShareAction(status: status, container: container)
        case .bookmark:
            return createBookmarkAction(status: status, container: container)
        case .openInSafari:
            return createOpenInSafariAction(status: status, container: container)
        }
    }
}

protocol StatusSwipeActionContainer: UIView {
    var mastodonController: MastodonController! { get }
    var navigationDelegate: any TuskerNavigationDelegate { get }
    var toastableViewController: ToastableViewController? { get }
    
    var canReblog: Bool { get }
    
    // necessary b/c the reblog-handling logic only exists in the cells
    func performReplyAction()
}

private func createReplyAction(status: StatusMO, container: StatusSwipeActionContainer) -> UIContextualAction? {
    guard container.mastodonController.loggedIn else {
        return nil
    }
    let action = UIContextualAction(style: .normal, title: "Reply") { [unowned container] _, _, completion in
        container.performReplyAction()
        completion(true)
    }
    action.image = UIImage(systemName: "arrowshape.turn.up.left.fill")
    action.backgroundColor = container.tintColor
    return action
}

private func createFavoriteAction(status: StatusMO, container: StatusSwipeActionContainer) -> UIContextualAction? {
    guard container.mastodonController.loggedIn else {
        return nil
    }
    let title = status.favourited ? "Unfavorite" : "Favorite"
    let action = UIContextualAction(style: .normal, title: title) { [unowned container] _, _, completion in
        completion(true)
        Task { @MainActor in
            await FavoriteService(status: status, mastodonController: container.mastodonController, presenter: container.navigationDelegate).toggleFavorite()
        }
    }
    action.image = UIImage(systemName: "star.fill")
    action.backgroundColor = status.favourited ? UIColor(displayP3Red: 235/255, green: 77/255, blue: 62/255, alpha: 1) : UIColor(displayP3Red: 1, green: 204/255, blue: 0, alpha: 1)
    return action
}

private func createReblogAction(status: StatusMO, container: StatusSwipeActionContainer) -> UIContextualAction? {
    guard container.mastodonController.loggedIn,
          container.canReblog else {
        return nil
    }
    let title = status.reblogged ? "Unreblog" : "Reblog"
    let action = UIContextualAction(style: .normal, title: title) { [unowned container] _, _, completion in
        completion(true)
        Task { @MainActor in
            await ReblogService(status: status, mastodonController: container.mastodonController, presenter: container.navigationDelegate).toggleReblog()
        }
    }
    action.image = UIImage(systemName: "repeat")
    action.backgroundColor = status.reblogged ? UIColor(displayP3Red: 235/255, green: 77/255, blue: 62/255, alpha: 1) : container.tintColor
    return action
}

private func createShareAction(status: StatusMO, container: StatusSwipeActionContainer) -> UIContextualAction {
    let action = UIContextualAction(style: .normal, title: "Share") { [unowned container] _, _, completion in
        MainActor.runUnsafely {
            container.navigationDelegate.showMoreOptions(forStatus: status.id, source: .view(container))
        }
        completion(true)
    }
    // bold to more closesly match other action symbols
    let config = UIImage.SymbolConfiguration(weight: .bold)
    action.image = UIImage(systemName: "square.and.arrow.up")!.applyingSymbolConfiguration(config)!
    action.backgroundColor = .lightGray
    return action
}

private func createBookmarkAction(status: StatusMO, container: StatusSwipeActionContainer) -> UIContextualAction? {
    guard container.mastodonController.loggedIn else {
        return nil
    }
    let bookmarked = status.bookmarked ?? false
    let title = bookmarked ? "Unbookmark" : "Bookmark"
    let action = UIContextualAction(style: .normal, title: title) { [unowned container] _, _, completion in
        completion(true)
        Task { @MainActor in
            let request = (bookmarked ? Status.unbookmark : Status.bookmark)(status.id)
            do {
                let (status, _) = try await container.mastodonController.run(request)
                container.mastodonController.persistentContainer.addOrUpdate(status: status)
            } catch {
                let config = ToastConfiguration(from: error, with: "Error \(bookmarked ? "Unb" : "B")ookmarking", in: container.navigationDelegate, retryAction: nil)
                container.navigationDelegate.showToast(configuration: config, animated: true)
            }
        }
    }
    action.image = UIImage(systemName: "bookmark.fill")
    action.backgroundColor = .systemRed
    return action
}

private func createOpenInSafariAction(status: StatusMO, container: StatusSwipeActionContainer) -> UIContextualAction {
    let action = UIContextualAction(style: .normal, title: "Open in Safari") { [unowned container] _, _, completion in
        MainActor.runUnsafely {
            container.navigationDelegate.selected(url: status.url!, allowUniversalLinks: false)
        }
        completion(true)
    }
    action.image = UIImage(systemName: "safari")
    action.backgroundColor = container.tintColor
    return action
}
