using System;
using System.Linq;
using System.IO;
using System.Xml.Linq;
using System.Collections.Generic;



namespace LabelerCore.Data
{

    public class Sample: VehicleInfo
    {

        public static readonly string VehicleClassColName = "class_name";

        //public static readonly string[] ComputedAttributes = 
        //{
        //     "DistToMean",
        //     "Cluster",
        //     "Mahalonobis",
        //     "MvnPD",
        //};

        public readonly string vehicleClass;         //sample label

        public double? distToMean = null;           //distance to Class mean
        //public int? cluster = null;
        public double? mahalonobisDist = null;      //mahalonobis distance to Class distribution
        public double? mvnPd = null;                //mvn prob. density

        public Sample(string fullFileName, string vehicleClass,
                      bool loadDataOnTheSpot = false,
                      Dictionary<string, string> additionalInfo = null,
                      bool checkPath=true)
            :base(fullFileName, additionalInfo, checkPath)
        {
            this.vehicleClass = vehicleClass;
            if(loadDataOnTheSpot)
            {
                var dummy1 = Frq;
                var dummy2 = WIM;
                var dummy3 = Img;
            }
        }

        public Sample(Sample s):
            base(s.path, s._preloadedAttributes)
        {
            vehicleClass = s.vehicleClass;
        }

        public Sample(VehicleInfo info, string vehicleClass)
            :base(info.path)
        {
            this.vehicleClass = vehicleClass;
        }

        public override object GetAttribute(string name)
        {
            if (name == "class_name")
                return vehicleClass;
            else if (name == "DistToMean")
                return distToMean;
            else if (name == "Mahalonobis")
                return mahalonobisDist.ToString();
            else if (name == "MvnPD")
                return mvnPd;
            else 
                return base.GetAttribute(name);

        }

        public override string ToString()
        {
            return base.path + ";" + vehicleClass;
        }         
        
        public string GetCsvRow(string[] attributeNames)
        {
           string attributes = string.Join(";",
               attributeNames.Select(x => GetAttribute(x) == null ? "" : GetAttribute(x).ToString()));
           return attributes;
        }    
      
        public static int getClassCode(string vehicleClass)
        {
            int classCode;
            if (int.TryParse(string.Join("", vehicleClass.Take(vehicleClass.IndexOf('-'))), out classCode))
                return classCode;
            else
                return -1;
        }

        public void CopyDataFilesTo(string path)
        {
           string dirName = Path.GetDirectoryName(base.path);
           string relDirName = string.Join("", base.path.Skip(base.path.IndexOf("FRQ")));
           string newPath = Path.Combine(path, relDirName);
           if (!Directory.Exists(newPath))
               Directory.CreateDirectory(newPath);
           File.Copy(Path.Combine(dirName, ID) + ".csv", Path.Combine(newPath, ID) + ".csv");
           File.Copy(Path.Combine(dirName, ID) + ".jpg", Path.Combine(newPath, ID) + ".jpg");
           File.Copy(Path.Combine(dirName, ID) + ".frq", Path.Combine(newPath, ID) + ".frq");
        }

        public XElement GetXElement(FeatureHeader[] features)
        {
            string dirName = Path.GetDirectoryName(base.path);
            int[] featuresToWrite = FeatureArray.Select(x => (int)Math.Round(x * 1000)).ToArray();
            string relDirName = string.Join("", dirName.Skip(dirName.IndexOf("FRQ")));
            return new XElement(XmlTags.PatternXmlTag, 
                                string.Join(";", featuresToWrite),
                                new XAttribute("ID", Path.Combine(relDirName, ID)));
        }

    }


}
