using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using GMLC01HerramientasCad.Logica;

namespace GMLC01HerramientasCad.Logica
{

    /// <summary>
    /// Formulario de búsqueda de elementos por criterio alfanumérico
    /// </summary>
    public partial class BuscarForm : BaseForm
    {
        private IBuscar iCommIF;
        private Entidad iEntidad;
        private List<TextoCriterio> criteriosTexto;
        private List<TextoCriterio> criteriosNumero;
        private List<TextoCriterio> criteriosDominio;

        /// <summary>
        /// Para controlar cuando se estan validando datos.
        /// </summary>
        private bool inValidating;

        /// <summary>
        /// Constructor del formulario
        /// </summary>
        /// <param name="commIF">Interfaz implementada con las funciones a llamar desde el formulario</param>
        /// <param name="entidad">Entidad sobre la que se va a realizar la búsqueda</param>
        public BuscarForm(IBuscar commIF, Entidad entidad)
        {
            try
            {
                iCommIF = commIF;
                iEntidad = entidad;

                InitializeComponent();
                InicializarListas();
                CreaControlesDinamicos(entidad);
            }
            catch (ExcepcionGMLC)
            {
                throw;
            }
            catch (Exception e)
            {
                Log.RegisterError(e);
                throw new ExcepcionGMLC(e.Message, e);
            }
        }

        private void InicializarListas()
        {
            criteriosTexto = new List<TextoCriterio>();
            criteriosTexto.Add(new TextoCriterio(TiposCriterios.Nada, ""));
            criteriosTexto.Add(new TextoCriterio(TiposCriterios.EsIgualA, Properties.Resources.EsIgualA ));
            criteriosTexto.Add(new TextoCriterio(TiposCriterios.NoEsIgualA, Properties.Resources.NoEsIgualA ));
            criteriosTexto.Add(new TextoCriterio(TiposCriterios.Contiene, Properties.Resources.Contiene));
            criteriosTexto.Add(new TextoCriterio(TiposCriterios.EmpiezaPor, Properties.Resources.EmpiezaPor));
            criteriosTexto.Add(new TextoCriterio(TiposCriterios.TerminaEn, Properties.Resources.TerminaEn));

            criteriosNumero = new List<TextoCriterio>();
            criteriosNumero.Add(new TextoCriterio(TiposCriterios.Nada, ""));
            criteriosNumero.Add(new TextoCriterio(TiposCriterios.EsIgualA, Properties.Resources.EsIgualA));
            criteriosNumero.Add(new TextoCriterio(TiposCriterios.NoEsIgualA, Properties.Resources.NoEsIgualA));
            criteriosNumero.Add(new TextoCriterio(TiposCriterios.EsMayorQue, Properties.Resources.EsMayorQue));
            criteriosNumero.Add(new TextoCriterio(TiposCriterios.EsMayorOIgualQue, Properties.Resources.EsMayorOIgualQue));
            criteriosNumero.Add(new TextoCriterio(TiposCriterios.EsMenorQue, Properties.Resources.EsMenorQue));
            criteriosNumero.Add(new TextoCriterio(TiposCriterios.EsMenorOIgualQue, Properties.Resources.EsMenorOIgualQue));

            criteriosDominio = new List<TextoCriterio>();
            criteriosDominio.Add(new TextoCriterio(TiposCriterios.Nada, ""));
            criteriosDominio.Add(new TextoCriterio(TiposCriterios.EsIgualA, Properties.Resources.EsIgualA ));
            criteriosDominio.Add(new TextoCriterio(TiposCriterios.NoEsIgualA, Properties.Resources.NoEsIgualA ));
        }

        private void CreaControl(Atributo atributo, int num)
        {
            TableLayoutPanel panel = this.atributosPanel;
            
            // label
            Label label = new Label();
            if (atributo.Unidades != null)
            {
                label.Text = atributo.Nombre + " (" + atributo.Unidades + ") : ";
            }
            else
            {
                label.Text = atributo.Nombre + " : ";
            }
            label.Anchor = AnchorStyles.Bottom | AnchorStyles.Left | AnchorStyles.Right | AnchorStyles.Top;
            label.TextAlign = ContentAlignment.MiddleRight;
            panel.Controls.Add(label, 0, num);

            //Tooltip
            ToolTip toolTip = new ToolTip();
            toolTip.SetToolTip(label, atributo.Descripcion);

            //Campo de edición
            switch (atributo.TipoEdicion)
            {
                case TiposEdicion.Texto:
                    TextBox textBox = new TextBox();
                    textBox.Anchor = AnchorStyles.Bottom | AnchorStyles.Left | AnchorStyles.Right | AnchorStyles.Top;
                    textBox.Name = atributo.Codigo + "_Control";
                    textBox.TextAlign = HorizontalAlignment.Left;
                    //textBox.Tag = atributo;
                    panel.Controls.Add(textBox, 1, num);
                    break;
                case TiposEdicion.Entero:
                case TiposEdicion.Doble:
                    TextBox numBox = new TextBox();
                    numBox.Anchor = AnchorStyles.Bottom | AnchorStyles.Left | AnchorStyles.Right | AnchorStyles.Top;
                    numBox.Name = atributo.Codigo + "_Control";
                    numBox.TextAlign = HorizontalAlignment.Right;
                    numBox.LostFocus += new EventHandler(NumBoxValidate);
                    numBox.Tag = atributo;
                    panel.Controls.Add(numBox, 1, num);
                    break;
                case TiposEdicion.Combo:
                    ComboBox comboBox = new ComboBox();
                    comboBox.Anchor = AnchorStyles.Bottom | AnchorStyles.Left | AnchorStyles.Right | AnchorStyles.Top;
                    comboBox.Name = atributo.Codigo + "_Control";
                    comboBox.DropDownStyle = ComboBoxStyle.DropDownList;
                    comboBox.DisplayMember = "Texto";
                    comboBox.ValueMember = "Codigo";
                    comboBox.DataSource = ModComun.XSD.Dominios[atributo.NombreDominio].Valores;
                    //comboBox.Tag = atributo;
                    panel.Controls.Add(comboBox, 1, num);
                    break;
            }

            //Campo de criterio
            switch (atributo.TipoEdicion)
            {
                case TiposEdicion.Texto:
                    {
                        ComboBox comboBox = new ComboBox();
                        comboBox.Anchor = AnchorStyles.Bottom | AnchorStyles.Left | AnchorStyles.Right | AnchorStyles.Top;
                        comboBox.Name = atributo.Codigo + "_Criterio";
                        comboBox.DropDownStyle = ComboBoxStyle.DropDownList;
                        comboBox.DisplayMember = "Texto";
                        comboBox.ValueMember = "Tipo";
                        comboBox.DataSource = new List<TextoCriterio>(criteriosTexto);
                        panel.Controls.Add(comboBox, 2, num);
                        break;
                    }
                case TiposEdicion.Entero:
                case TiposEdicion.Doble:
                    {
                        ComboBox comboBox = new ComboBox();
                        comboBox.Anchor = AnchorStyles.Bottom | AnchorStyles.Left | AnchorStyles.Right | AnchorStyles.Top;
                        comboBox.Name = atributo.Codigo + "_Criterio";
                        comboBox.DropDownStyle = ComboBoxStyle.DropDownList;
                        comboBox.DisplayMember = "Texto";
                        comboBox.ValueMember = "Tipo";
                        comboBox.DataSource = new List<TextoCriterio>(criteriosNumero);
                        panel.Controls.Add(comboBox, 2, num);
                        break;
                    }
                case TiposEdicion.Combo:
                    {
                        ComboBox comboBox = new ComboBox();
                        comboBox.Anchor = AnchorStyles.Bottom | AnchorStyles.Left | AnchorStyles.Right | AnchorStyles.Top;
                        comboBox.Name = atributo.Codigo + "_Criterio";
                        comboBox.DropDownStyle = ComboBoxStyle.DropDownList;
                        comboBox.DisplayMember = "Texto";
                        comboBox.ValueMember = "Tipo";
                        comboBox.DataSource = new List<TextoCriterio>(criteriosDominio);
                        panel.Controls.Add(comboBox, 2, num);
                        break;
                    }
            }
        }

        private void CreaControlesDinamicos(Entidad entidad)
        {
            int nAtributos = 0;

            this.SuspendLayout();
            atributosPanel.Controls.Clear();

            foreach (Atributo atributo in entidad.Atributos)
                if (atributo.Codigo != ModComun.XSD.Clave)
                    CreaControl(atributo, nAtributos++);

            this.ResumeLayout(true);
        }

        void NumBoxValidate(object sender, EventArgs e)
        {
            if (inValidating) return;
            inValidating = true;
            TextBox tBox = sender as TextBox;
            if (tBox.Text.Length ==0) return;
            double dob = double.NegativeInfinity;
            try
            {
                dob = System.Convert.ToDouble(tBox.Text.Replace(',', '.'), System.Globalization.CultureInfo.InvariantCulture);
                if (((Atributo)tBox.Tag).TipoEdicion == TiposEdicion.Entero)
                    dob = Math.Round(dob);
                tBox.Text = dob.ToString(System.Globalization.CultureInfo.InvariantCulture);
            }
            catch(FormatException)
            {
                tBox.Focus();
                MessageBox.Show(System.String.Format(System.Globalization.CultureInfo.CurrentCulture, GMLC01HerramientasCad.Logica.Properties.Resources.ElAtributoDebeSerUnValorNumerico, ((Atributo)tBox.Tag).Nombre),
                    "GMLC", MessageBoxButtons.OK, MessageBoxIcon.Exclamation, MessageBoxDefaultButton.Button1, 0);
            }
            catch (OverflowException)
            {
                tBox.Focus();
                MessageBox.Show(System.String.Format(System.Globalization.CultureInfo.CurrentCulture, GMLC01HerramientasCad.Logica.Properties.Resources.ElAtributoDebeSerUnValorNumerico, ((Atributo)tBox.Tag).Nombre),
                    "GMLC", MessageBoxButtons.OK, MessageBoxIcon.Exclamation, MessageBoxDefaultButton.Button1, 0);
            }
            inValidating = false;
        }

        private void CancelarButtonClick(object sender, EventArgs e)
        {
            this.Close();
        }
        /// <summary>
        /// 
        /// </summary>
        public override void ActualizarIdiomaInterfaz()
        {
            try
            {
                base.ActualizarIdiomaInterfaz();

                this.toolTip1.SetToolTip(this.cancelarButton, Properties.Resources.CancelarTxt );
                this.toolTip1.SetToolTip(this.buscarButton, Properties.Resources.BuscarTxt);
                this.Text = Properties.Resources.BuscarSeleccionar + " (" + iEntidad.Codigo + ")"; ;
            }
            catch (Exception e)
            {
                Log.RegisterError(e);
                throw new ExcepcionGMLC(e.Message, e);
            }

        }

        private void BuscarButtonClick(object sender, EventArgs e)
        {
            //Operacion dummy para FxCop
            TextoCriterio dummy = new TextoCriterio(TiposCriterios.Nada, "");
            dummy.Texto = dummy.Texto;
            dummy.Tipo = dummy.Tipo;

            try
            {
                CriterioBusqueda criterio = new CriterioBusqueda();

                criterio.Criterios = new Collection<CriterioAtributo>();

                foreach (Atributo atr in iEntidad.Atributos)
                {
                    if (atr.Codigo == ModComun.XSD.Clave)
                        continue;

                    CriterioAtributo ca = new CriterioAtributo();

                    ca.Atributo = (Atributo)atr.Clone();
                    if (atr.TipoEdicion == TiposEdicion.Combo)
                        ca.Atributo.Valor = ((ComboBox)atributosPanel.Controls[atr.Codigo + "_Control"]).SelectedValue.ToString();
                    else
                        ca.Atributo.Valor = atributosPanel.Controls[atr.Codigo + "_Control"].Text;

                    ca.Tipo = ((TiposCriterios)((ComboBox)atributosPanel.Controls[atr.Codigo + "_Criterio"]).SelectedValue);
                    criterio.Criterios.Add(ca);
                }
                iCommIF.Buscar(criterio);
            }
            catch (ExcepcionGMLC)
            {
                throw;
            }
            catch (Exception excpt)
            {
                throw new ExcepcionGMLC(excpt.Message, excpt);
            }
        }
    }

    internal class TextoCriterio
    {
        public TextoCriterio(TiposCriterios tipo, String texto)
        {
            Tipo = tipo;
            Texto = texto;
        }

        public TiposCriterios Tipo { get; set; }
        public String Texto { get; set; }
    }
}