// Copyright © 2024 Mastodon gGmbH. All rights reserved.

import Foundation
import MastodonSDK

extension MastodonStatusThreadViewModel {
    // Bookmark
    func handleBookmark(_ status: MastodonStatus) {
        ancestors = handleBookmark(status, items: ancestors)
        descendants = handleBookmark(status, items: descendants)
    }
    
    private func handleBookmark(_ status: MastodonStatus, items: [StatusItem]) -> [StatusItem] {
        var newRecords = Array(items)
        guard let index = newRecords.firstIndex(where: { $0.mastodonStatus?.id == status.id }) else {
            return items
        }
        var newRecord = newRecords[index]
        newRecord.mastodonStatus = status
        newRecords[index] = newRecord
        return newRecords
    }
    
    // Favorite
    func handleFavorite(_ status: MastodonStatus) {
        ancestors = handleFavorite(status, items: ancestors)
        descendants = handleFavorite(status, items: descendants)
    }
    
    private func handleFavorite(_ status: MastodonStatus, items: [StatusItem]) -> [StatusItem] {
        var newRecords = Array(items)
        guard let index = newRecords.firstIndex(where: { $0.mastodonStatus?.id == status.id }) else {
            return items
        }
        var newRecord = newRecords[index]
        newRecord.mastodonStatus = status
        newRecords[index] = newRecord
        return newRecords
    }
    
    // Reblog
    func handleReblog(_ status: MastodonStatus, _ isReblogged: Bool) {
        ancestors = handleReblog(status, isReblogged, items: ancestors)
        descendants = handleReblog(status, isReblogged, items: descendants)
    }
    
    private func handleReblog(_ status: MastodonStatus, _ isReblogged: Bool, items: [StatusItem]) -> [StatusItem] {
        var newRecords = Array(items)

        switch isReblogged {
        case true:
            let index: Int
            if let idx = newRecords.firstIndex(where: { $0.mastodonStatus?.reblog?.id == status.reblog?.id }) {
                index = idx
            } else if let idx = newRecords.firstIndex(where: { $0.mastodonStatus?.id == status.reblog?.id }) {
                index = idx
            } else {
                logger.warning("\(Self.entryNotFoundMessage)")
                return newRecords
            }
            var newRecord = newRecords[index]
            newRecord.mastodonStatus = status.inheritSensitivityToggled(from: newRecord.mastodonStatus)
            newRecords[index] = newRecord
        case false:
            let index: Int
            if let idx = newRecords.firstIndex(where: { $0.mastodonStatus?.reblog?.id == status.id }) {
                index = idx
            } else if let idx = newRecords.firstIndex(where: { $0.mastodonStatus?.id == status.id }) {
                index = idx
            } else {
                logger.warning("\(Self.entryNotFoundMessage)")
                return newRecords
            }
            var newRecord = newRecords[index]
            newRecord.mastodonStatus = status.inheritSensitivityToggled(from: newRecord.mastodonStatus)
            newRecords[index] = newRecord
        }

        return newRecords
    }
    
    // Sensitive
    func handleSensitive(_ status: MastodonStatus, _ isVisible: Bool) {
        ancestors = handleSensitive(status, isVisible, ancestors)
        descendants = handleSensitive(status, isVisible, descendants)
    }
    
    private func handleSensitive(_ status: MastodonStatus, _ isVisible: Bool, _ items: [StatusItem]) -> [StatusItem] {
        var newRecords = Array(items)
        guard let index = newRecords.firstIndex(where: { $0.mastodonStatus?.id == status.id }) else {
            return items
        }
        var newRecord = newRecords[index]
        newRecord.mastodonStatus = status
        newRecords[index] = newRecord
        return newRecords
    }
    
    // Edit
    func handleEdit(_ status: MastodonStatus) {
        ancestors = handleEdit(status, items: ancestors)
        descendants = handleEdit(status, items: descendants)
    }
    
    private func handleEdit(_ status: MastodonStatus, items: [StatusItem]) -> [StatusItem] {
        var newRecords = Array(items)
        guard let index = newRecords.firstIndex(where: { $0.mastodonStatus?.id == status.id }) else {
            return items
        }
        var newRecord = newRecords[index]
        newRecord.mastodonStatus = status
        newRecords[index] = newRecord
        return newRecords
    }
    
    // Delete
    func handleDelete(_ status: MastodonStatus) {
        ancestors = handleDelete(status, ancestors)
        descendants = handleDelete(status, descendants)
    }
    
    private func handleDelete(_ status: MastodonStatus, _ items: [StatusItem]) -> [StatusItem] {
        var newRecords = Array(items)
        newRecords.removeAll(where: { $0.mastodonStatus?.id == status.id })
        return newRecords
    }
}


private extension StatusItem {
    var mastodonStatus: MastodonStatus? {
        get {
            switch self {
            case .feed(let record):
                return record.status
            case .feedLoader(let record):
                return record.status
            case .status(let record):
                return record
            case .thread(let thread):
                return thread.record
            case .topLoader, .bottomLoader:
                return nil
            }
        }
        
        set {
            guard let status = newValue else { return }
            switch self {
            case .feed(let record):
                self = .feed(record: .fromStatus(status, kind: record.kind))
            case .feedLoader(let record):
                self = .feedLoader(record: .fromStatus(status, kind: record.kind))
            case .status:
                self = .status(record: status)
            case let .thread(thread):
                var newThread = thread
                newThread.record = status
                self = .thread(newThread)
            case .topLoader, .bottomLoader:
                break
            }
        }
    }
}
