using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Windows.Forms;
using LabelerCore.Data;


namespace UserControls
{
    public partial class TrainDataExplorer : UserControl
    {
        private Dictionary<string, bool> _displayClass;
        private bool _classesDGVCellValueChangedBlock = false;


        public delegate void VehicleClassSelectedHandler(string[] selectedClasses);
        public event VehicleClassSelectedHandler VehicleClassSelected;

        public TrainingData  TrainData 
        {
          get { return recordTable.TrainData;  }
          set { recordTable.TrainData = value; }
        }

        public string[] DisplayedClasses { get { return _displayClass.Where(x => x.Value).Select(x => x.Key).ToArray(); } }


        public TrainDataExplorer()
        {
            InitializeComponent();
            _displayClass = new Dictionary<string, bool>();
        }


        private void classesDGV_CellValueChanged(object sender, DataGridViewCellEventArgs e)
        {
            if (_classesDGVCellValueChangedBlock)
                return;
            if (classesDGV.Columns[e.ColumnIndex].Name == "displayColumn")
            {
                bool isChecked = classesDGV[e.ColumnIndex, e.RowIndex].Value.ToString() == "True";
                _displayClass[classesDGV["vehicleClassColumn", e.RowIndex].Value.ToString()] = isChecked;
                updateTrainDataDGV();
                if(VehicleClassSelected != null)
                    VehicleClassSelected(_displayClass.Where( x => x.Value).Select(x => x.Key).ToArray());
            }
        }

        private void classesDGV_CellMouseUp(object sender, DataGridViewCellMouseEventArgs e)
        {

            if (classesDGV.Columns[e.ColumnIndex].Name == "displayColumn" && e.RowIndex == -1)
            {
                _classesDGVCellValueChangedBlock = true;
                for (int i = 0; i < classesDGV.Rows.Count; i++)
                {
                    bool isChecked = classesDGV[e.ColumnIndex, i].Value.ToString() == "True";
                    classesDGV["displayColumn", i].Value = !isChecked;
                    _displayClass[classesDGV["vehicleClassColumn", i].Value.ToString()] = !isChecked;
                }
                _classesDGVCellValueChangedBlock = false;
                updateTrainDataDGV();
            }
            classesDGV.EndEdit();
   
        }

        private void _cmpDistToMean(List<Sample> samples)
        {
            LabelerCore.Loop.CmpSampleAttributes.SetDistToMean(samples);
        }

        private void _cmpMVN(List<Sample> samples)
        {
            LabelerCore.Loop.CmpSampleAttributes.SetMultivariateGaussian(samples.ToArray());
        }

        public void updateTrainDataDGV()
        {
            _classesDGVCellValueChangedBlock = true;
            if (TrainData == null)
                return;
            if (TrainData.Count < 1)
                return;
            List<Sample> samplesToDisplay = new List<Sample>();

            foreach (Sample s in TrainData)
                if (_displayClass.ContainsKey(s.vehicleClass))
                    if (_displayClass[s.vehicleClass])
                        samplesToDisplay.Add(s);

            RecordTableColumn distToMean = recordTable.TableColumns_.GetColumn("DistToMean");
            if(distToMean != null)
                if(distToMean.enabled)
                    _cmpDistToMean(samplesToDisplay);

            RecordTableColumn mahalonobis = recordTable.TableColumns_.GetColumn("Mahalonobis");
            RecordTableColumn mvnPD = recordTable.TableColumns_.GetColumn("MvnPD");

            if (mahalonobis != null)
                if(mahalonobis.enabled)
                    _cmpMVN(samplesToDisplay);
            if (mvnPD != null)
                if (mvnPD.enabled)
                    _cmpMVN(samplesToDisplay);

            recordTable.ShowItems(samplesToDisplay);
            _classesDGVCellValueChangedBlock = false;
        }

        public void updateClassesDGV()
        {
            if (TrainData == null)
                return;
            _classesDGVCellValueChangedBlock = true;
            classesDGV.Rows.Clear();
            _displayClass.Clear();
            if (TrainData.Classes.Count < 1)
                return;
            classesDGV.Rows.Add(TrainData.Classes.Count);
            for (int i = 0; i < TrainData.Classes.Count; i++)
            {
                string vehicleClass = TrainData.Classes[i];
                classesDGV[0, i].Value = vehicleClass;
                classesDGV[1, i].Value = TrainData.getClassCount(vehicleClass);
                
                //compute class inertia ...
                double[][] X = TrainData.Samples
                                        .Where(x => x.vehicleClass == vehicleClass)
                                        .Select(x => x.FeatureArray)
                                        .ToArray();
                //normalize
                X = (new LabelerCore.Model.Transformers.MinMaxScaler()).FitTransform(X);
                //compute inertia
                classesDGV[2, i].Value = LabelerCore.Model.Math.Stats.SumOfDists(X) / TrainData.getClassCount(vehicleClass);
                classesDGV[3, i].Value = false;
                _displayClass.Add(vehicleClass, false);
            }
            _classesDGVCellValueChangedBlock = false;
        }

    }
}
