using System;
using System.Collections.Generic;
using System.Text;

using GMLC01HerramientasCad.Logica;

using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.EditorInput;
using Autodesk.AutoCAD.Runtime;
using System.Globalization;

namespace GMLC01HerramientasCad.Acad
{
    class XData
    {
        private XData()
        {
        }

        public static Entidad GetXData(Autodesk.AutoCAD.DatabaseServices.ObjectId objId, string codigoEntidad)
        {
            string recordName = codigoEntidad.Split('.')[0];

            Entidad newEnt = null;
            Document doc = Application.DocumentManager.MdiActiveDocument;
            //Editor ed = doc.Editor;

            //Al ser las paletas algo NO MODAL, para evitar un "eLockViolation" se debe bloquear el documento.
            DocumentLock docLock = doc.LockDocument();
            using (docLock)
            {
                Transaction tr = doc.TransactionManager.StartTransaction();
                using (tr)
                {
                    DBObject obj = tr.GetObject(objId, OpenMode.ForRead);
                    ResultBuffer rb = obj.XData;
                    if (rb == null)
                    {
                        //ed.WriteMessage("\nEntity does not have XData attached.");
                        return null;
                    }
                    else
                    {
                        if (recordName == "*")
                        {
                            foreach (TypedValue tpv in rb.AsArray())
                            {
                                if (MyPlugin.modelLayers.Contains(tpv.Value.ToString().ToUpper(CultureInfo.CurrentCulture)))
                                {
                                    recordName = tpv.Value.ToString();
                                    break;
                                }
                            }
                        }

                        if (recordName != "*")
                        {
                            Entidad ent = ModComun.XSD.Entidades[recordName];

                            // Creación de la entidad de salida.
                            newEnt = new Entidad(ent.Codigo, ent.Nombres, ent.Descripciones, ent.TipoGeometria,
                                              ent.Categoria, ent.CampoSubTipo, ent.SubTipos, new ListaAtributos()); // new System.Collections.ObjectModel.Collection<atributo>());

                            foreach (TypedValue tv in rb)
                            {

                                if (tv.Value.ToString().StartsWith(recordName, StringComparison.OrdinalIgnoreCase) & tv.Value.ToString().Split('*').GetUpperBound(0) >= 2)
                                {
                                    //Este es un registro de la aplicación.
                                    if (tv.Value.ToString().Split('*')[0].ToString().ToUpper(CultureInfo.CurrentCulture) == recordName.ToUpper(CultureInfo.CurrentCulture))
                                    {

                                        Atributo att = null;
                                        foreach (Atributo at0 in ent.Atributos)
                                        {
                                            if (at0.Codigo.ToUpper(CultureInfo.CurrentCulture) == tv.Value.ToString().Split('*')[1].ToString().ToUpper(CultureInfo.CurrentCulture))
                                            {
                                                att = new Atributo(at0.Codigo, ent, at0.Nombres, at0.Descripciones, at0.TipoEdicion, tv.Value.ToString().Split('*')[2].ToString());
                                                att.Action = at0.Action;
                                            }
                                        }

                                        newEnt.Atributos.Add(att);
                                    }
                                }
                            }
                            rb.Dispose();
                        }
                        else
                        {
                            rb.Dispose();
                            return null;
                        }
                    }
                }
            }

            // Esto es por si ninguno de los atributos pertenecía al modelo (los HATCH los tienen).
            if (newEnt.Atributos.Count == 0) return null;

            return newEnt;

        }

        public static void SetXData(Autodesk.AutoCAD.DatabaseServices.ObjectId objId, Elemento elemento)
        {
            Document doc = Application.DocumentManager.MdiActiveDocument;
            //Editor ed = doc.Editor;

            string recordName = elemento.CodigoEntidad;

            //Al ser las paletas algo NO MODAL, para evitar un "eLockViolation" se debe bloquear el documento.
            DocumentLock docLock = doc.LockDocument();
            using (docLock)
            {
                Transaction tr = doc.TransactionManager.StartTransaction();
                using (tr)
                {
                    DBObject obj = tr.GetObject(objId, OpenMode.ForWrite);
                    AddRegAppTableRecord(recordName);
                    ResultBuffer rb = new ResultBuffer();
                    rb.Add(new TypedValue((int)DxfCode.ExtendedDataRegAppName, recordName));
                    foreach (Atributo atributo in elemento.Atributos)
                    {
                        string val = "" + atributo.Valor;
                        //En atributos numéricos, el separador de decimales será SIEMPRE el punto.
                        if ((atributo.TipoEdicion == TiposEdicion.Entero || atributo.TipoEdicion == TiposEdicion.Doble) && atributo.Valor != null) val = val.Replace(",", ".");
                        rb.Add(new TypedValue((int)DxfCode.ExtendedDataAsciiString, recordName + "*" + atributo.Codigo + "*" + val));
                    }
                    obj.XData = rb;
                    rb.Dispose();
                    tr.Commit();
                }
            }
        }

        private static void AddRegAppTableRecord(string regAppName)
        {
            Document doc = Application.DocumentManager.MdiActiveDocument;
            //Editor ed = doc.Editor;
            Database db = doc.Database;
            Transaction tr = doc.TransactionManager.StartTransaction();

            using (tr)
            {
                RegAppTable rat = (RegAppTable)tr.GetObject(db.RegAppTableId, OpenMode.ForRead, false);
                if (!rat.Has(regAppName))
                {
                    rat.UpgradeOpen();
                    RegAppTableRecord ratr = new RegAppTableRecord();
                    ratr.Name = regAppName;
                    rat.Add(ratr);
                    tr.AddNewlyCreatedDBObject(ratr, true);
                }
                tr.Commit();
            }

        }

    }
}
