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

namespace Magical_Hasse_Flow
{
    public class Hasse2D
    {
        public List<Nodo> dominio {get; set;}
        public Relacion2D[,] matriz { get; set; }
        public List<Relacion2D> antisimetricas{ get; set; }
        public List<int> NodosEnFila { get; set; }
        public int MyProperty { get; set; }
        public int alto { get; set; }
        public int ancho { get; set; }
        public Random aleatorio { get; set; }
        public Hasse2D()
        {
            aleatorio = new Random();
        }
        public bool R(int pA, int pB)
        {
            if ((pB % pA) == 0)
                return true;
            return false;
        }
        public void getCoordenadas()
        {
            int xInicio;

            for (int i = 0; i < dominio.Count; i++)
            {
                if (dominio[i].nivel != -1)
                { 
                xInicio = ancho - NodosEnFila[dominio[i].nivel];
                dominio[i].x = xInicio + dominio[i].posicion * 2 + 1;
                dominio[i].y = dominio[i].nivel + 1; 
                }
            }
        }

        public bool AleatorioBool()
        {
            if (aleatorio.Next(2) == 0)
                return true;
            else
                return false;
        }
        public void goHasse()
        {
            matriz = new Relacion2D[dominio.Count, dominio.Count];
            antisimetricas = new List<Relacion2D>();
            NodosEnFila = new List<int>(dominio.Count);

            Nodo a;
            Nodo b;
            Nodo A;
            Nodo B;

            for (int i = 0; i < dominio.Count; i++)
            {
                NodosEnFila.Add(0);
                b = dominio[i];

                for (int j = 0; j < dominio.Count; j++)
                {
                    a = dominio[j];

                    if(matriz[i, j] != null)
                        continue;

                    if (R(a.valor, b.valor))
                    {
                        if (a.valor == b.valor)
                        {
                            matriz[i, j] = new Relacion2D(a, b, TiposRelacion.Reflexiva);
                        }
                        else
                        {
                            matriz[i, j] = new Relacion2D(a, b, TiposRelacion.Antisimetrica);
                            matriz[i, j].color = new ColorRelacion(AleatorioBool(), AleatorioBool(), AleatorioBool(), aleatorio.Next(256), aleatorio.Next(256), aleatorio.Next(256));
                            antisimetricas.Add(matriz[i, j]);

                            if (a.nivel == -1)
                            {
                                a.nivel = 0;                        
                            }

                            b.nivel = a.nivel + 1;

                            A = b;
                            for (int k = i + 1; k < dominio.Count; k++)
                            {
                                B = dominio[k];

                                if (R(A.valor, B.valor))
                                { 
                                    matriz[k, j] = new Relacion2D(A, B, TiposRelacion.Transitiva);
                                }
                            }
                        }
                    }
                    else
                    {
                        matriz[i, j] = new Relacion2D(a, b, TiposRelacion.Null);
                    }

                }    
            }

            for (int i = 0; i < dominio.Count; i++)
            {
                if (dominio[i].nivel != -1)
                {
                    dominio[i].posicion = NodosEnFila[dominio[i].nivel];
                    NodosEnFila[dominio[i].nivel]++;
                }
            }

            for (int i = 0; i <= NodosEnFila.Count; i++)
            {
                alto = i;
                if (i == NodosEnFila.Count || NodosEnFila[i] == 0)
                    break;
            }
            
            ancho = 0;

            for (int i = 0; i < alto; i++)
            {
                if (NodosEnFila[i] > ancho)
                    ancho = NodosEnFila[i];
            }

            getCoordenadas();
        }

        public String NotacionDeConjuntos()
        {
            String notacion;
            int a;
            int b;

            notacion = "R = { ";

            for (int i = 0; i < dominio.Count; i++)
            {
                for (int j = 0; j < dominio.Count; j++)
                {
                    if (matriz[i, j].tipo != TiposRelacion.Null)
                    {
                        a = matriz[i, j].a.valor;
                        b = matriz[i, j].b.valor;

                        notacion += "(" + a.ToString() + "," + b.ToString() + ")";
                        notacion += " ; ";            
                    }                    
                }
            }

            notacion = notacion.Remove(notacion.Length - 3);
            notacion += " }";

            return notacion;

        }
       
    }
}
