using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Drawing;

using Nfiq;
using CUDAFingerprinting.Common;
using MccSdk = BioLab.Biometrics.Mcc.Sdk;
using Obedience.Processing;
using System.Xml.Serialization;

namespace ResultsExtraction
{
  public class FingerprintsDictionary
  {
    private const int ir = 500;
    private int pathLength = 0;

    public List<FingerprintStruct> ListOfFingerprints = new List<FingerprintStruct>();
    public Dictionary<string, List<FingerprintStruct>> DictionaryOfSame
      = new Dictionary<string, List<FingerprintStruct>>();

    public FingerprintsDictionary(string path)
    {
      this.pathLength = path.Length;
      string[] imagesNames = Directory.GetFiles(path);
      FingerprintStruct newStruct;
      List<FingerprintStruct> newList;

      foreach (var name in imagesNames)
      {
        newStruct = GetFingerprintStructure(name);

        if (!DictionaryOfSame.Keys.Contains(newStruct.Finger))
        {
          newList = new List<FingerprintStruct>();
          newList.Add(newStruct);
          DictionaryOfSame.Add(newStruct.Finger, newList);
        }
        else
        {
          DictionaryOfSame[newStruct.Finger].Add(newStruct);
        }

        ListOfFingerprints.Add(newStruct);
      }
    }

    private string GetShortName(string fullName)
    {
      return fullName.Substring(pathLength, fullName.Length - pathLength - 6);
    }

    private string GetNumberOfFinger(string fullName)
    {
      string shortName = fullName.Substring(pathLength, fullName.Length - pathLength - 4);

      return shortName.Substring(0, shortName.IndexOf('_'));
    }

    private FingerprintStruct GetFingerprintStructure(string name)
    {
      var image = ImageHelper.LoadImage(name);
      int iw = image.GetLength(1);
      int ih = image.GetLength(0);
      int[,] qualityMap = Nfiq.Nfiq.GetQualityMap(new Bitmap(name));
      List<Minutia> minutiae = MinutiaeExtractor.ExtractCUDAFpMinutiae(image, ih, iw);

      string finger = GetNumberOfFinger(name);
      List<MccSdk.Minutia> convertMinutiae = ConvertMinutiae(minutiae.FindAll(m => IsGoodMinutia(m, qualityMap)));
      object template = MccSdk.MccSdk.CreateMccTemplate(iw, ih, ir, convertMinutiae.ToArray());

      return new FingerprintStruct() { Finger = finger, Template = template};
    }

    private bool IsGoodMinutia(Minutia m, int[,] map)
    {
      int x = (int)Math.Ceiling(m.X / (double)Constants.Blocksize);
      int y = (int)Math.Ceiling(m.Y / (double)Constants.Blocksize);

      try
      {
        return ROC.IsGoodMinutia(map[x, y]);
      }
      catch (Exception e)
      {
        return false;
      }
    }

    private List<MccSdk.Minutia> ConvertMinutiae(List<Minutia> minutiae)
    {
      List<MccSdk.Minutia> result = new List<MccSdk.Minutia>();
      MccSdk.Minutia newItem;

      // convert to MccSdk minutiae

      for (int i = 0; i < minutiae.Count; i++)
      {
        newItem = new MccSdk.Minutia();
        newItem.X = minutiae[i].X;
        newItem.Y = minutiae[i].Y;
        newItem.Direction = minutiae[i].Angle;
        result.Add(newItem);
      }

      return result;
    }
  }
}
