//
//  ReportSection.swift
//  Mastodon
//
//  Created by ihugo on 2021/4/20.
//

import Combine
import CoreData
import CoreDataStack
import Foundation
import MastodonSDK
import UIKit
import os.log
import MastodonAsset
import MastodonLocalization

enum ReportSection: Equatable, Hashable {
    case main
}

extension ReportSection {
    
    struct Configuration {
    }
    
    static func diffableDataSource(
        tableView: UITableView,
        context: AppContext,
        configuration: Configuration
    ) -> UITableViewDiffableDataSource<ReportSection, ReportItem> {
        
        tableView.register(ReportHeadlineTableViewCell.self, forCellReuseIdentifier: String(describing: ReportHeadlineTableViewCell.self))
        tableView.register(ReportStatusTableViewCell.self, forCellReuseIdentifier: String(describing: ReportStatusTableViewCell.self))
        tableView.register(ReportCommentTableViewCell.self, forCellReuseIdentifier: String(describing: ReportCommentTableViewCell.self))
        tableView.register(ReportResultActionTableViewCell.self, forCellReuseIdentifier: String(describing: ReportResultActionTableViewCell.self))
        tableView.register(TimelineBottomLoaderTableViewCell.self, forCellReuseIdentifier: String(describing: TimelineBottomLoaderTableViewCell.self))

        return UITableViewDiffableDataSource(tableView: tableView) { tableView, indexPath, item -> UITableViewCell? in
            switch item {
            case .header(let headerContext):
                let cell = tableView.dequeueReusableCell(withIdentifier: String(describing: ReportHeadlineTableViewCell.self), for: indexPath) as! ReportHeadlineTableViewCell
                cell.primaryLabel.text = headerContext.primaryLabelText
                cell.secondaryLabel.text = headerContext.secondaryLabelText
                return cell
            case .status(let record):
                let cell = tableView.dequeueReusableCell(withIdentifier: String(describing: ReportStatusTableViewCell.self), for: indexPath) as! ReportStatusTableViewCell
                context.managedObjectContext.performAndWait {
                    guard let status = record.object(in: context.managedObjectContext) else { return }
                    configure(
                        context: context,
                        tableView: tableView,
                        cell: cell,
                        viewModel: .init(value: status),
                        configuration: configuration
                    )
                }
                return cell
            case .comment(let commentContext):
                let cell = tableView.dequeueReusableCell(withIdentifier: String(describing: ReportCommentTableViewCell.self), for: indexPath) as! ReportCommentTableViewCell
                cell.commentTextView.text = commentContext.comment
                NotificationCenter.default.publisher(for: UITextView.textDidChangeNotification, object: cell.commentTextView)
                    .receive(on: DispatchQueue.main)
                    .sink { [weak cell] notification in
                        guard let cell = cell else { return }
                        commentContext.comment = cell.commentTextView.text
                        
                        // fix shadow get animation issue when cell height changes
                        UIView.performWithoutAnimation {
                            tableView.beginUpdates()
                            tableView.endUpdates()
                        }
                    }
                    .store(in: &cell.disposeBag)
                return cell
            case .result(let record):
                let cell = tableView.dequeueReusableCell(withIdentifier: String(describing: ReportResultActionTableViewCell.self), for: indexPath) as! ReportResultActionTableViewCell
                context.managedObjectContext.performAndWait {
                    guard let user = record.object(in: context.managedObjectContext) else { return }
                    cell.avatarImageView.configure(configuration: .init(url: user.avatarImageURL()))
                }
                return cell
            case .bottomLoader:
                let cell = tableView.dequeueReusableCell(withIdentifier: String(describing: TimelineBottomLoaderTableViewCell.self), for: indexPath) as! TimelineBottomLoaderTableViewCell
                cell.activityIndicatorView.startAnimating()
                return cell
            }
        }
    }
}

extension ReportSection {
    
    static func configure(
        context: AppContext,
        tableView: UITableView,
        cell: ReportStatusTableViewCell,
        viewModel: ReportStatusTableViewCell.ViewModel,
        configuration: Configuration
    ) {
        StatusSection.setupStatusPollDataSource(
            context: context,
            statusView: cell.statusView
        )
        
        context.authenticationService.activeMastodonAuthenticationBox
            .map { $0 as UserIdentifier? }
            .assign(to: \.userIdentifier, on: cell.statusView.viewModel)
            .store(in: &cell.disposeBag)
        
        cell.configure(
            tableView: tableView,
            viewModel: viewModel
        )
    }
    
}
