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

import Combine
import Core
import UIKit

class LocationsListViewController: BaseViewController {
    
    // MARK: Properties
    
    private let viewModel: LocationsListViewModeling
    
    private var cancellables: Set<AnyCancellable> = []
    
    // MARK: Outlets
    
    private lazy var error = ErrorMessageView()
    private lazy var loading = LoadingSpinnerView()
    private lazy var table = {
        let table = UITableView(frame: .zero, style: .plain)
        
        table.dataSource = self
        table.delegate = self
        table.translatesAutoresizingMaskIntoConstraints = false
        
        table.register(LocationViewCell.self, forCellReuseIdentifier: LocationViewCell.identifier)

        return table
    }()
    
    // MARK: Initialisers
    
    init(viewModel: LocationsListViewModeling) {
        self.viewModel = viewModel
        
        super.init()
    }
    
    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
    
    // MARK: UIViewController

    override func viewDidLoad() {
        super.viewDidLoad()

        setupBar()
        setupView()
        bindViewModel()
        
        viewModel.loadLocations()
    }
    
}

// MARK: - UITableViewDataSource

extension LocationsListViewController: UITableViewDataSource {
    
    // MARK: Functions
    
    func numberOfSections(in tableView: UITableView) -> Int {
        viewModel.numberOfSectionsInData
    }
    
    func tableView(
        _ tableView: UITableView,
        numberOfRowsInSection section: Int
    ) -> Int {
        viewModel.numberOfDataItems(in: section)
    }
    
    func tableView(
        _ tableView: UITableView,
        cellForRowAt indexPath: IndexPath
    ) -> UITableViewCell {
        guard let cell = tableView.dequeueReusableCell(
            withIdentifier: LocationViewCell.identifier,
            for: indexPath
        ) as? LocationViewCell else {
            return .init()
        }
        
        let entity = viewModel.dataItem(at: indexPath)
        
        cell.update(
            iconName: entity.source == .remote ? "network" : "house",
            name: entity.name,
            latitude: entity.latitude,
            longitude: entity.longitude
        )

        return cell
    }
    
}

// MARK: - UITableViewDelegate

extension LocationsListViewController: UITableViewDelegate {}

// MARK: - Helpers

private extension LocationsListViewController {
    
    // MARK: Functions
    
    func setupBar() {
        navigationController?.navigationBar.prefersLargeTitles = true
        navigationController?.navigationBar.tintColor = .red
        navigationItem.rightBarButtonItem = .init(
            title: "Add",
            style: .plain,
            target: self,
            action: #selector(addLocationPressed)
        )
        title = "Locations"
    }
    
    func setupView() {
        view.addSubview(table)
        view.addSubview(error)
        view.addSubview(loading)

        error.onRetry = {
            self.viewModel.loadLocations()
        }

        NSLayoutConstraint.activate([
            error.widthAnchor.constraint(equalToConstant: 300),
            view.centerXAnchor.constraint(equalTo: error.centerXAnchor),
            view.centerYAnchor.constraint(equalTo: error.centerYAnchor),
            view.centerXAnchor.constraint(equalTo: loading.centerXAnchor),
            view.centerYAnchor.constraint(equalTo: loading.centerYAnchor),
            view.bottomAnchor.constraint(equalTo: table.bottomAnchor),
            view.leadingAnchor.constraint(equalTo: table.leadingAnchor),
            view.topAnchor.constraint(equalTo: table.topAnchor),
            view.trailingAnchor.constraint(equalTo: table.trailingAnchor),
        ])
    }
    
    func bindViewModel() {
        viewModel
            .viewStatusPublisher
            .receive(on: RunLoop.main)
            .sink { viewStatus in
                self.navigationItem.rightBarButtonItem?.isEnabled = viewStatus == .loaded
                self.error.isHidden = viewStatus != .error
                self.loading.isHidden = viewStatus != .loading
                self.table.isHidden = viewStatus != .loaded

                if viewStatus == .loaded {
                    self.table.reloadData()
                }
            }
            .store(in: &cancellables)
    }
    
    @objc func addLocationPressed() {
        viewModel.openAddLocation()
    }

}
