using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Graphs;

namespace Matching
{
    /// <summary>
    /// Labels hérite de Label et contient une liste de Label. Il permet de représenter les Label du graphe
    /// qui sont contenus dans un noeud de l'arbre de recherche SearchTree.
    /// </summary>
    public class Labels : Label
    {

        List<Label> listLabels = new List<Label>();

        /// <summary>
        /// Contient tous les labels d'un noeud de l'arbre de recherche
        /// </summary>
        public List<Label> ListLabels
        {
            get { return listLabels; }
            set { listLabels = value; }
        }


        /// <summary>
        /// Permet d'obtenir la chaine de caractères qui décrit tous les Label. La chaîne de caractères retournée est en fait la suite des Label.toString() contenus dans ListLabel
        /// </summary>
        /// <returns>Description de tous les Label contenus. Une ligne représente un label.</returns>
        public override string toString()
        {
            string retour = "";

            if (listLabels.Count > 0)
            {

                if (listLabels.ElementAt(0) != null) retour = "Label 0" + " : " + listLabels.ElementAt(0).toString();
                else retour = "Label 0 null";

                for (int i = 1; i < listLabels.Count; i++)
                {
                    if (listLabels.ElementAt(i) != null) retour = retour + "\t" + "Label " + i + " : " + listLabels.ElementAt(i).toString();
                    else retour = retour + "\t" + "Label " + i + " : null";
                }
            }
            return retour;
        }

        
        /// <summary>
        /// Permet de savoir si les deux ensembles de Label sont jugés identiques. 
        /// Cette fonction utilise la méthode dissimilarity de chaque Label contenu dans Labels
        /// avec celui de l'autre Labels étant au même indice. La fonction renvoie seulement
        /// une réponse vrai ou faux pour savoir si c'est deux Labels sont jugés égaux. 
        /// Effectivement la somme des Label pourrait être trompeuse en cas de signes contraires et 
        /// donc retourner un faux matching.
        /// </summary>
        /// <param name="labels">Labels avec lequel on veut tester la dissimilarité.</param>
        /// <returns>0 si les Labels sont jugés similaires, 1 s'ils ne sont pas similaires, double.MinValue si les Labels ne contiennent pas autant de Label ou que la paramètre n'est pas un Labels.</returns>
        public override double dissimilarity(Label labels)
        {
            if (labels is Labels)
            {
                //Il faut que les Labels aient autant de Label pour faire la comparaison
                if (((Labels)labels).listLabels.Count == this.listLabels.Count)
                {
                    // Il suffit que deux Label ne soient pas similaires pour qu'on retourne faux
                    for (int i = 0; i < listLabels.Count; i++)
                    {
                        //Quand les il n'y a pas de Label (exemple edge non existant) alors le Label est à null
                        if (((Labels)labels).ListLabels.ElementAt(i) == null && listLabels.ElementAt(i) == null) return 0;
                        else if (((Labels)labels).ListLabels.ElementAt(i) == null || listLabels.ElementAt(i) == null) return 1;
                        if(((Labels)labels).ListLabels.ElementAt(i).dissimilarity(listLabels.ElementAt(i)) != 0) return 1;
                    }

                    // Dans ce cas ils sont tous similaires
                    return 0;
                }
                else return double.MinValue;
                
            }
            else return double.MinValue;
        }

        /// <summary>
        /// Permet de faire le mapping du fichier GXL vers les Label contenus dans Labels. Dans cette fonction est appelé
        /// la fonction Label.fromAttributes de chaque Label contenus dans Labels.
        /// </summary>
        /// <param name="attributes">Liste d'AttributeGXL contenant les informations sur les valeurs du Labels à distribuer
        /// pour les différents Label.</param>
         public override void fromAttributes(List<AttributeGXL> attributes)
        {
            List<AttributeGXL> listOneLabel = new List<AttributeGXL>();
            Boolean premierLabel = true;
            int indiceLabel = 0;

            for(int indiceAttribut = 0; indiceAttribut < attributes.Count;indiceAttribut++)
            {
            
                //On ne tient pas compte du premier attribut qui s'appelle Label
                if (premierLabel)
                {
                    premierLabel = false;
                }

                else
                {
                    //Si l'attribut ne s'appelle pas Label alors on l'ajoute
                    if (attributes.ElementAt(indiceAttribut).Name != "Labels")
                    {

                        listOneLabel.Add(attributes.ElementAt(indiceAttribut));
                    }
                    //Sinon on appel fromAttributes de ce Label et on clear la liste et on passe au suivant
                    else
                    {

                        listLabels.ElementAt(indiceLabel).fromAttributes(listOneLabel);
                        indiceLabel++;
                        listOneLabel.Clear();
                    }
                    //Il faut appeler fromAttributes car il n'y a pas d'attributeGXL.Name = Label pour le dernier
                    if (indiceAttribut == attributes.Count - 1)
                    {
                        listLabels.ElementAt(indiceLabel).fromAttributes(listOneLabel);
                        indiceLabel++;
                        listOneLabel.Clear();
                    }
                }

            }
        }

        /// <summary>
        /// Permet de faire le mapping du Label vers le fichier GXL.Dans cette fonction est appelé
        /// la fonction Label.toAttributes de chaque Label contenus dans Labels.
        /// </summary>
        /// <returns>Liste d'AttributeGXL représentant les Label contenus dans Labels. </returns>
         public override List<AttributeGXL> toAttributes()
        {

            List<AttributeGXL> attributes = new List<AttributeGXL>();

            foreach (Label label in listLabels)
            {
                //Il faut insérer la balise Label pour distinguer les attributs de chaque Label
                AttributeGXL baliseLabel = new AttributeGXL("String", "Labels", "");
                attributes.Add(baliseLabel);

                //Ensuite on insère les attributs du Label
                if (label != null)
                {
                    List<AttributeGXL> attributesTemp = label.toAttributes();
                    attributes = attributes.Concat(attributesTemp).ToList();
                }

            }

            return attributes;
            
        }

    }
}
