//
//  LocationsListViewModel.swift
//  Locations
//
//  Created by Javier Cicchelli on 11/04/2023.
//  Copyright © 2023 Röck+Cöde. All rights reserved.
//

import CoreData
import Combine
import Dependency
import Foundation
import Persistence

class LocationsListViewModel: ObservableObject {
    
    // MARK: Dependencies
    
    @Dependency(\.persistence) private var persistence

    // MARK: Properties
    
    weak var coordinator: LocationsListCoordination?
    
    @Published private var viewStatus: LocationsListViewStatus = .initialised
    
    private lazy var fetchedResultsController = NSFetchedResultsController(
        fetchRequest: NSFetchRequest<Location>.allLocations(),
        managedObjectContext: persistence.container.viewContext,
        sectionNameKeyPath: nil,
        cacheName: nil
    )
    
    private let loadRemoteLocations = LoadRemoteLocationsUseCase()
    
    // MARK: Initialisers
    
    init(coordinator: LocationsListCoordination) {
        self.coordinator = coordinator
    }

}

// MARK: - LocationsListViewModeling

extension LocationsListViewModel: LocationsListViewModeling {
    
    // MARK: Properties
    
    var viewStatusPublisher: Published<LocationsListViewStatus>.Publisher { $viewStatus }
    var numberOfSectionsInData: Int { fetchedResultsController.sections?.count ?? 0 }
    
    // MARK: Functions
    
    func openAddLocation() {
        coordinator?.openAddLocation()
    }
    
    func loadLocations() {
        Task {
            do {
                viewStatus = .loading
                
                try await loadRemoteLocations()
                
                try fetchedResultsController.performFetch()

                viewStatus = .loaded
            } catch {
                viewStatus = .error
            }
        }
    }
    
    func numberOfDataItems(in section: Int) -> Int {
        guard
            let sections = fetchedResultsController.sections,
            sections.endIndex > section
        else {
            return 0
        }

        return sections[section].numberOfObjects
    }
    
    func dataItem(at indexPath: IndexPath) -> Location {
        fetchedResultsController.object(at: indexPath)
    }
    
}

// MARK: - Enumerations

enum LocationsListViewStatus {
    case initialised
    case loading
    case loaded
    case error
}
