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

namespace EvoBoat.EvoAlg
{
    /// <summary>
    /// specification of a solution to a general problem
    /// </summary>
    /// <typeparam name="R">solution structure</typeparam>
    public interface ISolution<R> : IComparable<ISolution<R>>
    {
        R Content { get; set; } //解的内容
        double Fit { get; set; } //解的适应度值
    }

    /// <summary>
    /// solution with a vector of elements with type e
    /// </summary>
    public class VecSolution<R, e> : ISolution<R>, ICloneable<VecSolution<R, e>>
        where R : IVector<e>, ICloneable<R>
    {
        public double Fit { get; set; }

        public R Content { get; set; }

        public VecSolution()
        { }
        
        public VecSolution(R content)
        {
            this.Content = content;
        }

        public virtual VecSolution<R, e> Clone()
        {
            VecSolution<R, e> sol = new VecSolution<R, e>(this.Content.Clone());
            sol.Fit = this.Fit;
            return sol;
        }

        public int CompareTo(VecSolution<R, e> sol)
        {
            return this.Fit.CompareTo(sol.Fit);
        }

        int IComparable<ISolution<R>>.CompareTo(ISolution<R> sol)
        {
            return this.Fit.CompareTo(sol.Fit);
        }

        public override bool Equals(object obj)
        {
            if (Object.ReferenceEquals(this, obj))
                return true;
            VecSolution<R, e> sol = obj as VecSolution<R, e>;
            if (sol == null)
                return false;
            return this.Content.Equals(sol.Content);
        }

        public override int GetHashCode()
        {
            return Content.GetHashCode();
        }

        public override string ToString()
        {
            StringBuilder sb = new StringBuilder(Content.ToString());
            sb[sb.Length - 1] = '(';
            sb.Append(string.Format("{0:F3}",this.Fit));
            sb.Append(')');
            return sb.ToString();
        }
    }
}
