//
//  SharedSequence+Operators+arity.swift
//  RxCocoa
//
//  Created by Krunoslav Zaher on 10/14/15.
//  Copyright © 2015 Krunoslav Zaher. All rights reserved.
//

import RxSwift

<% for i in 2 ... 8 { %>

// <%= i %>

extension SharedSequence {
    /**
    Merges the specified observable sequences into one observable sequence by using the selector function whenever all of the observable sequences have produced an element at a corresponding index.

    - parameter resultSelector: Function to invoke for each series of elements at corresponding indexes in the sources.
    - returns: An observable sequence containing the result of combining elements of the sources using the specified result selector function.
    */
    public static func zip<<%= (Array(1...i).map { "O\($0): SharedSequenceConvertibleType" }).joined(separator: ", ") %>>
        (<%= (Array(1...i).map { "_ source\($0): O\($0)" }).joined(separator: ", ") %>, resultSelector: @escaping (<%= (Array(1...i).map { "O\($0).E" }).joined(separator: ", ") %>) throws -> E)
        -> SharedSequence<O1.SharingStrategy, E> where <%= (Array(1...i).map { "SharingStrategy == O\($0).SharingStrategy" }).joined(separator: ",\n            ") %> {
        let source = Observable.zip(
            <%= (Array(1...i).map { "source\($0).asSharedSequence().asObservable()" }).joined(separator: ", ") %>,
            resultSelector: resultSelector
        )

        return SharedSequence<SharingStrategy, E>(source)
    }
}

extension SharedSequenceConvertibleType where E == Any {
    /**
    Merges the specified observable sequences into one observable sequence of element tuples whenever all of the observable sequences have produced an element at a corresponding index.

    - returns: An observable sequence containing the result of combining elements of the sources.
    */
    public static func zip<<%= (Array(1...i).map { "O\($0): SharedSequenceConvertibleType" }).joined(separator: ", ") %>>
        (<%= (Array(1...i).map { "_ source\($0): O\($0)" }).joined(separator: ", ") %>)
        -> SharedSequence<O1.SharingStrategy, (<%= (Array(1...i).map { "O\($0).E" }).joined(separator: ", ") %>)> where <%= (Array(1...i).map { "SharingStrategy == O\($0).SharingStrategy" }).joined(separator: ",\n            ") %> {
        let source = Observable.zip(
            <%= (Array(1...i).map { "source\($0).asSharedSequence().asObservable()" }).joined(separator: ", ") %>
        )

        return SharedSequence<SharingStrategy, (<%= (Array(1...i).map { "O\($0).E" }).joined(separator: ", ") %>)>(source)
    }
}

extension SharedSequence {
    /**
    Merges the specified observable sequences into one observable sequence by using the selector function whenever any of the observable sequences produces an element.

    - parameter resultSelector: Function to invoke whenever any of the sources produces an element.
    - returns: An observable sequence containing the result of combining elements of the sources using the specified result selector function.
    */
    public static func combineLatest<<%= (Array(1...i).map { "O\($0): SharedSequenceConvertibleType" }).joined(separator: ", ") %>>
        (<%= (Array(1...i).map { "_ source\($0): O\($0)" }).joined(separator: ", ") %>, resultSelector: @escaping (<%= (Array(1...i).map { "O\($0).E" }).joined(separator: ", ") %>) throws -> E)
        -> SharedSequence<SharingStrategy, E> where <%= (Array(1...i).map { "SharingStrategy == O\($0).SharingStrategy" }).joined(separator: ",\n            ") %> {
        let source = Observable.combineLatest(
                <%= (Array(1...i).map { "source\($0).asSharedSequence().asObservable()" }).joined(separator: ", ") %>,
                resultSelector: resultSelector
            )

        return SharedSequence<O1.SharingStrategy, E>(source)
    }
}

extension SharedSequenceConvertibleType where E == Any {
    /**
    Merges the specified observable sequences into one observable sequence of element tuples whenever any of the observable sequences produces an element.

    - returns: An observable sequence containing the result of combining elements of the sources.
    */
    public static func combineLatest<<%= (Array(1...i).map { "O\($0): SharedSequenceConvertibleType" }).joined(separator: ", ") %>>
        (<%= (Array(1...i).map { "_ source\($0): O\($0)" }).joined(separator: ", ") %>)
        -> SharedSequence<SharingStrategy, (<%= (Array(1...i).map { "O\($0).E" }).joined(separator: ", ") %>)> where <%= (Array(1...i).map { "SharingStrategy == O\($0).SharingStrategy" }).joined(separator: ",\n            ") %> {
        let source = Observable.combineLatest(
                <%= (Array(1...i).map { "source\($0).asSharedSequence().asObservable()" }).joined(separator: ", ") %>
            )

        return SharedSequence<O1.SharingStrategy, (<%= (Array(1...i).map { "O\($0).E" }).joined(separator: ", ") %>)>(source)
    }
}

<% } %>
