// Created with MonoDevelop
//
//    QuickStep: Acquire, view and identify spectra 
//    Copyright (C) 2024 Hiperscan GmbH Dresden, Germany
//
//    This program is free software: you can redistribute it and/or modify
//    it under the terms of the GNU General Public License as published by
//    the Free Software Foundation, either version 3 of the License, or
//    (at your option) any later version.
//
//    This program is distributed in the hope that it will be useful,
//    but WITHOUT ANY WARRANTY; without even the implied warranty of
//    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//    GNU General Public License for more details.
//
//    You should have received a copy of the GNU General Public License
//    along with this program.  If not, see <http://www.gnu.org/licenses/>.


using System;
using System.Collections.Generic;
using Hiperscan.AnalysisModule.Identification.ValidationReportInfo;
using Hiperscan.ApoIdentCore.Reporting.Protocol.Footer;
using Hiperscan.ApoIdentCore.Reporting.ReportData;
using Hiperscan.PdfLib;

namespace Hiperscan.ApoIdentCore.Reporting.Protocol.Validation
{
    public class DeValidation
    {
        public DeValidation(PdfArgs args)
        {
            this.Args = args;
        }

        public void Draw()
        {
            this.CreateValidationHeader();
            this.CreateValidationTableResult();
            this.CreateValidationTestResult();
            this.CreateValidationDistanceTable();
            this.CreateValidationDemarcationTable();
        }

        private void CreateValidationHeader()
        {
            this.Layout.SetFont(PdfFontTypes.HELVETICA_BOLD, this.Args.ReferenceFontSize, PdfColors.Black);
            this.Text = "Validierungs-Informationen zum Datenbankeintrag";
            this.Layout.AddParagraph(this.Text);
            this.Layout.Feed(this.Layout.ParagraphBoundingBox.Height + 6 * this.Args.ReferenceLineDistance);


            this.Layout.SetFont(PdfFontTypes.HELVETICA, this.Args.ReferenceFontSize, PdfColors.Black);
            this.Text = "Substanz/Substanzgruppe:";
            this.Layout.AddParagraph(this.Text);

            double width = this.Layout.MeasureString(this.Text + " ");
            this.Layout.XPosition = width;
            this.Layout.SetFont(PdfFontTypes.HELVETICA_BOLD, this.Args.ReferenceFontSize, PdfColors.Black);
            this.Text = this.Info.ValidationReportInfo.ClassificationName;
            this.Layout.AddParagraph(this.Text);
            this.Layout.Feed(this.Layout.ParagraphBoundingBox.Height + 6 * this.Args.ReferenceLineDistance);


            this.Layout.XPosition = 0;
            this.Layout.SetFont(PdfFontTypes.HELVETICA, this.Args.ReferenceFontSize, PdfColors.Black);
            this.Text = "IdentModul:";
            this.Layout.AddParagraph(this.Text);

            width = this.Layout.MeasureString(this.Text + " ");
            this.Layout.XPosition = width;
            this.Layout.SetFont(PdfFontTypes.HELVETICA_BOLD, this.Args.ReferenceFontSize, PdfColors.Black);
            this.Text = this.Info.AnalysisModuleVersion;
            this.Layout.AddParagraph(this.Text);
            this.Layout.Feed(this.Layout.ParagraphBoundingBox.Height + 6 * this.Args.ReferenceLineDistance);
        }

        private void CreateValidationTableResult()
        {
            this.TableCells = new PdfTableStringCell[5, 5];

            for (int i = 0; i < this.TableCells.GetLength(0); i++)
            {
                for (int j = 0; j < TableCells.GetLength(1); j++)
                {
                    this.TableCells[i, j] = new PdfTableStringCell();
                    this.TableCells[i, j].FontSize = this.Args.ReferenceFontSize;

                    if (i == 0 || i == 1)
                        this.TableCells[i, j].FontType = PdfFontTypes.HELVETICA_BOLD;
                    else
                        this.TableCells[i, j].FontType = PdfFontTypes.HELVETICA;

                    if (j == 0)
                    {
                        this.TableCells[i, j].Align = PdfTextAlignments.Left;
                    }
                    else if (j == 1)
                    {
                        this.TableCells[i, j].Align = PdfTextAlignments.Center;
                    }
                    else
                    {
                        if (i == 1)
                        {
                            this.TableCells[i, j].Align = PdfTextAlignments.Center;
                        }
                        else
                        {
                            this.TableCells[i, j].Align = PdfTextAlignments.Center;
                        }
                    }
                }
            }

            ClassificationReportInfo val_info = this.Info.ValidationReportInfo;

            this.TableCells[0, 0].Value = "Validierungsergebnisse\n \n ";
            this.TableCells[0, 1].Value = " Anzahl\nunabhängiger\nProben";
            this.TableCells[0, 2].Value = "Falsch-\npositive\nErgebnis";
            this.TableCells[0, 3].Value = " \n \nSpezifität";
            this.TableCells[0, 4].Value = " \nErkennungs-\nrate";

            this.TableCells[1, 0].Value = "Kriterium";
            this.TableCells[1, 1].Value = " ";
            this.TableCells[1, 2].Value = "=0";
            this.TableCells[1, 3].Value = "=100%";
            this.TableCells[1, 4].Value = ">=85%";

            foreach (string substance in val_info.UsedBatchesTable.Substances.Keys)
            {
                string a_item = val_info.UsedBatchesTable.Substances[substance][ValidationTypes.A];
                this.NumberOfA_Batches += Int32.Parse(a_item);

                string b_item = val_info.UsedBatchesTable.Substances[substance][ValidationTypes.B];
                this.NumberOfB_Batches += Int32.Parse(b_item);

                string c_item = val_info.UsedBatchesTable.Substances[substance][ValidationTypes.C];
                this.NumberOfC_Batches += Int32.Parse(c_item);
            }

            this.TableCells[2, 0].Value = "Aufbau der Datenbank (Typ A)";
            this.TableCells[2, 1].Value = String.Format("{0} von {1}", this.NumberOfA_Batches, this.NumberOfA_Batches + this.NumberOfB_Batches);
            this.TableCells[2, 2].Value = val_info.ValidationsTable.FalsePositive[ValidationTypes.A];
            this.TableCells[2, 3].Value = val_info.StatisticsTable.Specifities[ValidationTypes.A];
            this.TableCells[2, 4].Value = val_info.StatisticsTable.DetectionRates[ValidationTypes.A];

            this.TableCells[3, 0].Value = "Validierung (Typ B)";
            this.TableCells[3, 1].Value = String.Format("{0} von {1}", this.NumberOfB_Batches, this.NumberOfA_Batches + this.NumberOfB_Batches);
            this.TableCells[3, 2].Value = val_info.ValidationsTable.FalsePositive[ValidationTypes.B];
            this.TableCells[3, 3].Value = val_info.StatisticsTable.Specifities[ValidationTypes.B];
            this.TableCells[3, 4].Value = val_info.StatisticsTable.DetectionRates[ValidationTypes.B];

            this.TableCells[4, 0].Value = "Felddaten zur Optimierung (Typ C)";
            this.TableCells[4, 1].Value = String.Format("{0}", this.NumberOfC_Batches);
            this.TableCells[4, 2].Value = val_info.ValidationsTable.FalsePositive[ValidationTypes.C];
            this.TableCells[4, 3].Value = val_info.StatisticsTable.Specifities[ValidationTypes.C];
            this.TableCells[4, 4].Value = val_info.StatisticsTable.DetectionRates[ValidationTypes.C];

            this.TableNumberOfColumns = this.TableCells.GetLength(1);
            this.TableColumnWidths = new double[this.TableNumberOfColumns];
            this.TableFirstColumnWidth = 170;

            double other_column_widths = this.Layout.InnerPageWidth - this.TableFirstColumnWidth;
            other_column_widths += (this.TableNumberOfColumns - 1) * this.TableBorderWidth;
            other_column_widths /= (this.TableNumberOfColumns - 1);
            this.TableColumnWidths[0] = this.TableFirstColumnWidth;
            for (int i = 1; i < this.TableNumberOfColumns; i++)
                this.TableColumnWidths[i] = other_column_widths;

            this.Table = new PdfTable(this.Layout,
                                      this.TableCells,
                                      this.TableColumnWidths,
                                      this.TableTopCellPadding,
                                      this.TableBottomCellPadding,
                                      this.TableBorderWidth);

            double y_pos_table = this.Table.Draw(0, this.Layout.YPosition, PdfColors.Black);

            this.Layout.Feed(this.Layout.ParagraphBoundingBox.Height + 9 * this.Args.ReferenceLineDistance);
        }

        private void CreateValidationTestResult()
        {
            this.Layout.XPosition = 0;
            this.Layout.SetFont(PdfFontTypes.HELVETICA_BOLD, this.Args.ReferenceFontSize, PdfColors.Black);
            this.Text = (this.NumberOfA_Batches + this.NumberOfB_Batches).ToString();
            this.Layout.AddParagraph(this.Text);

            double width = this.Layout.MeasureString(this.Text + " ");
            this.Layout.SetFont(PdfFontTypes.HELVETICA, this.Args.ReferenceFontSize, PdfColors.Black);
            this.Layout.XPosition = width;
            this.Text = "unabhängige Proben (aus unterschiedlichen Chargen) wurden verwendet,";
            this.Layout.AddParagraph(this.Text);
            this.Layout.Feed(this.Layout.ParagraphBoundingBox.Height + this.Args.ReferenceLineDistance);

            this.Layout.XPosition = 0;
            this.Layout.SetFont(PdfFontTypes.HELVETICA_BOLD, this.Args.ReferenceFontSize, PdfColors.Black);
            this.Text = (this.NumberOfA_Batches).ToString();
            this.Layout.AddParagraph(this.Text);

            width = this.Layout.MeasureString(this.Text + " ");
            this.Layout.SetFont(PdfFontTypes.HELVETICA, this.Args.ReferenceFontSize, PdfColors.Black);
            this.Layout.XPosition = width;
            this.Text = "davon für den Aufbau der Datenbank";
            this.Layout.AddParagraph(this.Text);

            width = this.Layout.MeasureString(this.Text + " ");
            this.Layout.SetFont(PdfFontTypes.HELVETICA_BOLD, this.Args.ReferenceFontSize, PdfColors.Black);
            this.Layout.XPosition += width;
            this.Text = "(Typ A)";
            this.Layout.AddParagraph(this.Text);
            this.Layout.Feed(this.Layout.ParagraphBoundingBox.Height + this.Args.ReferenceLineDistance);


            this.Layout.XPosition = 0;
            this.Layout.SetFont(PdfFontTypes.HELVETICA_BOLD, this.Args.ReferenceFontSize, PdfColors.Black);
            this.Text = (this.NumberOfB_Batches).ToString();
            this.Layout.AddParagraph(this.Text);

            width = this.Layout.MeasureString(this.Text + " ");
            this.Layout.SetFont(PdfFontTypes.HELVETICA, this.Args.ReferenceFontSize, PdfColors.Black);
            this.Layout.XPosition = width;
            this.Text = "davon für die Validierung";
            this.Layout.AddParagraph(this.Text);

            width = this.Layout.MeasureString(this.Text + " ");
            this.Layout.SetFont(PdfFontTypes.HELVETICA_BOLD, this.Args.ReferenceFontSize, PdfColors.Black);
            this.Layout.XPosition += width;
            this.Text = "(Typ B)";
            this.Layout.AddParagraph(this.Text);
            this.Layout.Feed(this.Layout.ParagraphBoundingBox.Height + 6 * this.Args.ReferenceLineDistance);

            this.Layout.SetFont(PdfFontTypes.HELVETICA, this.Args.ReferenceFontSize, PdfColors.Black);
            this.Layout.XPosition = 0;
            this.Text = String.Format("{0} Chargen-Nummern wurden bei Messungen im Feld angegeben (Typ C). " +
                                      "Diese dienten zur Optimierung der Spezifität und zur Sicherstellung " +
                                      "und Kontrolle der Robustheit.", this.NumberOfC_Batches);
            this.Layout.AddParagraph(this.Text);
            this.Layout.Feed(this.Layout.ParagraphBoundingBox.Height + 12 * this.Args.ReferenceLineDistance);
        }

        private void CreateValidationDistanceTable()
        {
            this.Layout.XPosition = 0;
            this.Layout.SetFont(PdfFontTypes.HELVETICA_BOLD, this.Args.ReferenceFontSize, PdfColors.Black);
            this.Text = "Abgrenzung zu verwandten Arzneibuch-Substanzen und Abstand zur nächsten Fremdprobe M>=9";
            this.Layout.AddParagraph(this.Text);
            this.Layout.Feed(this.Layout.ParagraphBoundingBox.Height + 6 * this.Args.ReferenceLineDistance);

            this.Layout.XPosition = 0;
            this.Layout.SetFont(PdfFontTypes.HELVETICA, this.Args.ReferenceFontSize, PdfColors.Black);
            this.Text = "Die drei nächsten chemometrischen Nachbarn (mit den ähnlichsten Spektren) sind:";
            this.Layout.AddParagraph(this.Text);
            this.Layout.Feed(this.Layout.ParagraphBoundingBox.Height + 6 * this.Args.ReferenceLineDistance);

            ClassificationReportInfo val_info = this.Info.ValidationReportInfo;
            this.TableFirstColumnWidth = 130;
            int i = 0;

            foreach (string substance_name in val_info.DistancesTable.Distances.Keys)
            {
                double tmp = this.Layout.MeasureString(substance_name);
                if (tmp > this.TableFirstColumnWidth)
                    this.TableFirstColumnWidth = tmp;

                i++;
                if (i == 3)
                    break;
            }

            this.TableFirstColumnWidth += 5;

            this.TableCells = new PdfTableStringCell[1, 3];
            this.TableCells[0, 0] = new PdfTableStringCell();
            this.TableCells[0, 0].FontType = PDFjet.NET.CoreFont.HELVETICA_BOLD;
            this.TableCells[0, 0].FontSize = this.Args.ReferenceFontSize;
            this.TableCells[0, 0].Align = PdfTextAlignments.Left;
            this.TableCells[0, 0].Value = "Substanz\n ";
            this.TableCells[0, 1] = new PdfTableStringCell();
            this.TableCells[0, 1].FontType = PDFjet.NET.CoreFont.HELVETICA_BOLD;
            this.TableCells[0, 1].FontSize = this.Args.ReferenceFontSize;
            this.TableCells[0, 1].Align = PdfTextAlignments.Right;
            this.TableCells[0, 1].Value = "Abstand im\nHauptmodell";
            this.TableCells[0, 2] = new PdfTableStringCell();
            this.TableCells[0, 2].FontType = PDFjet.NET.CoreFont.HELVETICA_BOLD;
            this.TableCells[0, 2].FontSize = this.Args.ReferenceFontSize;
            this.TableCells[0, 2].Align = PdfTextAlignments.Right;
            this.TableCells[0, 2].Value = "Abstand im\nZweite-Stufe-Modell";


            double other_column_width = 100;
            double indent = (this.Layout.InnerPageWidth - this.TableFirstColumnWidth - 2 * other_column_width) / 2;
            double line_extension = 6;

            if (indent < line_extension / 2)
            {
                this.TableFirstColumnWidth = this.Layout.InnerPageWidth - 2 * other_column_width - line_extension;
                indent = line_extension / 2;
            }


            double line_width = this.TableFirstColumnWidth + 2 * other_column_width + line_extension;

            this.Layout.AddHorizontalLine(indent - line_extension / 2,
                                          this.Layout.YPosition + 2,
                                          line_width,
                                          this.TableBorderWidth,
                                          PdfColors.Black);

            this.TableNumberOfColumns = this.TableCells.GetLength(1);
            this.TableColumnWidths = new double[this.TableNumberOfColumns];
            this.TableColumnWidths[0] = this.TableFirstColumnWidth;
            this.TableColumnWidths[1] = other_column_width;
            this.TableColumnWidths[2] = other_column_width;

            this.Table = new PdfTable(this.Layout,
                                           this.TableCells,
                                           this.TableColumnWidths,
                                           this.TableTopCellPadding,
                                           this.TableBottomCellPadding,
                                           0);

            double y_pos_table = this.Table.Draw(indent,
                                            this.Layout.YPosition,
                                            PdfColors.Black);

            this.Layout.AddHorizontalLine(indent - line_extension / 2,
                                          y_pos_table + 1,
                                          line_width,
                                          this.TableBorderWidth,
                                          PdfColors.Black);


            i = 0;

            foreach (string substance_name in val_info.DistancesTable.Distances.Keys)
            {
                this.TableCells = new PdfTableStringCell[1, 3];

                this.TableCells[0, 0] = new PdfTableStringCell();
                this.TableCells[0, 0].FontType = PDFjet.NET.CoreFont.HELVETICA;
                this.TableCells[0, 0].FontSize = this.Args.ReferenceFontSize;
                this.TableCells[0, 0].Align = PdfTextAlignments.Left;
                this.TableCells[0, 0].Value = substance_name;

                this.TableCells[0, 1] = new PdfTableStringCell();
                this.TableCells[0, 1].FontType = PDFjet.NET.CoreFont.HELVETICA;
                this.TableCells[0, 1].FontSize = this.Args.ReferenceFontSize;
                this.TableCells[0, 1].Align = PdfTextAlignments.Right;
                this.TableCells[0, 1].Value = val_info.DistancesTable.Distances[substance_name].MainModel;

                this.TableCells[0, 2] = new PdfTableStringCell();
                this.TableCells[0, 2].FontType = PDFjet.NET.CoreFont.HELVETICA;
                this.TableCells[0, 2].FontSize = this.Args.ReferenceFontSize;
                this.TableCells[0, 2].Align = PdfTextAlignments.Right;
                this.TableCells[0, 2].Value = val_info.DistancesTable.Distances[substance_name].SecondModel;

                this.Table = new PdfTable(this.Layout,
                                          this.TableCells,
                                          this.TableColumnWidths,
                                          this.TableTopCellPadding,
                                          this.TableBottomCellPadding - 2,
                                          0);



                y_pos_table = this.Table.Draw(indent,
                                         y_pos_table,
                                         PdfColors.Black);

                i++;
                if (i == 3)
                    break;
            }

            this.Layout.AddHorizontalLine(indent - line_extension / 2,
                                          y_pos_table + this.TableTopCellPadding,
                                          line_width,
                                          this.TableBorderWidth,
                                          PdfColors.Black);

            this.Layout.Feed(this.Layout.ParagraphBoundingBox.Height + 9 * this.Args.ReferenceLineDistance);

            this.Layout.XPosition = 0;
            this.Layout.SetFont(PdfFontTypes.HELVETICA, this.Args.ReferenceFontSize, PdfColors.Black);
            this.Text = "Erreicht der Mahalanobis-Abstand im Hauptmodell nicht M >= 9, kann ein " +
                "Zweite-Stufe-Modell mit M>=9 die Abgrenzung zwischen den beiden Substanzen doch " +
                "noch sicherstellen (\"grüne Substanz\"). (Der Abstand in der ersten Stufe ist dann nicht von Belang).";
            this.Layout.AddParagraph(this.Text);
            this.Layout.Feed(this.Layout.ParagraphBoundingBox.Height + 6 * this.Args.ReferenceLineDistance);

            this.Text = "Alternativ kommen die nicht sicher abgrenzbaren Substanzen in eine Gruppe (\"gelbe Substanz\").";
            this.Layout.AddParagraph(this.Text);
            this.Layout.Feed(this.Layout.ParagraphBoundingBox.Height + 6 * this.Args.ReferenceLineDistance);

            if (this.Info.ValidationReportInfo.DemarcationsTable.Entries.Count == 0)
                this.CreateFooter();

        }

        private void CreateValidationDemarcationTable(int index = 0)
        {
            if (this.Info.ValidationReportInfo.DemarcationsTable.Entries.Count == 0)
                return;

            if (index == 0)
            {
                this.Layout.XPosition = 0;
                this.Layout.SetFont(PdfFontTypes.HELVETICA, this.Args.ReferenceFontSize, PdfColors.Black);
                this.Text = "Zur vereinfachten Kontrolle ist in der folgenden Tabelle für einige verwandte Substanzen angegeben, wie " +
                    "die Abgrenzung überprüft wird:";
                this.Layout.AddParagraph(this.Text);
                this.Layout.Feed(this.Layout.ParagraphBoundingBox.Height + 6 * this.Args.ReferenceLineDistance);
            }
            else
            {
                this.Layout.XPosition = 0;
                this.Layout.SetFont(PdfFontTypes.HELVETICA, this.Args.ReferenceFontSize, PdfColors.Black);
                this.Text = "Fortsetung der Abgrenzungstabelle:";
                this.Layout.AddParagraph(this.Text);
                this.Layout.Feed(this.Layout.ParagraphBoundingBox.Height + 6 * this.Args.ReferenceLineDistance);
            }




            ClassificationReportInfo val_info = this.Info.ValidationReportInfo;
            double width = this.Layout.MeasureString("Art der Abgrenzung");
            foreach (string entry in val_info.DemarcationsTable.Entries.Values)
            {
                double tmp = this.Layout.MeasureString(entry);
                if (tmp > width)
                    width = tmp;
            }
            width += 5;

            this.TableCells = new PdfTableStringCell[1, 2];
            this.TableCells[0, 0] = new PdfTableStringCell();
            this.TableCells[0, 0].FontType = PDFjet.NET.CoreFont.HELVETICA_BOLD;
            this.TableCells[0, 0].FontSize = this.Args.ReferenceFontSize;
            this.TableCells[0, 0].Align = PdfTextAlignments.Left;
            this.TableCells[0, 0].Value = "Substanz";
            this.TableCells[0, 1] = new PdfTableStringCell();
            this.TableCells[0, 1].FontType = PDFjet.NET.CoreFont.HELVETICA_BOLD;
            this.TableCells[0, 1].FontSize = this.Args.ReferenceFontSize;
            this.TableCells[0, 1].Align = PdfTextAlignments.Left;
            this.TableCells[0, 1].Value = "Art der Abgrenzung";


            this.TableFirstColumnWidth = this.Layout.InnerPageWidth - width;

            this.Layout.AddHorizontalLine(0,
                                          this.Layout.YPosition + 2,
                                          this.Layout.InnerPageWidth,
                                          this.TableBorderWidth,
                                          PdfColors.Black);

            this.TableNumberOfColumns = this.TableCells.GetLength(1);
            this.TableColumnWidths = new double[this.TableNumberOfColumns];
            this.TableColumnWidths[0] = this.TableFirstColumnWidth;
            this.TableColumnWidths[1] = width;

            this.Table = new PdfTable(this.Layout,
                                      this.TableCells,
                                      this.TableColumnWidths,
                                      this.TableTopCellPadding,
                                      this.TableBottomCellPadding,
                                      0);

            double y_pos_table = this.Table.Draw(0,
                                                 this.Layout.YPosition,
                                                 PdfColors.Black);

            this.Layout.AddHorizontalLine(0,
                                          y_pos_table + 1,
                                          this.Layout.InnerPageWidth,
                                          this.TableBorderWidth,
                                          PdfColors.Black);

            List<string> substances = new List<string>(val_info.DemarcationsTable.Entries.Keys);

            int next_index = -1;


            for (int i = index; i < substances.Count; i++)
            {
                try
                {
                    string substance_name = substances[i];

                    this.TableCells = new PdfTableStringCell[1, 2];

                    this.TableCells[0, 0] = new PdfTableStringCell();
                    this.TableCells[0, 0].FontType = PDFjet.NET.CoreFont.HELVETICA;
                    this.TableCells[0, 0].FontSize = this.Args.ReferenceFontSize;
                    this.TableCells[0, 0].Align = PdfTextAlignments.Left;
                    this.TableCells[0, 0].Value = substance_name;

                    this.TableCells[0, 1] = new PdfTableStringCell();
                    this.TableCells[0, 1].FontType = PDFjet.NET.CoreFont.HELVETICA;
                    this.TableCells[0, 1].FontSize = this.Args.ReferenceFontSize;
                    this.TableCells[0, 1].Align = PdfTextAlignments.Left;
                    this.TableCells[0, 1].Value = val_info.DemarcationsTable.Entries[substance_name];

                    this.Table = new PdfTable(this.Layout,
                                              this.TableCells,
                                              this.TableColumnWidths,
                                              this.TableTopCellPadding,
                                              this.TableBottomCellPadding - 2,
                                              0);

                    y_pos_table = this.Table.Draw(0,
                                             y_pos_table,
                                             PdfColors.Black);
                }
                catch (PdfLayoutException)
                {
                    next_index = i;
                    break;
                }
            }

            this.Layout.AddFooterHorizontalLine(0,
                                          y_pos_table + this.TableTopCellPadding,
                                          this.Layout.InnerPageWidth,
                                          this.TableBorderWidth,
                                          PdfColors.Black);

            this.CreateFooter();

            if (next_index != -1)
                this.AppendValidationPage(next_index);
        }

        private void AppendValidationPage(int index)
        {
            this.Layout.AddNewPage();

            this.Args.State.CurrentPage++;
            if (this.Args.State.IsSet(PdfCreationStates.TryMode))
                this.Args.State.TotalPages++;

            this.Layout.YPosition = 0;
            this.Layout.XPosition = 0;

            this.CreateValidationHeader();
            this.CreateValidationDemarcationTable(index);

            this.CreateFooter();
        }

        private void CreateFooter()
        {
            CommonFooter footer = new CommonFooter();
            footer.Draw(this.Args);
        }

        private Layout Layout
        {
            get
            {
                return this.Args.Layout;
            }
        }

        private ReportInfo Info
        {
            get
            {
                return this.Args.Info;
            }
        }

        private int NumberOfA_Batches { get; set; } = 0;
        private int NumberOfB_Batches { get; set; } = 0;
        private int NumberOfC_Batches { get; set; } = 0;

        private PdfTable Table { get; set; }
        private PdfTableStringCell[,] TableCells { get; set; }
        private double TableBorderWidth { get; set; } = 0.5;
        private double TableFirstColumnWidth { get; set; } = 0;
        private double TableTopCellPadding { get; set; } = 2;
        private double TableBottomCellPadding { get; set; } = 4;
        private double[] TableColumnWidths { get; set; }
        private int TableNumberOfColumns { get; set; }

        private PdfArgs Args { get; set; }
        private string Text { get; set; }
    }
}
