using System;
using LabelerCore.Model.Math;

namespace LabelerCore.Model.Transformers
{
    public class MinMaxScaler: ITransformer
    {
        protected double[] _min; //length - number of features
        protected double[] _max; //length - number of features
        public readonly double Min;
        public readonly double Max;

        protected void _CheckFitness()
        {
            if (_min == null && _max == null)
            {
                throw new NullReferenceException("MinMaxScaler is not fitted yet");
            }
        }

        public MinMaxScaler(double newMin = 0.0, double newMax = 1.0)
        {
            if (newMin > newMax)
                throw new ArgumentOutOfRangeException("newMin should be less than newMax");
            Min = newMin;
            Max = newMax;
        }

        public void Fit(double[][] X, int[] y = null)
        {
            _min = Stats.Min(X, axis: 0);
            _max = Stats.Max(X, axis: 0);
        }

        public double[][] FitTransform(double[][] X, int[] y = null)
        {
            Fit(X, y);
            return Transform(X);
        }
        public double[][] Transform(double[][] X)
        {
           _CheckFitness();
            CheckInputs.CheckNumberOfFeatures(X, _min);
            double[][] ret = new double[X.Length][];
            for (int i = 0; i < X.Length; i++)
                ret[i] = Transform(X[i]);
            return ret;

        }
        public double[] Transform(double[] x)
        {
           _CheckFitness();
            CheckInputs.CheckNumberOfFeatures(_min, x);
            double[] ret = new double[x.Length];
            for(int i = 0; i < x.Length; i++)
            {
                double xStd = (x[i] - _min[i]) / (_max[i] - _min[i]);
                if(double.IsNaN(xStd)) // same max and min cse
                    xStd = 0.0;
                ret[i] = xStd * (Max - Min) + Min; 
            }
            return ret;
        }

        public object Clone()
        {
            return this.MemberwiseClone();
        }

    }
}
