﻿using System;
using System.Collections.Generic;
using System.Linq;
using SolidModel.Functions;
using SolidModel.Network;

namespace SolidModel.Builder
{
    public class DelayedSimpleHiddenLayerBuilder<TData, TRecipient> : IBuilder<IEnumerable<IObserver<TData>>>
        where TRecipient : IObserver<TData>
    {
        private int numberOfNeurons;

        private IBuilder<IEnumerable<TRecipient>> nextLayerBuilder;

        private IBuilder<ITransformingFunction<IEnumerable<TData>, TData>> functionSource;

        public int NumberOfNeurons
        {
            get
            {
                return this.numberOfNeurons;
            }
            set
            {
                if (value < 1)
                {
                    throw new ArgumentException("The number of neurons cannot be less than one.");
                }
                this.numberOfNeurons = value;
            }
        }

        public IBuilder<ITransformingFunction<IEnumerable<TData>, TData>> FunctionSource
        {
            get
            {
                return this.functionSource;
            }
            set
            {
                this.functionSource = value;
            }
        }

        public IBuilder<IEnumerable<TRecipient>> NextLayerBuilder
        {
            get
            {
                return this.nextLayerBuilder;
            }
            set
            {
                this.nextLayerBuilder = value;
            }
        }

        public IEnumerable<IObserver<TData>> Build()
        {
            var nextLayer = this.nextLayerBuilder.Build().OfType<IObserver<TData>>();
            var wrappedLayer = new OneToOneBufferingDecorator<TData>(new CompositeObserver<TData>(nextLayer), numberOfNeurons);
            for (int index = 0; index < numberOfNeurons; index++)
            {
                yield return new DelayedActivationNeuron<TData, TData>(this.functionSource.Build(), wrappedLayer);
            }
        }
    }
}
