/// <summary>
 /// Agrega el Anexo de Condiciones Particulares a la plantilla de LaTeX indicada. Regresa el
 /// último índice de fila utilizado (actualiza el índice constantemente para buscar los placeholders).
 /// </summary>
 /// <typeparam name="T">El tipo de dato del lector escritor. Este método debería ser utilizado únicamente con los lectores/escritores de este espacio de nombres.</typeparam>
 /// <param name="lectorEscritor">El lector/escritor que utilizará este método para rellenar su plantilla correspondiente.</param>
 /// <param name="plantilla">Las filas de la plantilla leídas desde el archivo .tex.</param>
 /// <param name="anexo">Los datos del anexo de condiciones particulares.</param>
 /// <param name="noPoliza">El número de póliza.</param>
 /// <param name="indice">El índice de la fila de la plantilla a partir de la cual se empezará la búsqueda.</param>
 /// <returns>El último índice de fila utilizado.</returns>
 public static int RellenarAnexoCondiciones <T>(
     this T lectorEscritor,
     IList <string> plantilla,
     AnexoCondicionesParticularesCoaseguroResultSet anexo,
     string noPoliza,
     int indice)
 {
     return(RellenarAnexoCondicionesGenerico(plantilla, anexo, noPoliza, indice));
 }
 /// <summary>
 /// Genera una nueva instancia con el anexo y el encabezado indicados.
 /// </summary>
 /// <param name="anexo">Los datos del Anexo y Condiciones Particulares en Coaseguro.</param>
 /// <param name="encabezado">Los datos del encabezado del reporte.</param>
 /// <param name="rutaCompilador">La ruta absoluta al compilador (.exe) de LaTex.</param>
 /// <param name="inputDir">La ruta del directorio de multimedia de la plantilla.</param>
 public AnexoLectorEscritor(
     AnexoCondicionesParticularesCoaseguroResultSet anexo,
     EncabezadoReportesEmisionResultSet encabezado,
     string rutaCompilador,
     string inputDir)
     : base(rutaCompilador, inputDir)
 {
     this.anexo      = anexo;
     this.encabezado = encabezado;
 }
        /// <summary>
        /// Regresa el código para la tabla de porcentajes y montos de Fee por coaseguradora seguidora
        /// para la sección de Anexo de Condiciones Particulares.
        /// </summary>
        /// <param name="anexo">Los datos del anexo de condiciones particulares.</param>
        /// <returns>Una cadena con todo el código de la tabla.</returns>
        private static string ObtenerTablaFeeAnexo(AnexoCondicionesParticularesCoaseguroResultSet anexo)
        {
            var builder = new StringBuilder();

            foreach (var coas in anexo.Coaseguradoras)
            {
                builder.AppendLine($@"{coas.Coaseguradora} & {coas.PorcentajeFee.ToString("N2")} \% & \$ {coas.MontoFee.ToString("N2")}\\\hline");
            }

            return(builder.ToString());
        }
        /// <summary>
        /// Regresa el código para la sección de conceptos incluidos en el pago de comisión al agente para
        /// la sección de Anexo de Condiciones Particulares.
        /// </summary>
        /// <param name="anexo">Los datos del anexo de condiciones particulares.</param>
        /// <returns>Una cadena con el código de los conceptos.</returns>
        private static string ObtenerConceptosPagoComisionAgenteAnexo(AnexoCondicionesParticularesCoaseguroResultSet anexo)
        {
            var builder       = new StringBuilder();
            var primaNeta     = anexo.DatosEspecificos.PrimaNetaComisionAgente;
            var recargo       = anexo.DatosEspecificos.RecargoPagoFraccionado;
            var sobrecomision = anexo.DatosEspecificos.SobreComision;

            return(builder
                   .AppendLine($@"${(primaNeta ? @"\boxtimes" : @"\Box")}$ Prima Neta\\")
                   .AppendLine($@"\indent ${(recargo ? @"\boxtimes" : @"\Box")}$ Recargos por pago fraccionado\\")
                   .AppendLine($@"\indent ${(sobrecomision ? @"\boxtimes" : @"\Box")}$ Sobre comisión\\")
                   .ToString());
        }
        /// <summary>
        /// Regresa el código para la tabla de participación por sección/ramo para la sección de
        /// Anexo de Condiciones Particulares.
        /// </summary>
        /// <param name="anexo">Los datos del anexo de condiciones particulares.</param>
        /// <returns>Una cadena con todo el código de la tabla.</returns>
        private static string ObtenerTablaParticipacionAnexo(AnexoCondicionesParticularesCoaseguroResultSet anexo)
        {
            var builder = new StringBuilder(anexo.GMX.Ramo)
                          .AppendLine($@" & GRUPO MEXICANO DE SEGUROS, S.A. DE C.V. & {anexo.GMX.PorcentajeGMX.ToString("N2")} \% & Líder\\\hline");

            foreach (var coas in anexo.Coaseguradoras)
            {
                builder
                .Append($@"{coas.Ramo} & {coas.Coaseguradora} & ")
                .AppendLine($@"{coas.PorcentajeParticipacion.ToString("N2")} \% & Seguidor\\\hline");
            }

            return(builder.ToString());
        }
        /// <summary>
        /// Ejecuta el procedimiento sp_AnexoCondicionesParticularesCoaseguro() y
        /// regresa toda la información de éste.
        /// </summary>
        /// <param name="idPv">El Id de la póliza a buscar.</param>
        /// <returns>>Una nueva instancia de <see cref=""/>
        /// con los datos requeridos.</returns>
        public AnexoCondicionesParticularesCoaseguroResultSet ObtenerAnexoCondicionesParticulares(int idPv)
        {
            var rs = new AnexoCondicionesParticularesCoaseguroResultSet();
            var cmd = db.Database.Connection.CreateCommand();
            var paramIdPv = cmd.CreateParameter();

            cmd.CommandText = "EXEC sp_AnexoCondicionesParticularesCoaseguro @IdPv";
            paramIdPv.ParameterName = "@IdPv";
            paramIdPv.Value = idPv;
            cmd.Parameters.Add(paramIdPv);

            try {
                db.Database.Connection.Open();
                var reader = cmd.ExecuteReader();
                var context = (db as IObjectContextAdapter).ObjectContext;

                rs.DatosGenerales = context
                    .Translate<DatosGeneralesAnexoRS>(reader)
                    .FirstOrDefault() ?? new DatosGeneralesAnexoRS();

                // *** Posibles efectos secundarios
                // Translate<T>() por alguna razón no obtiene el campo 'Vigencia' del DbDataReader.
                // Por lo tanto, se obtiene el valor manualmente y se asigna al result set.
                rs.DatosGenerales.FechaVigencia = reader["Vigencia"] as DateTime?;

                reader.NextResult();
                rs.GMX = context
                    .Translate<GMXAnexoRS>(reader)
                    .FirstOrDefault() ?? new GMXAnexoRS();

                reader.NextResult();
                rs.Coaseguradoras = context
                    .Translate<CoaseguradorasAnexoRS>(reader)
                    .ToList();

                reader.NextResult();
                rs.DatosEspecificos = context
                    .Translate<DatosEspecificosAnexoRS>(reader)
                    .FirstOrDefault() ?? new DatosEspecificosAnexoRS();
            } catch {
                // TODO: Posible log
                throw;
            } finally {
                db.Database.Connection.Close();
            }

            return rs;
        }
        /// <summary>
        /// Agrega las condiciones específicas del anexo, ya que se utilizan varios checkboxes
        /// con sus respectivas condiciones.
        /// </summary>
        /// <param name="plantilla">La plantilla de LaTex.</param>
        /// <param name="anexo">Los datos del anexo de condiciones particulares.</param>
        /// <param name="indice">El último índice de la fila de la plantilla</param>
        private static void AgregarCondicionesEspecíficasAnexo(IList <string> plantilla, AnexoCondicionesParticularesCoaseguroResultSet anexo, int indice)
        {
            var newLine = Environment.NewLine;

            // Moneda
            var moneda = anexo.DatosEspecificos.Moneda;

            indice            = plantilla.FindIndex(linea => linea.Contains("<MONEDA>"), indice);
            plantilla[indice] =
                $@"${(moneda.Contains("NACIONAL") ? @"\boxtimes" : @"\Box")}$ Pesos Mexicanos (MXP)\\{newLine}"
                + $@"\indent ${(moneda.Contains("AMERICANO") ? @"\boxtimes" : @"\Box")}$ Dólares (USD)\\{newLine}";

            // Forma de Pago del Asegurado
            var formaPago = anexo.DatosEspecificos.FormaPago;

            indice            = plantilla.FindIndex(linea => linea.Contains("<FORMA-PAGO-ASEGURADO>"), indice);
            plantilla[indice] =
                $@"${(formaPago == "ANUAL" ? @"\boxtimes" : @"\Box")}$ Anual\\{newLine}"
                + $@"\indent ${(formaPago == "CONTADO" ? @"\boxtimes" : @"\Box")}$ Contado\\{newLine}"
                + $@"\indent ${(formaPago == "SEMESTRAL" ? @"\boxtimes" : @"\Box")}$ Semestral\\{newLine}"
                + $@"\indent ${(formaPago == "TRIMESTRAL" ? @"\boxtimes$" : @"\Box")}$ Trimestral\\{newLine}"
                + $@"\indent ${(formaPago == "MENSUAL" ? @"\boxtimes$" : @"\Box")}$ Mensual\\{newLine}";

            // Garantía de Pago
            var garantiaPago = anexo.DatosEspecificos.GarantiaPago;
            var son30Dias    = garantiaPago.Contains("Ley");

            indice = plantilla.FindIndex(linea => linea.Contains("<GARANTIA-PAGO>"), indice);

            plantilla[indice] =
                $@"${(son30Dias ? @"\boxtimes" : @"\Box")}$ De acuerdo a la Ley Sobre el Contrato de Seguro\\{newLine}"
                + $@"\indent ${(!son30Dias ? @"\boxtimes" : @"\Box")}$ Otro (especificar): \underline{{{(son30Dias ? @"\hspace{5cm}" : garantiaPago)}}}\\{newLine}";

            // Método de Pago
            var metodoPago     = anexo.DatosEspecificos.MetodoPago;
            var esEstadoCuenta = metodoPago == "Estado de Cuenta";

            indice            = plantilla.FindIndex(linea => linea.Contains("<METODO-PAGO>"), indice);
            plantilla[indice] =
                $@"${(esEstadoCuenta ? @"\boxtimes" : @"\Box")}$ {metodoPago}\\{newLine}"
                + $@"\indent ${(!esEstadoCuenta ? @"\boxtimes" : @"\Box")}$ Otro (especificar): \underline{{{(esEstadoCuenta ? @"\hspace{5cm}" : metodoPago)}}} \\{newLine}";

            // Pago de Comisión al Agente
            var comisionAgente = anexo.DatosEspecificos.PagoComisionAgente;
            var esLider100     = comisionAgente.Contains("100%");

            indice            = plantilla.FindIndex(linea => linea.Contains("<PAGO-COMISION-AGENTE>"), indice);
            plantilla[indice] =
                $@"${(esLider100 ? @"\boxtimes" : @"\Box")}$ La COASEGURADORA LÍDER paga el 100 \%\\{newLine}"
                + $@"\indent ${(!esLider100 ? @"\boxtimes" : @"\Box")}$ Cada COASEGURADORA paga su participación \\{newLine}";

            // Conceptos de Pago de Comisión al Agente
            indice            = plantilla.FindIndex(linea => linea.Contains("<CONCEPTOS-PAGO-COMISION-AGENTE>"), indice);
            plantilla[indice] = ObtenerConceptosPagoComisionAgenteAnexo(anexo);

            // Fees
            indice            = plantilla.FindIndex(linea => linea.Contains("<TABLA-ANEXO-FEE>"), indice);
            plantilla[indice] = ObtenerTablaFeeAnexo(anexo);

            // Siniestros e Indemnizaciones
            var formaIndemnizacion = anexo.DatosEspecificos.FormaIndemnizacion;

            indice = plantilla.FindIndex(linea => linea.Contains("<PAGO-SINIESTRO>"), indice);

            if (formaIndemnizacion == null)
            {
                plantilla[indice] =
                    $@"$\boxtimes$ Hasta el \underline{{{anexo.GMX.PorcentajeGMX.ToString("N2")}}} \% del límite de responsabilidad\\{newLine}"
                    + $@"\indent $\Box$ Hasta un límite máximo de \$\underline{{\hspace{{2cm}}}}";
            }
            else
            {
                if (formaIndemnizacion == "Monto")
                {
                    plantilla[indice] =
                        $@"$\Box$ Hasta el \underline{{\hspace{{2cm}}}} \% del límite de responsabilidad\\{newLine}"
                        + $@"\indent $\boxtimes$ Hasta un límite máximo de \$ \underline{{{anexo.DatosEspecificos.MontoSiniestro?.ToString("N2")}}}";
                }
                else
                {
                    plantilla[indice] =
                        $@"$\boxtimes$ Hasta el \underline{{{anexo.DatosEspecificos.PorcentajeSiniestro?.ToString("N2")}}} \% del límite de responsabilidad\\{newLine}"
                        + $@"\indent $\Box$ Hasta un límite máximo de \$\underline{{\hspace{{2cm}}}}";
                }
            }

            // Sucursal y Fecha de Emisión
            indice            = plantilla.FindIndex(linea => linea.Contains("<ANEXO-SUCURSAL>"), indice);
            plantilla[indice] = plantilla[indice]
                                .Replace("<ANEXO-SUCURSAL>", anexo.DatosEspecificos.Sucursal)
                                .Replace("<ANEXO-DIA>", anexo.DatosEspecificos.FechaEmision.Day.ToString().PadLeft(2, '0'))
                                .Replace("<ANEXO-MES>", anexo.DatosEspecificos.FechaEmision.ToString("MMMM", CultureInfo.GetCultureInfo("es-MX")))
                                .Replace("<ANEXO-ANIO>", anexo.DatosEspecificos.FechaEmision.Year.ToString());

            // Tabla de Firmas
            indice            = plantilla.FindIndex(linea => linea.Contains("<TABLA-FIRMAS>"), indice);
            plantilla[indice] = ObtenerTablaRepresentantes(anexo.Coaseguradoras.Select(coas => coas.Coaseguradora));
        }
        /// <summary>
        /// Agrega el Anexo de Condiciones Particulares a la plantilla de LaTeX indicada. Regresa el
        /// último índice de fila utilizado (actualiza el índice constantemente para buscar los placeholders).
        /// </summary>
        /// <param name="plantilla">Las filas de la plantilla leídas desde el archivo .tex.</param>
        /// <param name="anexo">Los datos del anexo de condiciones particulares.</param>
        /// <param name="noPoliza">El número de póliza.</param>
        /// <param name="indice">El índice de la fila de la plantilla a partir de la cual se empezará la búsqueda.</param>
        /// <returns>El último índice de fila utilizado.</returns>
        private static int RellenarAnexoCondicionesGenerico(IList <string> plantilla, AnexoCondicionesParticularesCoaseguroResultSet anexo, string noPoliza, int indice)
        {
            indice            = plantilla.FindIndex(linea => linea.Contains("<ASEGURADO>"), indice);
            plantilla[indice] = plantilla[indice]
                                .Replace("<ASEGURADO>", anexo.DatosGenerales.Asegurado);

            indice            = plantilla.FindIndex(linea => linea.Contains("<RFC>"), indice);
            plantilla[indice] = plantilla[indice]
                                .Replace("<RFC>", anexo.DatosGenerales.RFC);

            indice            = plantilla.FindIndex(linea => linea.Contains("<DOMICILIO-FISCAL>"), indice);
            plantilla[indice] = plantilla[indice]
                                .Replace("<DOMICILIO-FISCAL", anexo.DatosGenerales.DomicilioFiscal.Replace('|', ' '));

            indice            = plantilla.FindIndex(linea => linea.Contains("<GIRO>"), indice);
            plantilla[indice] = plantilla[indice]
                                .Replace("<GIRO>", anexo.DatosGenerales.Giro);

            indice            = plantilla.FindIndex(linea => linea.Contains("<NO-POLIZA>"), indice);
            plantilla[indice] = plantilla[indice]
                                .Replace("<NO-POLIZA>", noPoliza);

            indice            = plantilla.FindIndex(linea => linea.Contains("<VIGENCIA>"), indice);
            plantilla[indice] = plantilla[indice]
                                .Replace("<VIGENCIA>", anexo.DatosGenerales.FechaVigencia?.ToString("dd/MM/yyyy") ?? "Sin Vigencia");

            indice            = plantilla.FindIndex(linea => linea.Contains("<TABLA-ANEXO-PARTICIPACION-COASEGURADORAS>"), indice);
            plantilla[indice] = ObtenerTablaParticipacionAnexo(anexo);

            AgregarCondicionesEspecíficasAnexo(plantilla, anexo, indice);

            return(indice);
        }