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


namespace UserControls
{

    public partial class RecordTable : UserControl
    {
        private bool _dataDGVCellValueChangedBlock = false;
        private bool _dataDGV_RowEnterBlock = false;
        private TrainingData  _trainData;
        private RecordTableColumns _columnsEnabled = new RecordTableColumns();
        private VehicleInfo[] _displayedVehicles;
        public VehicleInfo[] DisplayedVehicles { get { return _displayedVehicles;  } }

        public RecordTableColumns TableColumns_
        {
            get { return _columnsEnabled; }
            set { _columnsEnabled = value; UpdateColumns(); }
        }
        public delegate void TrainDataCountChangedHandler(int count);
        public delegate void ItemEnterHandler(VehicleInfo info, 
                                              double[] x,
                                              int toolTipXPos,
                                              int toolTipYPos);

        public delegate void TableUpdatedHandler();
        public event TrainDataCountChangedHandler TrainDataCountChanged;
        public event ItemEnterHandler ItemEnter;
        public event TableUpdatedHandler TableUpdated;



        private void UpdateColumns()
        {
            DGV.Columns.Clear();
            foreach (var item in TableColumns_.columns)
                if (item.enabled)
                    AddColumn(item.name, item.isReadonly, item.type);
        }

        public void AddColumn(string name, bool isReadonly=true, Type type=null)
        {
            DataGridViewColumn col = new DataGridViewColumn();
            col.ValueType = type;
            col.Name = name + "Col";
            col.HeaderText = name;
            col.DataPropertyName = name;
            col.ReadOnly = isReadonly;
            col.CellTemplate = new DataGridViewTextBoxCell();
            col.SortMode = DataGridViewColumnSortMode.Automatic;
            col.AutoSizeMode = DataGridViewAutoSizeColumnMode.Fill;
            DGV.Columns.Add(col);
        }

        public TrainingData  TrainData
        {
            get { return _trainData; }
            set { _trainData = value; }
        }

        public RecordTable()
        {
            InitializeComponent();
            UpdateColumns();
        }

        public VehicleInfo[] GetCurrentItems()
        {
            VehicleInfo[] res = new VehicleInfo[DGV.Rows.Count];
            for (int i = 0; i < res.Length; i++)
                res[i] = (VehicleInfo)DGV.Rows[i].Tag;
            return res;
        }

        public void AddColumn(Tuple<VehicleInfo, object>[] items, string colName)
        {

            _dataDGVCellValueChangedBlock = true;
            AddColumn(colName);
            foreach(var infoVal in items)
                //find row with current item id
                for(int i = 0; i < DGV.Rows.Count; i++)
                    if (infoVal.Item1.ID == ((VehicleInfo)DGV.Rows[i].Tag).ID)
                        DGV[DGV.Columns[colName + "Col"].Index, i].Value = infoVal.Item2; 
            _dataDGVCellValueChangedBlock = false;
        }

        public void ShowItems(VehicleInfo[] vehicleInfos)
        {
            if (vehicleInfos == null)
                return;
            _displayedVehicles = vehicleInfos;
            DGV.Rows.Clear();
            UpdateColumns();
            if (vehicleInfos.Length < 1)
                return;
            if (DGV.Columns.Count < 1)
                return;

            _dataDGVCellValueChangedBlock = true;
            _dataDGV_RowEnterBlock = true;

            DGV.Rows.Add(vehicleInfos.Length);
            for (int idx = 0; idx < vehicleInfos.Length; idx++)
            {
                try
                {
                    VehicleInfo info = vehicleInfos[idx];
                    if (_trainData != null) {
                        if (_trainData.Exists(info.ID)) {
                            info = _trainData.getSample(info.ID);
                            //DGV[DGV.Columns[Sample.VehicleClassColName + "Col"].Index, idx].Value = info.GetAttribute("class_name");
                        }
                    }
                    foreach (var item in TableColumns_.columns)
                    {
                        if (item.enabled)
                        {
                           
                            object attr = info.GetAttribute(item.name);
                            if (item.type == typeof(double?) || item.type == typeof(double))
                            {
                                double dummy; string s = attr.ToString().Replace('.', ',');
                                if (double.TryParse(s, out dummy))
                                    DGV[DGV.Columns[item.name + "Col"].Index, idx].Value = dummy;
                                else
                                    DGV[DGV.Columns[item.name + "Col"].Index, idx].Value = s;
                            }
                            else if (item.type == typeof(int))
                            {
                                int dummy; string s = attr.ToString().Replace('.', ',');
                                if (int.TryParse(s, out dummy))
                                    DGV[DGV.Columns[item.name + "Col"].Index, idx].Value = dummy;
                                else
                                    DGV[DGV.Columns[item.name + "Col"].Index, idx].Value = s;
                            }
                            else if (item.type == typeof(System.DateTime))
                                DGV[DGV.Columns[item.name + "Col"].Index, idx].Value = (System.DateTime)attr;
                            else
                                DGV[DGV.Columns[item.name + "Col"].Index, idx].Value = attr;
                        }   
                    }
                    DGV.Rows[idx].Tag = info;
                }
                catch (System.Exception e)
                {
                    DGV[0, idx].Value = "Error: " + e.Message;
                }

            }
            _dataDGVCellValueChangedBlock = false;
            _dataDGV_RowEnterBlock = false;
            if (TableUpdated != null)
                TableUpdated();
        }

        public void ShowItems(List<Sample> samples)
        {
            ShowItems(samples.ToArray());
        }

        protected void dataDGV_RowEnter(object sender, DataGridViewCellEventArgs e)
        {
            if (_dataDGV_RowEnterBlock) return;
            if (DGV.SelectedRows.Count == 0) return;
            if (DGV.CurrentRow == null) return;
            if (DGV.SelectedRows[0].Tag == null) return;

            if (ItemEnter != null)
            {
                VehicleInfo info = (VehicleInfo)DGV.Rows[e.RowIndex].Tag;
                double[] x = info.FeatureArray;
                var rowDisplayRect =  DGV.GetRowDisplayRectangle(e.RowIndex, false);
                //raise event
                ItemEnter((VehicleInfo)DGV.SelectedRows[0].Tag,
                          x,
                          rowDisplayRect.X + DGV.Width / 2,  //tooltip position
                          rowDisplayRect.Y + DGV.CurrentRow.Height); //tooltip position
            }
        }

        protected void dataDGV_CellValueChanged(object sender, DataGridViewCellEventArgs e)
        {
            if (_dataDGVCellValueChangedBlock)
                return;
            if (DGV.Columns[e.ColumnIndex].Name == Sample.VehicleClassColName + "Col")
            {
                if ((VehicleInfo)DGV.SelectedRows[0].Tag == null)
                    return;
                VehicleInfo info = (VehicleInfo)DGV.SelectedRows[0].Tag;
                if (DGV[e.ColumnIndex, e.RowIndex].Value == null)
                {
                    _trainData.RemoveSample(info.ID);
                    if (TrainDataCountChanged != null)
                        TrainDataCountChanged(_trainData.Count);
                    return;
                }

                string vehicleClass = DGV[e.ColumnIndex, e.RowIndex].Value.ToString();
                Sample s = new Sample(info, vehicleClass);
                if (!_trainData.AddSample(s))
                    _trainData.InsertSample(s);
                if (TrainDataCountChanged != null)
                    TrainDataCountChanged(_trainData.Count);
            }
        }

        private void setAutoComplete(TextBox autoText)
        {
            if (autoText != null)
            {
                autoText.AutoCompleteMode = AutoCompleteMode.Suggest;
                autoText.AutoCompleteSource = AutoCompleteSource.CustomSource;
                AutoCompleteStringCollection dataCollection = new AutoCompleteStringCollection();
                dataCollection.AddRange(_trainData.Classes.ToArray());
                autoText.AutoCompleteCustomSource = dataCollection;
            }
        }

        private void dataDGV_EditingControlShowing(object sender, DataGridViewEditingControlShowingEventArgs e)
        {
            TextBox autoText = e.Control as TextBox;
            setAutoComplete(autoText);
        }


    }
}
