//
//  InstanceTimelineViewController.swift
//  Tusker
//
//  Created by Shadowfacts on 12/19/19.
//  Copyright © 2019 Shadowfacts. All rights reserved.
//

import UIKit
import Pachyderm

protocol InstanceTimelineViewControllerDelegate: AnyObject {
    func didSaveInstance(url: URL)
    func didUnsaveInstance(url: URL)
}

class InstanceTimelineViewController: TimelineViewController {
    
    weak var instanceTimelineDelegate: InstanceTimelineViewControllerDelegate?

    weak var parentMastodonController: MastodonController?
    
    let instanceURL: URL
    let instanceMastodonController: MastodonController
    
    private var toggleSaveButton: UIBarButtonItem!
    
    private var isInstanceSaved: Bool {
        let req = SavedInstance.fetchRequest(url: instanceURL, account: parentMastodonController!.accountInfo!)
        return parentMastodonController!.persistentContainer.viewContext.objectExists(for: req)
    }
    private var toggleSaveButtonTitle: String {
        if isInstanceSaved {
            return NSLocalizedString("Unsave", comment: "unsave instance button")
        } else {
            return NSLocalizedString("Save", comment: "save instance button")
        }
    }
    
    var browsingEnabled = true
    
    init(for url: URL, parentMastodonController: MastodonController) {
        self.parentMastodonController = parentMastodonController
        
        self.instanceURL = url

        // the timeline VC only stores a weak reference to it, so we need to store a strong reference to make sure it's not released immediately
        instanceMastodonController = MastodonController(instanceURL: url, transient: true)

        super.init(for: .public(local: true), mastodonController: instanceMastodonController)
        
        title = url.host!
        userActivity = nil // todo: activity for instance-specific timelines
    }
    
    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        toggleSaveButton = UIBarButtonItem(title: toggleSaveButtonTitle, style: .plain, target: self, action: #selector(toggleSaveButtonPressed))
        navigationItem.rightBarButtonItem = toggleSaveButton
        
        NotificationCenter.default.addObserver(self, selector: #selector(savedInstancesChanged), name: .savedInstancesChanged, object: nil)
    }
    
    @objc func savedInstancesChanged() {
        toggleSaveButton.title = toggleSaveButtonTitle
    }
    
    override func configureStatusCell(_ cell: TimelineStatusCollectionViewCell, id: String, state: CollapseState, filterResult: Filterer.Result, precomputedContent: NSAttributedString?) {
        cell.delegate = browsingEnabled ? self : nil
        cell.overrideMastodonController = mastodonController
        cell.updateUI(statusID: id, state: state, filterResult: filterResult, precomputedContent: precomputedContent)
    }
    
    override func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
        guard browsingEnabled else { return }
        super.collectionView(collectionView, didSelectItemAt: indexPath)
    }
    
    // MARK: Timeline
    
    override func handleLoadAllError(_ error: Swift.Error) async {
        guard let error = error as? Client.Error else {
            await super.handleLoadAllError(error)
            return
        }
        let code: Int
        switch error.type {
        case .mastodonError(let c, _), .unexpectedStatus(let c):
            code = c
        default:
            await super.handleLoadAllError(error)
            return
        }
        guard code == 422 || code == 401 else {
            await super.handleLoadAllError(error)
            return
        }
        
        collectionView.isHidden = true
        view.backgroundColor = .appBackground
        
        let image = UIImageView(image: UIImage(systemName: "lock.fill"))
        image.tintColor = .secondaryLabel
        image.contentMode = .scaleAspectFit
        
        let title = UILabel()
        title.textColor = .secondaryLabel
        title.font = .preferredFont(forTextStyle: .title1).withTraits(.traitBold)!
        title.adjustsFontForContentSizeCategory = true
        title.numberOfLines = 0
        title.textAlignment = .center
        title.text = "This instance requires an account to view."
        
        let stack = UIStackView(arrangedSubviews: [
            image,
            title,
        ])
        stack.axis = .vertical
        stack.alignment = .center
        stack.spacing = 8
        stack.isAccessibilityElement = true
        stack.accessibilityLabel = title.text!
        
        stack.translatesAutoresizingMaskIntoConstraints = false
        view.addSubview(stack)
        NSLayoutConstraint.activate([
            image.widthAnchor.constraint(equalToConstant: 64),
            image.heightAnchor.constraint(equalToConstant: 64),
            
            stack.leadingAnchor.constraint(equalToSystemSpacingAfter: view.safeAreaLayoutGuide.leadingAnchor, multiplier: 1),
            view.safeAreaLayoutGuide.trailingAnchor.constraint(equalToSystemSpacingAfter: stack.trailingAnchor, multiplier: 1),
            stack.centerYAnchor.constraint(equalTo: view.safeAreaLayoutGuide.centerYAnchor),
        ])
    }
    
    // MARK: Interaction
    @objc func toggleSaveButtonPressed() {
        let context = parentMastodonController!.persistentContainer.viewContext
        let req = SavedInstance.fetchRequest(url: instanceURL, account: parentMastodonController!.accountInfo!)
        let existing = try? context.fetch(req).first
        if let existing = existing {
            context.delete(existing)
            instanceTimelineDelegate?.didUnsaveInstance(url: instanceURL)
        } else {
            _ = SavedInstance(url: instanceURL, account: parentMastodonController!.accountInfo!, context: context)
            instanceTimelineDelegate?.didSaveInstance(url: instanceURL)
        }
        mastodonController.persistentContainer.save(context: context)
    }

}
