<commit_before>//
//  FetchedArrayViewModel.Swift
//  Pods
//
//  Created by <NAME> on 3/2/16.
//  Copyright © 2016 ReactiveSprint. All rights reserved.
//

import ReactiveCocoa
import Result

/// Non-generic FetchedArrayViewModelType used with Cocoa.
public protocol _FetchedArrayViewModelType: _ArrayViewModelType
{
    /// Whether the ViewModel is refreshing.
    var refreshing: AnyProperty<Bool> { get }
    
    /// Whether the ViewModel is fetching next page and is not refreshing.
    var fetchingNextPage: AnyProperty<Bool> { get }
    
    /// Whether the ViewModel has next page.
    var hasNextPage: AnyProperty<Bool> { get }
}

/// ArrayViewModel which its array is lazily fetched, or even paginated.
public protocol FetchedArrayViewModelType: ArrayViewModelType, _FetchedArrayViewModelType
{
    typealias FetchInput
    typealias PaginationType
    typealias FetchError: ViewModelErrorType
    
    /// Next Page
    var nextPage: PaginationType? { get }
    
    /// Action which refreshes ViewModels.
    var refreshAction: Action<FetchInput, [Element], FetchError> { get }
    
    /// Action which fetches ViewModels.
    ///
    /// If `nextPage` is nil, then this action will refresh, else this action should fetch next page.
    var fetchAction: Action<FetchInput, [Element], FetchError> { get }
    
    /// Applies `fetchAction` only if next page is availabe or returns `SignalProducer.empty`
    func fetchIfNeeded(input: FetchInput) -> SignalProducer<[Element], ActionError<FetchError>>
}

public extension FetchedArrayViewModelType
{
    private var willFetchNextPage: Bool {
        return nextPage != nil
    }
    
    /// Applies `fetchAction` only if next page is availabe or returns `SignalProducer.empty`
    @warn_unused_result(message="Did you forget to call `start` on the producer?")
    public func fetchIfNeeded(input: FetchInput) -> SignalProducer<[Element], ActionError<FetchError>>
    {
        if willFetchNextPage && hasNextPage.value
        {
            return fetchAction.apply(input)
        }
        
        return SignalProducer.empty
    }
}

/// An implementation of FetchedArrayViewModelType that fetches ViewModels by calling `fetchClosure.`
public class FetchedArrayViewModel<Element: ViewModelType, PaginationType, FetchError: ViewModelErrorType>: ViewModel, FetchedArrayViewModelType
{
    private let _viewModels: MutableProperty<[Element]> = MutableProperty([])
    public var viewModels: [Element] {
        return _viewModels.value
    }
    
    private lazy var _count: AnyProperty<Int> = AnyProperty(initialValue: 0, producer: self._viewModels.producer.map { $0.count })
    private(set) public lazy var count: AnyProperty<Int> = AnyProperty(self._count)
    
    public let localizedEmptyMessage = MutableProperty<String?>(nil)
    
    private let _refreshing = MutableProperty(false)
    private(set) public lazy var refreshing: AnyProperty<Bool> = AnyProperty(self._refreshing)
    
    private let _fetchingNextPage = MutableProperty(false)
    private(set) public lazy var fetchingNextPage: AnyProperty<Bool> = AnyProperty(self._fetchingNextPage)
    
    private let _hasNextPage = MutableProperty(true)
    private(set) public lazy var hasNextPage: AnyProperty<Bool> = AnyProperty(self._hasNextPage)
    
    private(set) public var nextPage: PaginationType? = nil
    
    public let fetchClosure: PaginationType? -> SignalProducer<([Element], PaginationType?), FetchError>
    private(set) public lazy var refreshAction: Action<(), [Element], FetchError> = self.initRefreshAction()
    private(set) public lazy var fetchAction: Action<(), [Element], FetchError> = self.initFetchAction()
    
    /// Initializes an instance with `fetchClosure`
    ///
    /// - Parameter fetchClosure: A closure which is called each time `refreshAction` or `fetchAction`
    /// are called passing latest PaginationType
    /// and returns a `SignalProducer` which sends an array of `Element` and PaginationType.
    /// If the returned SignalProducer sends nil PaginationType, then no pagination will be handled.
    public init(_ fetchClosure: PaginationType? -> SignalProducer<([Element], PaginationType?), FetchError>)
    {
        self.fetchClosure = fetchClosure
        super.init()
    }
    
    public subscript(index: Int) -> Element {
        return _viewModels.value[index]
    }
    
    /// Initializes refresh action.
    ///
    /// Default implementation initializes an Action that is enabled when the receiver is,<commit_msg>Added cocoa actions in _FetchedArrayViewModel<commit_after>//
//  FetchedArrayViewModel.Swift
//  Pods
//
//  Created by <NAME> on 3/2/16.
//  Copyright © 2016 ReactiveSprint. All rights reserved.
//

import ReactiveCocoa
import Result

/// Non-generic FetchedArrayViewModelType used with Cocoa.
public protocol _FetchedArrayViewModelType: _ArrayViewModelType
{
    /// Whether the ViewModel is refreshing.
    var refreshing: AnyProperty<Bool> { get }
    
    /// Whether the ViewModel is fetching next page and is not refreshing.
    var fetchingNextPage: AnyProperty<Bool> { get }
    
    /// Whether the ViewModel has next page.
    var hasNextPage: AnyProperty<Bool> { get }
    
    var refreshCocoaAction: CocoaAction { get }
    
    var fetchCocoaAction: CocoaAction { get }

    var fetchIfNeededCocoaAction: CocoaAction { get }
}

/// ArrayViewModel which its array is lazily fetched, or even paginated.
public protocol FetchedArrayViewModelType: ArrayViewModelType, _FetchedArrayViewModelType
{
    typealias FetchInput
    typealias PaginationType
    typealias FetchError: ViewModelErrorType
    
    /// Next Page
    var nextPage: PaginationType? { get }
    
    /// Action which refreshes ViewModels.
    var refreshAction: Action<FetchInput, [Element], FetchError> { get }
    
    /// Action which fetches ViewModels.
    ///
    /// If `nextPage` is nil, then this action will refresh, else this action should fetch next page.
    var fetchAction: Action<FetchInput, [Element], FetchError> { get }
    
    /// Applies `fetchAction` only if next page is availabe or returns `SignalProducer.empty`
    var fetchIfNeededAction: Action<FetchInput, [Element], ActionError<FetchError>> { get }
}

public extension FetchedArrayViewModelType
{
    private var willFetchNextPage: Bool {
        return nextPage != nil
    }
    
    public func fetchIfNeeded(input: FetchInput) -> SignalProducer<[Element], ActionError<FetchError>>
    {
        if willFetchNextPage && hasNextPage.value
        {
            return fetchAction.apply(input)
        }
        
        return SignalProducer.empty
    }
    
    public var fetchCocoaAction: CocoaAction { return fetchAction.unsafeCocoaAction }
    
    public var refreshCocoaAction: CocoaAction { return refreshAction.unsafeCocoaAction }
    
    public var fetchIfNeededCocoaAction: CocoaAction { return fetchIfNeededAction.unsafeCocoaAction }
}

/// An implementation of FetchedArrayViewModelType that fetches ViewModels by calling `fetchClosure.`
public class FetchedArrayViewModel<Element: ViewModelType, PaginationType, FetchError: ViewModelErrorType>: ViewModel, FetchedArrayViewModelType
{
    private let _viewModels: MutableProperty<[Element]> = MutableProperty([])
    public var viewModels: [Element] {
        return _viewModels.value
    }
    
    private lazy var _count: AnyProperty<Int> = AnyProperty(initialValue: 0, producer: self._viewModels.producer.map { $0.count })
    private(set) public lazy var count: AnyProperty<Int> = AnyProperty(self._count)
    
    public let localizedEmptyMessage = MutableProperty<String?>(nil)
    
    private let _refreshing = MutableProperty(false)
    private(set) public lazy var refreshing: AnyProperty<Bool> = AnyProperty(self._refreshing)
    
    private let _fetchingNextPage = MutableProperty(false)
    private(set) public lazy var fetchingNextPage: AnyProperty<Bool> = AnyProperty(self._fetchingNextPage)
    
    private let _hasNextPage = MutableProperty(true)
    private(set) public lazy var hasNextPage: AnyProperty<Bool> = AnyProperty(self._hasNextPage)
    
    private(set) public var nextPage: PaginationType? = nil
    
    public let fetchClosure: PaginationType? -> SignalProducer<([Element], PaginationType?), FetchError>
    private(set) public lazy var refreshAction: Action<(), [Element], FetchError> = self.initRefreshAction()
    private(set) public lazy var fetchAction: Action<(), [Element], FetchError> = self.initFetchAction()
    
    private(set) public lazy var fetchIfNeededAction: Action<(), [Element], ActionError<FetchError>> = { _ in
        
        let action = Action<(), [Element], ActionError<FetchError>>(enabledIf: self.enabled) { [unowned self] _ in
            return self.fetchIfNeeded()
        }
        
        action.unsafeCocoaAction = CocoaAction(action, input: ())
        
        return action
    }()
    
    /// Initializes an instance with `fetchClosure`
    ///
    /// - Parameter fetchClosure: A closure which is called each time `refreshAction` or `fetchAction`
    /// are called passing latest PaginationType
    /// and returns a `SignalProducer` which sends an array of `Element` and PaginationType.
    /// If the returned SignalProducer sends nil PaginationType, then no pagination will be handled.
    public init(_ fetchClosure: PaginationType? -> SignalProducer<([Element], PaginationType?), FetchError>)
    {
        self.fetchClosure = fetchClosure
        super.init()
    }
    
    public subscript(index: Int) -> Element {
        return _viewModels.value[index]
    }
    
    /// Initializes refresh action.
    ///
    /// Default implementation initializes an Action that is enabled when the receiver is,
{'fraction_non_alphanumeric': 0.08835630528697799, 'fraction_numerical': 0.002057189878625797, 'mean_word_length': 3.460091743119266, 'pattern_counts': {'":': 0, '<': 51, '<?xml version=': 0, '>': 60, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3418292', 'n_tokens_mistral': 2805, 'n_tokens_neox': 2684, 'n_words': 795}