using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace EvoBoat.EvoAlg
{
    public abstract class SolutionFactory<P, S, R>
        where P : IProblem<S, R>
        where S : class, ISolution<R>, new()
    {
        public virtual P Problem { get; set; }

        public virtual Random Rand { get; set; }

        public SolutionFactory(P problem, int seed = 0)
        {
            this.Problem = problem;
            if (seed == 0)
                Rand = new Random((int)DateTime.Now.Ticks);
            else
                Rand = new Random(seed);
        }

        public abstract S CreateEmpty();
        public abstract S CreateRandom();

        public S[] CreatePop(int np)
        {
            S[] pop = new S[np];
            for (int i = 0; i < np; i++)
                pop[i] = this.CreateRandom();
            return pop;
        }
    }

    public class VectorSolutionFactory<P, S> : SolutionFactory<P, S, Vector>
        where P : NumOptProblem<S>
        where S : VecSolution<Vector, double>, new()
    {
        public VectorSolutionFactory(P problem, int seed = 0) : base(problem, seed)
        { }

        public override S CreateEmpty()
        {
            return new S() { Content = new Vector(new double[Problem.Dimension]) };
        }

        public override S CreateRandom()
        {
            double[] values = new double[Problem.Dimension];
            for (int j = 0; j < Problem.Dimension; j++)
                values[j] = Problem.Lowers[j] + Rand.NextDouble() * (Problem.Uppers[j] - Problem.Lowers[j]);
            return new S() { Content = new Vector(values) };
        }
    }    
}
