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

namespace Intemi
{
    public class OneNNConfig : IConfiguration
    {
        public void Configure(ConfigBuilder confBuilder)
        {
	        confBuilder.DeclareInput("Dataset",
	            new Type[] { typeof(IDataTable), typeof(ITargets) });
	        confBuilder.DeclareOutput("Classifier", null,
	            new Type[] { typeof(IClassifier) });
        }
        public object Clone() { return new OneNNConfig(); }
    }

    [Machine("1NN",typeof(OneNNConfig))]
    public class OneNN : IMachine, IClassifier
    {
        IMachineBase machineBase;
        public void SetMachineBase(IMachineBase mb) { machineBase = mb; }

        IDataTable trnD;
        IOneFeatureData targets;
        public void Run(ref bool shouldTerminate) 
        { 
		    trnD = machineBase.GetInput("Dataset") as IDataTable;
        	targets = (trnD as ITargets).Targets;
        }
        public IOneFeatureData Classify(IDataSet data)
        {
            IOneFeatureDataBuilder t = targets.CopyStructure(data.InstanceCount);
	        IInstanceEnumerator ed = data.InstanceEnumerator();
	        IInstanceEnumerator et = trnD.InstanceEnumerator();
            SquareEuclideanMetric m = new SquareEuclideanMetric();

	        for (int i = 0; i < data.InstanceCount; i++)
	        {
	            ed.GoToInstance(i);
	            double d, minDist = System.Double.PositiveInfinity;
	            int minId = -1;
                for (int j = 0; j < trnD.InstanceCount; j++)
                {
                    et.GoToInstance(j);
                    d = m.Distance(ed, et, minDist);
                    if (d < minDist) { minId = j; minDist = d; }
                }
	            t.AddValue(targets[minId]);
	        }
            return (IOneFeatureData)t.Build();
        }
        public bool VerifyTestData(IDataSet data) 
        { 
	        int featureCount = trnD != null? trnD.FeaturesInfo.Count : 0;
	        IDataTable dt = data as IDataTable;
	        return dt != null && dt.FeaturesInfo.Count == featureCount; 
        }
    }
}
