<#@ template debug="false" hostspecific="false" language="C#" #>
<#@ assembly name="System.Core" #>
<#@ import namespace="System.Linq" #>
<#@ import namespace="System.Text" #>
<#@ import namespace="System.Collections.Generic" #>
<#@ output extension=".cs" #>
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the Apache 2.0 License.
// See the LICENSE file in the project root for more information. 

using System.Reactive.Disposables;

namespace System.Reactive.Linq.ObservableImpl
{
    #region [3,16]-ary

    /* The following code is generated by a T4 template. */

    #region CombineLatest auto-generated code (<#=DateTime.Now.ToString()#>)

<#
for (var i = 3; i <= 16; i++)
{
    var ts = string.Join(", ", Enumerable.Range(1, i).Select(j => "T" + j));
    var os = string.Join(", ", Enumerable.Range(1, i).Select(j => "IObservable<T" + j + "> source" + j));
    var vs = string.Join(", ", Enumerable.Range(1, i).Select(j => "_observer" + j + ".Value"));
    var ss = string.Join(", ", Enumerable.Range(1, i).Select(j => "_source" + j));
#>
    internal sealed class CombineLatest<<#=ts#>, TResult> : Producer<TResult, CombineLatest<<#=ts#>, TResult>._>
    {
<#
for (var j = 1; j <= i; j++)
{
#>
        private readonly IObservable<T<#=j#>> _source<#=j#>;
<#
}
#>
        private readonly Func<<#=ts#>, TResult> _resultSelector;

        public CombineLatest(<#=os#>, Func<<#=ts#>, TResult> resultSelector)
        {
<#
for (var j = 1; j <= i; j++)
{
#>
            _source<#=j#> = source<#=j#>;
<#
}
#>
            _resultSelector = resultSelector;
        }

        protected override _ CreateSink(IObserver<TResult> observer) => new _(_resultSelector, observer);

        protected override void Run(_ sink) => sink.Run(<#=ss#>);

        internal sealed class _ : CombineLatestSink<TResult>
        {
            private readonly Func<<#=ts#>, TResult> _resultSelector;

            public _(Func<<#=ts#>, TResult> resultSelector, IObserver<TResult> observer)
                : base(<#=i#>, observer)
            {
                _resultSelector = resultSelector;
            }

<#
for (var j = 1; j <= i; j++)
{
#>
            private CombineLatestObserver<T<#=j#>> _observer<#=j#>;
<#
}
#>

            public void Run(<#=os#>)
            {
                var subscriptions = new IDisposable[<#=i#>];

<#
for (var j = 1; j <= i; j++)
{
#>
                subscriptions[<#=j - 1#>] = _observer<#=j#> = new CombineLatestObserver<T<#=j#>>(_gate, this, <#=j - 1#>);
<#
}
#>

<#
for (var j = 1; j <= i; j++)
{
#>
                _observer<#=j#>.SetResource(source<#=j#>.SubscribeSafe(_observer<#=j#>));
<#
}
#>

                SetUpstream(StableCompositeDisposable.CreateTrusted(subscriptions));
            }

            protected override TResult GetResult() => _resultSelector(<#=vs#>);
        }
    }

<#
}
#>

    #endregion

    #endregion
}
