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

namespace EvoBoat.EvoAlg.WWO
{
    public class Num_VarWWOAlg<S> : VarWWOAlg<NumOptProblem<S>, S, Vector, double>
        where S : VecSolution<Vector, double>, new()
    {
        protected Vector sranges;

        protected double beta;
        public double BetaMax { get; set; }
        public double BetaMin { get; set; }

        public Num_VarWWOAlg() : base()
        {
            gRand = new GaussRandom((int)DateTime.Now.Ticks);
        }

        public Num_VarWWOAlg(NumOptProblem<S> problem, int seed = 0) : base(problem, seed)
        {
            gRand = new GaussRandom(seed);
        }

        public override void SetFactory()
        {
            if (Problem == null)
                throw new ArgumentNullException("Please assign the problem instance before set the factory");
            Factory = new VectorSolutionFactory<NumOptProblem<S>, S>(Problem);
        }

        public override void SetParameters()
        {
            base.SetParameters();
            BetaMax = 0.25;
            BetaMin = 0.001;
        }

        public override void InitPop()
        {
            base.InitPop();
            beta = BetaMax;
            sranges = beta * Problem.Ranges;
        }

        public override void Calculate()
        {
            base.Calculate();
            if (nfes > 0)
                beta = BetaMax - (BetaMax - BetaMin) * nfe / nfes;
            else if (iters > 0)
                beta = BetaMax - (BetaMax - BetaMin) * iter / iters;
            sranges = beta * Problem.Ranges;
        }

        public override double MoveP(S sol, int index, int d)
        {
            return Num_WWOAlg<S>.MovePFunc(this, sol, index, d);
        }

        public override double MoveB(S sol, int index, int d)
        {
            return Num_WWOAlg<S>.MoveBFunc(this, sol, index, d, sranges[d]);
        }

        public override S Reflect(S sol, int index)
        {
            return Num_WWOAlg<S>.ReflectFunc(this, sol, index, best);
        }
    }
}
