using System;
using System.Collections.Generic;
using System.Text;

namespace Intemi
{
    public class RankingCCConfig : IConfiguration
    {
        private bool selectByThreshold = false;
        public bool SelectByThreshold
        {
            get { return selectByThreshold; }
            set { selectByThreshold = value; }
        }
        private double selectionThreshold = 0.5;
        public double SelectionThreshold
        {
            get { return selectionThreshold; }
            set { selectionThreshold = value; }
        }
        private int selectionSize = 1;
        public int SelectionSize
        {
            get { return selectionSize; }
            set { selectionSize = value; }
        }
        private bool weightByNonmissing = true;
        public bool WeightByNonmissing
        {
            get { return weightByNonmissing; }
            set { weightByNonmissing = value; }
        }

        void IConfiguration.Configure(ConfigBuilder builder)
        {
            builder.DeclareInput("Dataset", 
                new Type[] { typeof(IDataTable), typeof(ITargets) });
            builder.DeclareOutput("Feature Ranking", "Fr",
                new Type[] { typeof(IFeatureRanking) });
        }
        object ICloneable.Clone()
        {
            RankingCCConfig cnf = new RankingCCConfig();
            cnf.selectByThreshold = selectByThreshold;
            cnf.selectionSize = selectionSize;
            cnf.selectionThreshold = selectionThreshold;
            cnf.weightByNonmissing = weightByNonmissing;
            return cnf;
        }
    }

    [Machine("CC ranking",typeof(RankingCCConfig))]
    public class RankingCC : IMachine
    {
        IMachineBase machineBase;
        IFeatureRanking fr;

        public IFeatureRanking Fr
        {
            get { return fr; }
        }

        public void SetMachineBase(IMachineBase _machineBase)
        {
            machineBase = _machineBase;
        }
        public void Run(ref bool shouldTerminate)
        {
            RankingCCConfig config = (RankingCCConfig)machineBase.ConfBase.Configuration;
            IDataTable dt = machineBase.GetInput("Dataset") as IDataTable;
            IOneFeatureData t = (dt as ITargets).Targets;
            IVectorEnumerator fe = dt.FeatureEnumerator();
            IVectorEnumerator te = t.FeatureEnumerator();
            float[] fVector = fe.Vector;
            float[] tVector = te.Vector;
            bool[] mVector = fe.Missing;
            bool[] tmVector = te.Missing;
            FeatureStat[] fs = dt.FeatureStatistics;
            FeatureStat ts = t.FeatureStatistics;

            te.GoToInstance(0);

            FeatureRankingBuilder frb;

            int fCount = dt.FeaturesInfo.Count;
            if (dt != null)
                frb = new FeatureRankingBuilder(fCount, "CC Ranking");
            else return;
            double value;
            for (int i = 0; !shouldTerminate && i < fCount; i++)
            {
                fe.GoToInstance(i);
                value = CITools.CorrCoef(fVector, tVector, mVector, tmVector,
                        fs[i].mean, ts.mean, fs[i].standardDev, ts.standardDev);
                if (config.WeightByNonmissing)
                    value *= (fVector.Length - dt.FeatureStatistics[i].missValueStat) / fVector.Length;
                frb.AddRank(i,value);
            }
            if (!shouldTerminate)
                frb.SortAbsDesc();
            frb.SelectByThreshold = config.SelectByThreshold;
            frb.SelectionThreshold = config.SelectionThreshold;
            frb.SelectionSize = config.SelectionSize;
            if (!shouldTerminate)
                fr = frb.Build();
        }
    }
}
