using MoreLinq;
using System;
using System.Collections.Generic;
using System.Linq;

namespace Gremlin.GremlinUtilities.GUClasses
{
    class DataIdentificator
    {
        private readonly string _source;    //Qualifier-Liste
        private readonly Dictionary<string, int> _mappingTable; //Mapping Spaltenzahl <-> Property/(übersetzte) Spaltenüberschrift
        public List<DataIdType> DataTypes { get; set; }
        

        public DataIdentificator(Dictionary<string, int> MappingTable)
        {
            _mappingTable = MappingTable;
            //DataTypes populieren. Dazu: einlesen, nach DT qualifier in temp. Liste speichern, damit neuen DIDT erzeugen und zur Liste hinzufügen
            this.Initialize();
        }

        private void Initialize()
        {
            string _currentDataType;
            DataTypes = new();
            List<DataIdentifier> dataIdentifier = ReadDataIdentifierFromFile();
            _currentDataType = dataIdentifier[0].DataType;
            List<string> _identifierOfCurrentType = new();
            foreach (DataIdentifier qualifier in dataIdentifier)
            {
                if (qualifier.DataType == _currentDataType)
                {
                    _identifierOfCurrentType.Add(qualifier.Identifier);
                    if (qualifier == dataIdentifier[^1])  //letztes Element der Liste
                    {
                        DataIdType typeToBeAdded = new(_currentDataType, _identifierOfCurrentType);
                        DataTypes.Add(typeToBeAdded);
                        //_currentDataType = qualifier.DataType;
                    }
                    continue;
                }
                else
                {
                    DataIdType typeToBeAdded = new(_currentDataType, _identifierOfCurrentType);
                    DataTypes.Add(typeToBeAdded);
                    _currentDataType = qualifier.DataType;
                    _identifierOfCurrentType.Clear();
                    _identifierOfCurrentType.Add(qualifier.Identifier);
                }
            }
        }

        public List<string> Identify(bool MustMatchAllQualifer = true)
        {
            List<string> winners = new();

            foreach (DataIdType datatype in DataTypes)
            {
                foreach (string qualifier in datatype.Qualifiers)
                {
                    if (_mappingTable.ContainsKey(qualifier))
                    {
                        datatype.AddFoundQualfier(qualifier);
                    }
                }
            }

            if (MustMatchAllQualifer)
            {
                foreach (DataIdType dataType in DataTypes)  //may return multiple winners
                {
                    if (dataType.AllQualifierMatched)
                    {
                        winners.Add(dataType.DataType);
                    }
                }
            }
            else //return the winner by highest score:
            {
                winners.Add(DataTypes.Aggregate((x, y) => x.Score > y.Score ? x : y).DataType.ToString());
            }

            //Plausibilty checkpoint: 
            //1. Remove "PL", "AccountType", "Submarket" from Winner-List, if detected datatype is "LSAG" or "Account".
            //2. LSAG = Account + Contact --> when LSAG is a winner, remove "LSAG" and add "Account" and "Contact" to use their dedicated import methods.
            //3. Remove any other winner, when winner is one of "PL", "AccountType", "Submarket" AND fields[].count = 2.
            if (MustMatchAllQualifer == true && winners.Contains("LSAG"))
            {
                if (winners.Contains("ProductLine")) winners.Remove("ProductLine");
                if (winners.Contains("AccountType")) winners.Remove("AccountType");
                if (winners.Contains("SubMarket"))   winners.Remove("SubMarket");
                
                if (winners.Contains("Account"))     winners.Remove("Account");
                if (winners.Contains("Contact"))     winners.Remove("Contact");
            }

            if (MustMatchAllQualifer == true && winners.Contains("Account"))
            {
                if (winners.Contains("ProductLine")) winners.Remove("ProductLine");
                if (winners.Contains("AccountType")) winners.Remove("AccountType");
                if (winners.Contains("SubMarket")) winners.Remove("SubMarket");
            }

            if (MustMatchAllQualifer == false && _mappingTable.Count == 2)
            {
                if (winners.Contains("ProductLine"))
                {
                    winners.Clear();
                    winners.Add("ProductLine");
                }

                if (winners.Contains("AccountType"))
                {
                    winners.Clear();
                    winners.Add("AccountType");
                }

                if (winners.Contains("SubMarket"))
                {
                    winners.Clear();
                    winners.Add("SubMarket");
                }
            }

            return winners;
        }

        public List<DataIdentifier> ReadDataIdentifierFromFile()
        {
            List<DataIdentifier> result = new(50);
            string fileInput = FileIO.ReadResource("DataIdentifier.txt");
            string[] lines = fileInput.Split(Environment.NewLine);
            foreach (string line in lines)
            {
                string[] fields;
                DataIdentifier identifier = new();
                fields = line.Split("|");
                identifier.DataType = fields[0];
                identifier.Identifier = fields[1];
                result.Add(identifier);
            }
            return result;
        }

    }
}
