// Created with MonoDevelop
//
//    QuickStep: Acquire, view and identify spectra 
//    Copyright (C) 2017 Thomas Klose & Torsten Schache, 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 Hiperscan.PdfLib;
using Hiperscan.I18n;
using Hiperscan.Spectroscopy;
using System.IO;
using Hiperscan.Spectroscopy.IdentModule;
using System.Globalization;

namespace Hiperscan.Extensions.ApoIdent.Report
{
	public class GreatBritain : Hiperscan.Extensions.ApoIdent.Report.Generic
	{
        public GreatBritain(ReportInfo report_info) : base(report_info)
		{
		}

		protected override void CreateHeader()
		{
			this.Layout.SetFont(PdfFontTypes.HELVETICA, 14, PdfColors.Black);
			this.Layout.Feed(10);
			this.Layout.AddParagraph("Test report for identity verification of raw substances",		                    
			                         PdfTextAlignments.Center);	
			this.Layout.Feed(5);
		}
      
		protected override bool CreateAddressHeader()
        {
            this.Layout.Feed(30);

            this.Layout.SetFont(PdfFontTypes.HELVETICA_BOLD, this.ReferenceFontSize, PdfColors.Black);

			this.Text = String.Format("\nDate: {0}\nTest number: {1}",
                                      Locale.LocalizedDate(this.ReportInfo.Date, this.ReportInfo.Culture),
                                      this.ReportInfo.TestId);
         
            if (this.Layout.AddParagraph(this.Text, PdfTextAlignments.Right) == false)
                return false;

			this.Text = String.Format("{0}\n{1}, {2}\nOperator name: {3}",
                                      this.ReportInfo.Company,
                                      this.ReportInfo.Street,
                                      this.ReportInfo.Town,
                                      this.ReportInfo.User);

            if (this.Layout.AddParagraph(this.Text) == false)
                return false;

            this.Layout.Feed(this.Layout.ParagraphBoundingBox.Height + this.ReferenceLineDistance);
            return true;
        }
      
        protected override bool CreateSubstanceProperties()
        {
            this.Layout.Feed(this.ReferenceParagraphFeed * 1.5);
            this.Layout.SetFont(PdfFontTypes.HELVETICA_BOLD, this.ReferenceFontSize, PdfColors.Black);

            this.Layout.XPosition = 0;
			if (this.Layout.AddParagraph("Tested substance:") == false)
                return false;
            this.Layout.XPosition = this.ReferenceTabIndent;
            if (this.Layout.AddParagraph(this.GetSubstanceName()) == false)
                return false;
            this.Layout.SetFont(PdfFontTypes.HELVETICA, this.ReferenceFontSize, PdfColors.Black);
            this.Layout.Feed(this.Layout.ParagraphBoundingBox.Height + this.ReferenceLineDistance);
            if (this.Layout.AddParagraph(this.GetLatinName()) == false)
                return false;

            if (this.State.CurrentPage > 1)
            {
                this.Layout.Feed(this.Layout.ParagraphBoundingBox.Height + this.ReferenceLineDistance);
                return true;
            }

			this.Layout.Feed(this.Layout.ParagraphBoundingBox.Height + this.ReferenceLineDistance);
            this.Layout.XPosition = 0;
            if (this.Layout.AddParagraph("Manufacturer/Supplier:") == false)
                return false;
            this.Layout.XPosition = this.ReferenceTabIndent;
            if (this.Layout.AddParagraph(this.ReportInfo.Supplier) == false)
                return false;

            this.Layout.SetFont(PdfFontTypes.HELVETICA, this.ReferenceFontSize, PdfColors.Black);
            this.Layout.Feed(this.Layout.ParagraphBoundingBox.Height + this.ReferenceLineDistance);
            this.Layout.XPosition = 0;
			if (this.Layout.AddParagraph("Batch number:") == false)
                return false;
         
            this.Layout.XPosition = this.ReferenceTabIndent;
            this.Text = this.ReportInfo.Batch;
            if (String.IsNullOrEmpty(this.ReportInfo.Pzn) == false)
                this.Text += " " + String.Format("(PPN: {0})", this.ReportInfo.Pzn);
            if (this.Layout.AddParagraph(this.Text) == false)
                return false;
         
            this.Layout.Feed(this.Layout.ParagraphBoundingBox.Height + this.ReferenceLineDistance);
            this.Layout.XPosition = 0;
            if (this.Layout.AddParagraph(this.ReportInfo.Label.UseByDate) == false)
                return false;
            this.Layout.XPosition = this.ReferenceTabIndent;
            if (this.Layout.AddParagraph(Locale.LocalizedUseByDate(this.ReportInfo.ExpireDate, this.ReportInfo.Culture)) == false)
                return false;

            this.Layout.Feed(this.Layout.ParagraphBoundingBox.Height + this.ReferenceLineDistance);
            this.Layout.XPosition = 0;
			if (this.Layout.AddParagraph("Corr. factor weighing:") == false)
                return false;
            this.Layout.XPosition = this.ReferenceTabIndent;
            this.Text = this.ReportInfo.CorrectionFactor;
            if (String.IsNullOrWhiteSpace(this.Text))
                this.Text = "n/a";
            if (this.Layout.AddParagraph(this.Text) == false)
                return false;

            this.Layout.Feed(this.Layout.ParagraphBoundingBox.Height + this.ReferenceLineDistance);
            return true;
        }
      
        protected override bool CreateNirProperties()
        {

            if (this.ReportInfo.IsMeasurable == false)
                return true;

            this.Layout.Feed(this.ReferenceParagraphFeed);
            this.Layout.SetFont(PdfFontTypes.HELVETICA, this.ReferenceFontSize, PdfColors.Black);

            this.Layout.XPosition = 0;
			if (this.Layout.AddParagraph("Type of measurement:") == false)
                return true;
			this.Text = "Near-infrared spectroscopy (Ph. Eur 9.0/2.2.40) ";
			if (this.ReportInfo.SpectrumType == SpectrumType.ProcessedFluidSpecimen)
            {
				this.Text += "Liquids, transflectance";
            }
            else if (this.ReportInfo.SpectrumType == SpectrumType.ProcessedSolidSpecimen)
            {
                if (this.ReportInfo.ProbeType == ProbeType.FinderInsert ||
                    this.ReportInfo.ProbeType == ProbeType.FinderSDInsert)
					this.Text += "Solids, with sample insert";
                else
					this.Text += "Solids, diffuse reflectance";
            }
            this.Layout.XPosition = this.ReferenceTabIndent;
            if (this.Layout.AddParagraph(this.Text) == false)
                return true;


            this.Layout.Feed(this.Layout.ParagraphBoundingBox.Height + this.ReferenceLineDistance);
            this.Layout.XPosition = 0;
			if (this.Layout.AddParagraph("Instrument:") == false)
                return true;
            Text = String.Format("Name: {0}/serial number: {1}", this.ReportInfo.DeviceName, 
                                 this.ReportInfo.OemSerialNumber); 
            this.Layout.XPosition = this.ReferenceTabIndent;
            if (this.Layout.AddParagraph(this.Text) == false)
                return true;

            this.Layout.Feed(this.Layout.ParagraphBoundingBox.Height + this.ReferenceLineDistance);
            this.Layout.XPosition = 0;
			if (this.Layout.AddParagraph("Substance class:") == false)
                return true;
            Text = String.Format("{0}", this.ReportInfo.SubstanceClass);
            this.Layout.XPosition = this.ReferenceTabIndent;
            if (this.Layout.AddParagraph(this.Text) == false)
                return true;

            this.Layout.Feed(this.Layout.ParagraphBoundingBox.Height + this.ReferenceLineDistance);
            this.Layout.XPosition = 0;
            if (this.Layout.AddParagraph("Model:") == false)
                return true;

            this.Text = this.ReportInfo.Version;
            if (this.ReportInfo.AccessDatabaseType == AccessDatabaseType.Extension)
				this.Text += "(added)";
            this.Layout.XPosition = this.ReferenceTabIndent;
            if (this.Layout.AddParagraph(this.Text) == false)
                return true;

            this.Layout.Feed(this.Layout.ParagraphBoundingBox.Height + this.ReferenceLineDistance);
            this.Layout.XPosition = 0;
			if (this.Layout.AddParagraph("Sample/Substance ID:") == false)
                return true;
            this.Text = this.ReportInfo.MatchId + "/" + this.ReportInfo.SelectedSubstanceId;
            this.Layout.XPosition = this.ReferenceTabIndent;
            if (this.Layout.AddParagraph(this.Text) == false)
                return true;

            this.Layout.Feed(this.Layout.ParagraphBoundingBox.Height + this.ReferenceLineDistance);
            this.Layout.XPosition = 0;
			if (this.Layout.AddParagraph("Report file:") == false)
                return false;
            this.Layout.XPosition = this.ReferenceTabIndent;
            this.Text = Path.GetFileName(this.ReportInfo.PdfFileFullName);
            if (String.IsNullOrEmpty(this.Text) == true)
                this.Text = " ";
            if (this.Layout.AddParagraph(this.Text) == false)
                return false;

            this.Layout.Feed(this.Layout.ParagraphBoundingBox.Height + this.ReferenceLineDistance);
            return true;
        }

        protected override bool CreateCommentProperties()
        {
            this.Layout.Feed(this.ReferenceParagraphFeed);
            this.Layout.SetFont(PdfFontTypes.HELVETICA, this.ReferenceFontSize, PdfColors.Black);
            this.Layout.XPosition = 0;
            if (this.Layout.AddParagraph("Comment:") == false)
                return false;
            this.Layout.XPosition = this.ReferenceTabIndent;
            if (this.Layout.AddParagraph(this.ReportInfo.Comment) == false)
                return false;

            this.Layout.Feed(this.Layout.ParagraphBoundingBox.Height + this.ReferenceLineDistance);
            return true;
        }
      
		protected override bool CreateGraphics()
		{ 
			this.Layout.Feed(this.ReferenceParagraphFeed);
            if (this.ReportInfo.IsMeasurable == false)
			{
				if (this.Layout.AddHorizontalLine(0, this.Layout.YPosition, this.Layout.InnerPageWidth, 0.5f) == false)
					return false;
			}
			else
			{
				this.Layout.Feed(5);

				double padding = 1;
				int bitmap_save_width = (int)this.Layout.InnerPageWidth;
				int bitmap_save_height = (int) (0.8 * bitmap_save_width);
				double reference_width = this.Layout.InnerPageWidth / 2 - 2 * padding;

                DetailsPlot plot = new DetailsPlot(this.ReportInfo, false);
				plot.Dispose();

				PdfPoint point1 = new PdfPoint(padding, this.Layout.YPosition);
				System.Drawing.Bitmap bmp1 = plot.Plot1.GetBitmap(bitmap_save_width, bitmap_save_height);
				if (this.Layout.AddBitmap(bmp1, point1, PdfBitmapScales.X, reference_width) == false)
					return false;

				PdfPoint point2 = new PdfPoint(this.Layout.InnerPageWidth / 2 + padding, this.Layout.YPosition);
				System.Drawing.Bitmap bmp2 = plot.Plot2.GetBitmap(bitmap_save_width, bitmap_save_height);
				if (this.Layout.AddBitmap(bmp2, point2, PdfBitmapScales.X, reference_width) == false)
					return false;

				this.Layout.Feed(5 + this.Layout.ImageBoundingBox.Height);
			}
			return true;
		}

		protected override bool CreateNirResultSection()
		{
            if (this.ReportInfo.IsMeasurable == false)
				return true;

			bool success = true;

			if (this.ReportInfo.IsMatch == false)
			{
                switch(this.ReportInfo.ClassificationType)
				{
				case ClassificationType.Single:
					if (this.CreateSingleNegativeResult() == false)
						success = false;
					break;

				case ClassificationType.Multiple:
					if (this.CreateMultipleNegativeResult() == false)
						success = false;
					break;

				case ClassificationType.NonMultiple:
					if (this.CreateNonMultipleNegativeResult() == false)
						success = false;
					break;

				default:
					break;
				}
			}
			else
			{
                switch(this.ReportInfo.ClassificationType)
				{
				case ClassificationType.Single:
					if (this.CreateSinglePositiveResult() == false)
						success = false;
					break;

				case ClassificationType.Multiple:
					if (this.CreateMultiplePositiveResult() == false)
						success = false;
					break;

				case ClassificationType.NonMultiple:
					if (this.CreateNonMultiplePositiveResult() == false)
						success = false;
					break;

				default:
					break;
				}
			}

			return success;
		}

		protected override bool CreateSingleNegativeResult()
		{
			this.Layout.Feed(this.ReferenceParagraphFeed);
			this.Layout.SetFont(PdfFontTypes.HELVETICA_BOLD, this.ReferenceFontSize, PdfColors.Black);

			this.Layout.XPosition = 0;
			if (this.Layout.AddParagraph("Result NIRS:") == false)
				return false;

			double nir_width = this.Layout.MeasureString("Result NIRS:");
			this.Layout.XPosition = nir_width + 10;
			this.Text = "No match";
			if (this.Layout.AddParagraph(this.Text) == false)
				return false;

			double identified_width = this.Layout.MeasureString(this.Text);						
			if (this.Layout.AddHorizontalLine(this.Layout.XPosition, this.Layout.YPosition + 
				this.Layout.ParagraphBoundingBox.Height + 2, identified_width, 0.5) == false)
				return false;

			this.Layout.SetFont(PdfFontTypes.HELVETICA, this.ReferenceFontSize, PdfColors.Black);

			this.Layout.XPosition = this.ReferenceTabIndent;
			this.Text = "The sample has not been identified as:";
			if (this.Layout.AddParagraph(this.Text) == false)
				return false;

			this.Layout.Feed( this.Layout.ParagraphBoundingBox.Height);
			this.Layout.Feed(0.6 * this.ReferenceParagraphFeed);
            if (this.Layout.AddParagraph(this.GetSubstanceName()) == false)
				return false;

			if (this.AddNirEvaluation() == false)
				return false;

			this.Layout.Feed(this.Layout.ParagraphBoundingBox.Height + this.ReferenceLineDistance);

			return true;
		}

		protected override bool CreateSinglePositiveResult()
		{
			this.Layout.Feed(this.ReferenceParagraphFeed);
			this.Layout.SetFont(PdfFontTypes.HELVETICA_BOLD, this.ReferenceFontSize, PdfColors.Black);

			this.Layout.XPosition = 0;
			if (this.Layout.AddParagraph("Result NIRS:") == false)
				return false;

			double nir_width = this.Layout.MeasureString("Result NIRS:");

			this.Layout.XPosition = nir_width + 10;
			this.Text = "Match";
			if (this.Layout.AddParagraph(this.Text) == false)
				return false;

			double identified_width = this.Layout.MeasureString(this.Text);						
			if (this.Layout.AddHorizontalLine(this.Layout.XPosition, this.Layout.YPosition + 
				this.Layout.ParagraphBoundingBox.Height + 2, identified_width, 0.5) == false)
				return false;

			this.Layout.SetFont(PdfFontTypes.HELVETICA, this.ReferenceFontSize, PdfColors.Black);

			this.Layout.XPosition = this.ReferenceTabIndent;
			this.Text = "The sample has been identified as:";
			if (this.Layout.AddParagraph(this.Text) == false)
				return false;

			this.Layout.Feed( this.Layout.ParagraphBoundingBox.Height);
			this.Layout.Feed(0.6 * this.ReferenceParagraphFeed);
            if (this.Layout.AddParagraph(this.GetSubstanceName()) == false)
				return false;

			if (this.AddNirEvaluation() == false)
				return false;

			this.Layout.Feed(this.Layout.ParagraphBoundingBox.Height + this.ReferenceLineDistance);
			return true;
		}

		protected override bool CreateMultipleNegativeResult()
		{
			this.Layout.Feed(this.ReferenceParagraphFeed);
			this.Layout.SetFont(PdfFontTypes.HELVETICA_BOLD, this.ReferenceFontSize, PdfColors.Black);

			this.Layout.XPosition = 0;
			if (this.Layout.AddParagraph("Result NIRS:") == false)
				return false;

			double nir_width = this.Layout.MeasureString("Result NIRS:");
			this.Layout.XPosition = nir_width + 10;
			this.Text = "No match";
			if (this.Layout.AddParagraph(this.Text) == false)
				return false;

			double identified_width = this.Layout.MeasureString(this.Text);						
			if (this.Layout.AddHorizontalLine(this.Layout.XPosition, this.Layout.YPosition + 
				this.Layout.ParagraphBoundingBox.Height + 2, identified_width, 0.5) == false)
				return false;

			this.Layout.SetFont(PdfFontTypes.HELVETICA, this.ReferenceFontSize, PdfColors.Black);

			this.Layout.XPosition = this.ReferenceTabIndent;
			this.Text = "The sample has not been identified as:";
			if (this.Layout.AddParagraph(this.Text) == false)
				return false;

			this.Layout.Feed( this.Layout.ParagraphBoundingBox.Height);
			this.Layout.Feed(0.6 * this.ReferenceParagraphFeed);
            if (this.Layout.AddParagraph(this.GetSubstanceName()) == false)
				return false;

			if (this.AddNirEvaluation() == false)
				return false;

			this.Layout.Feed(this.Layout.ParagraphBoundingBox.Height + this.ReferenceLineDistance);
			return true;
		}

		protected override bool CreateMultiplePositiveResult()
		{
			this.Layout.Feed(this.ReferenceParagraphFeed);
			this.Layout.SetFont(PdfFontTypes.HELVETICA_BOLD, this.ReferenceFontSize, PdfColors.Black);

			this.Layout.XPosition = 0;
			if (this.Layout.AddParagraph("Result NIRS:") == false)
				return false;

			this.Layout.XPosition = this.ReferenceTabIndent;
			this.Text = String.Format("The sample has been identified as a substance within the group {0}*.", 
                                      this.ReportInfo.ClassificationName);
			if (this.Layout.AddParagraph(this.Text) == false)
				return false;

			if (this.AddNirEvaluation() == false)
				return false;

			this.Layout.Feed( this.Layout.ParagraphBoundingBox.Height);
			this.Layout.Feed(0.6 * this.ReferenceParagraphFeed);
			this.Text = "All other substances of the database have been excluded on the basis of the NIR spectrum. " +
				"The test result is only conclusive with additional tests which differentiates within the group.";
			if (this.Layout.AddParagraph(this.Text) == false)
				return false;

			this.Layout.SetFont(PdfFontTypes.HELVETICA_OBLIQUE, this.ReferenceFontSize, PdfColors.Black);
			this.Layout.Feed(this.Layout.ParagraphBoundingBox.Height + this.ReferenceLineDistance);
			this.Layout.Feed(0.6 * this.ReferenceParagraphFeed);
			if (this.Layout.AddParagraph("*") == false)
				return false;

			double asterisk_width = Layout.MeasureString("*") * 2;
			this.Layout.XPosition = this.ReferenceTabIndent + asterisk_width;
            this.Text = String.Join("; ", this.ReportInfo.SubstanceNamesOfClassification.ToArray());
			if (this.Layout.AddParagraph(this.Text) == false)
				return false;

			this.Layout.Feed(this.Layout.ParagraphBoundingBox.Height + this.ReferenceLineDistance);
			return true;
		}

		protected override bool CreateNonMultipleNegativeResult()
		{
			this.Layout.Feed(this.ReferenceParagraphFeed);
			this.Layout.SetFont(PdfFontTypes.HELVETICA_BOLD, this.ReferenceFontSize, PdfColors.Black);

			this.Layout.XPosition = 0;
			if (this.Layout.AddParagraph("Result NIRS:") == false)
				return false;

			double nir_width = this.Layout.MeasureString("Result NIRS:");
			this.Layout.XPosition = nir_width + 10;
			this.Text = "No match";
			if (this.Layout.AddParagraph(this.Text) == false)
				return false;

			double identified_width = this.Layout.MeasureString(this.Text);						
			if (this.Layout.AddHorizontalLine(this.Layout.XPosition, this.Layout.YPosition + 
				this.Layout.ParagraphBoundingBox.Height + 2, identified_width, 0.5) == false)
				return false;

			this.Layout.SetFont(PdfFontTypes.HELVETICA, this.ReferenceFontSize, PdfColors.Black);

			this.Layout.XPosition = this.ReferenceTabIndent;
			this.Text = String.Format("The sample has not been identified as a batch of the substance {0}*.", 
                                      this.ReportInfo.ClassificationName);
			if (this.Layout.AddParagraph(this.Text) == false)
				return false;

			if (this.AddNirEvaluation() == false)
				return false;

			this.Layout.SetFont(PdfFontTypes.HELVETICA_OBLIQUE, this.ReferenceFontSize, PdfColors.Black);
			this.Layout.Feed(this.Layout.ParagraphBoundingBox.Height + this.ReferenceLineDistance);
			this.Layout.Feed(0.6 * this.ReferenceParagraphFeed);
			if (this.Layout.AddParagraph("*") == false)
				return false;

			double asterisk_width = Layout.MeasureString("*") * 2;
			this.Layout.XPosition = this.ReferenceTabIndent + asterisk_width;
			this.Text = String.Format("The following batches of this substance are included in the database: {0}",
                                      String.Join("; ", this.ReportInfo.BatchNumbers.ToArray()));
			if (this.Layout.AddParagraph(this.Text) == false)
				return false;

			this.Layout.Feed(this.Layout.ParagraphBoundingBox.Height + this.ReferenceLineDistance);
			return true;
		}

		protected override bool CreateNonMultiplePositiveResult()
		{
			this.Layout.Feed(this.ReferenceParagraphFeed);
			this.Layout.SetFont(PdfFontTypes.HELVETICA_BOLD, this.ReferenceFontSize, PdfColors.Black);

			this.Layout.XPosition = 0;
			if (this.Layout.AddParagraph("Result NIRS:") == false)
				return false;

			double nir_width = this.Layout.MeasureString("Result NIRS:");

			this.Layout.XPosition = nir_width + 10;
			this.Text = "Match";
			if (this.Layout.AddParagraph(this.Text) == false)
				return false;

			double identified_width = this.Layout.MeasureString(this.Text);						
			if (this.Layout.AddHorizontalLine(this.Layout.XPosition, this.Layout.YPosition + 
				this.Layout.ParagraphBoundingBox.Height + 2, identified_width, 0.5) == false)
				return false;

			this.Layout.SetFont(PdfFontTypes.HELVETICA, this.ReferenceFontSize, PdfColors.Black);

			this.Layout.XPosition = this.ReferenceTabIndent;
			this.Text = String.Format("The sample has been identified as a batch of the substance {0}*.", 
                                      this.ReportInfo.ClassificationName);
			if (this.Layout.AddParagraph(this.Text) == false)
				return false;

			if (this.AddNirEvaluation() == false)
				return false;

			this.Layout.SetFont(PdfFontTypes.HELVETICA_OBLIQUE, this.ReferenceFontSize, PdfColors.Black);
			this.Layout.Feed(this.Layout.ParagraphBoundingBox.Height + this.ReferenceLineDistance);
			this.Layout.Feed(0.6 * this.ReferenceParagraphFeed);
			if (this.Layout.AddParagraph("*") == false)
				return false;

			double asterisk_width = Layout.MeasureString("*") * 2;
			this.Layout.XPosition = this.ReferenceTabIndent + asterisk_width;
			this.Text = String.Format("The following batches of this substance are included in the database: {0}",
                                      String.Join("; ", this.ReportInfo.BatchNumbers.ToArray()));
			if (this.Layout.AddParagraph(this.Text) == false)
				return false;

			this.Layout.Feed(this.Layout.ParagraphBoundingBox.Height + this.ReferenceLineDistance);
			return true;
		}

		protected override bool AddNirEvaluation()
		{
			this.Layout.Feed( this.Layout.ParagraphBoundingBox.Height);
			this.Layout.Feed(0.6 * this.ReferenceParagraphFeed);

			this.Layout.SetFont(PdfFontTypes.HELVETICA, this.ReferenceFontSize, PdfColors.Black);
            string min_rating 	= (this.ReportInfo.MinRating * 100).ToString("f1", this.Culture);
            string rating		= (this.ReportInfo.Rating * 100).ToString("f1", this.Culture);
			if (this.ReportInfo.IsMatch == false && min_rating == rating)
                rating = (this.ReportInfo.MinRating * 100 - 0.1).ToString("f1", this.Culture);
			this.Text = String.Format("Value: {0}% (limits {1}% to 100%)", rating, min_rating);
			if (this.Layout.AddParagraph(this.Text) == false)
				return false;

            if (this.ReportInfo.HasValidationDocument == true)
			{
                if (this.ReportInfo.ClassificationType == ClassificationType.NonMultiple ||
                    ApoIdentEnvs.DebugOn)
				{
                    string result = this.ReportInfo.SignificanceLevel;
					if (String.IsNullOrEmpty(result) == false)
					{
						this.Layout.Feed(this.Layout.ParagraphBoundingBox.Height + this.ReferenceLineDistance);

						string[] values = result.Split(new char[]{' '});
                        if (this.ReportInfo.IsMatch == true)
							this.Text = String.Format("{0} specificity ({1} statistical prediction)", values[0], values[1]);
						else
							this.Text = String.Format("{0} detection rate ({1} statistical prediction)", values[0], values[1]);

						if (this.Layout.AddParagraph(this.Text) == false)
							return false;
					}
				}

			}

			return true;
		}

		protected override bool CreateAdditionalTest()
		{
			this.Layout.Feed(this.ReferenceParagraphFeed * 1.5);
			this.Layout.SetFont(PdfFontTypes.HELVETICA, this.ReferenceFontSize, PdfColors.Black);

			double y_pos = this.Layout.YPosition; 
			double next_feed = 0;
			this.Layout.XPosition = 0;
            if (this.Layout.AddParagraph(this.SubstanceTestType) == false)
                return false;

            if (this.State.CurrentPage == 1 && this.State.IsSet(PdfCreationStates.CreateTwoSides) == true)
            {
                this.Layout.XPosition = this.ReferenceTabIndent;
                if (this.Layout.AddParagraph("See page 2") == false)
                    return false;

                this.Layout.Feed(this.Layout.ParagraphBoundingBox.Height + this.ReferenceLineDistance);
                return true;
            }

			this.Layout.Feed(this.Layout.ParagraphBoundingBox.Height + this.ReferenceLineDistance);
			if (this.Layout.AddParagraph("(Method and results)") == false)
				return false;

			this.Layout.Feed(this.Layout.ParagraphBoundingBox.Height + this.ReferenceLineDistance);
			next_feed = this.Layout.YPosition;

			this.Layout.YPosition = y_pos;

			this.Layout.XPosition = this.ReferenceTabIndent;

			if (String.IsNullOrEmpty(this.ReportInfo.AdditionalTest) == false)
			{
				if (this.Layout.AddParagraph(this.ReportInfo.AdditionalTest) == false)
					return false;

				this.Layout.Feed(this.Layout.ParagraphBoundingBox.Height + this.ReferenceLineDistance);
			}
			else
			{
                double width = this.Layout.InnerPageWidth - this.Layout.XPosition;

                for (int i = 0; i < this.NumberOfAdditionalTextLines; i++)
                {
					this.Layout.Feed(1.5 * Generic.DEFAULT_FEED);
                    if (this.Layout.AddHorizontalLine(this.Layout.XPosition, this.Layout.YPosition, width, 0.5) == false)
                        return false;
                }
			}

			if (this.Layout.YPosition < next_feed)
				this.Layout.YPosition = next_feed;
			return true;
		}

		protected override bool CreateFinalResult()
		{
            if (this.State.CurrentPage == 1 && this.State.IsSet(PdfCreationStates.CreateTwoSides) == true)
                return true;
            
            if (this.ReportInfo.ClassificationType != ClassificationType.Multiple && 
                this.ReportInfo.IsMeasurable == true	&&
				this.ReportInfo.IsMatch == true)
				return true;

			this.Layout.Feed(this.ReferenceParagraphFeed * 1.1);
			this.Layout.SetFont(PdfFontTypes.HELVETICA_BOLD, this.ReferenceFontSize, PdfColors.Black);

			this.Layout.XPosition = 0;
			if (this.Layout.AddParagraph("Conclusion:") == false)
				return false;

			this.Layout.SetFont(PdfFontTypes.HELVETICA, this.ReferenceFontSize, PdfColors.Black);
			this.Layout.XPosition = this.ReferenceTabIndent;
            this.Text = String.Format("{0} has been clearly identified.", this.GetSubstanceName());
			if (this.Layout.AddParagraph(this.Text) == false)
				return false;

			if (this.ReportInfo.CustomerResult == false)
			{
				this.Layout.Feed( this.Layout.ParagraphBoundingBox.Height * 1.6);

				PdfRect sqaure_yes = new PdfRect(this.ReferenceTabIndent, this.Layout.YPosition, 
					this.ReferenceFontSize, this.ReferenceFontSize);
				if (this.Layout.AddRectangle(sqaure_yes, 0.5, PdfColors.Black) == false)
					return false;

				this.Layout.YPosition -= 0.15 * this.ReferenceFontSize;
				this.Layout.XPosition = this.ReferenceTabIndent +  this.ReferenceFontSize * 1.2;
				if (this.Layout.AddParagraph("Yes") == false)
					return false;
				this.Layout.YPosition += 0.15 * this.ReferenceFontSize;

				double no_indent = 50;
				PdfRect sqaure_no = new PdfRect(this.ReferenceTabIndent + no_indent, this.Layout.YPosition, 
					this.ReferenceFontSize, this.ReferenceFontSize);
				if (this.Layout.AddRectangle(sqaure_no, 0.5, PdfColors.Black) == false)
					return false;

				this.Layout.YPosition -= 0.15 * this.ReferenceFontSize;
				this.Layout.XPosition = this.ReferenceTabIndent +  no_indent + this.ReferenceFontSize * 1.2;
				if (this.Layout.AddParagraph("No") == false)
					return false;
				this.Layout.YPosition += 0.15  * this.ReferenceFontSize;
			}

			this.Layout.Feed(this.Layout.ParagraphBoundingBox.Height + this.ReferenceLineDistance);
			return true;
		}

        protected override bool CreateTestCertificateSection()
        {
            if (this.State.CurrentPage == 1 && this.State.IsSet(PdfCreationStates.CreateTwoSides) == true)
                return true;

            this.Layout.Feed(this.ReferenceParagraphFeed * 1.1);
            this.Layout.SetFont(PdfFontTypes.HELVETICA_OBLIQUE, this.ReferenceFontSize, PdfColors.Black);

            this.Layout.XPosition = this.ReferenceTabIndent;
            if (this.Layout.AddParagraph("> Attach test certificate here or on the following page <") == false)
                return false;

            this.Layout.Feed(this.Layout.ParagraphBoundingBox.Height + 20 * Generic.DEFAULT_LINE_DISTANCE);
            return true;
        }

		protected override bool CreateSignature()
		{
			this.Layout.Feed(50);
			this.Layout.SetFont(PdfFontTypes.HELVETICA, this.ReferenceFontSize, PdfColors.Black);

			this.Layout.XPosition = 0;
			if (this.Layout.AddParagraph("Approved by:") == false)
				return false;

			this.Layout.Feed(this.ReferenceFontSize);

			double width = 150;

			this.Layout.XPosition = this.ReferenceTabIndent;
			if (this.Layout.AddHorizontalLine(this.Layout.XPosition, this.Layout.YPosition, width, 0.5) == false)
				return false;

			this.Layout.SetFont(PdfFontTypes.HELVETICA, 0.8 * this.ReferenceFontSize, PdfColors.Black);
			if (this.Layout.AddParagraph("Name", 150, PdfTextAlignments.Center) == false)
				return false;

			this.Layout.XPosition = Layout.InnerPageWidth - width;
			if (this.Layout.AddHorizontalLine(this.Layout.XPosition, this.Layout.YPosition, width, 0.5) == false)
				return false;

			this.Layout.SetFont(PdfFontTypes.HELVETICA, 0.8 * this.ReferenceFontSize, PdfColors.Black);
			if (this.Layout.AddParagraph("Date/Signature", 150, PdfTextAlignments.Center) == false)
				return false;

			this.Layout.Feed(this.Layout.ParagraphBoundingBox.Height + this.ReferenceLineDistance);
			return true;
		}

		protected override void CreateFooter()
		{
            this.Layout.SetFont(PdfFontTypes.HELVETICA_BOLD, 5, PdfColors.Black);

			this.Layout.YPosition = this.Layout.InnerPageHeight + 10;
			this.Layout.XPosition = 0;

			this.Text = String.Format("Page {0}", this.State.CurrentPage);
            this.Layout.AddFooter(this.Text, PdfTextAlignments.Right);

			this.Layout.SetFont(PdfFontTypes.HELVETICA, 5, PdfColors.Black);
            this.Layout.Feed(this.Layout.ParagraphBoundingBox.Height + 2);
         
            this.Layout.XPosition = 0;
            this.Text = String.Format("{0}\n{1}",
                                      PdfFooter.Copyright,
                                      "www.hiperscan.com");
            this.Layout.AddFooter(this.Text);

            this.Layout.XPosition = 120;
			this.Text = String.Format("QuickStep Apo-Ident {0}", Plugin.version);
            if (this.ReportInfo.IsMeasurable == false)
            {
                this.Layout.AddFooter(this.Text);
                return;
            }

            this.Text += String.Format("\n{0} {1}",
                                       "Identmodule",
                                       IdentServerClient.Info?.ShortIdentModuleVersion ?? String.Empty);
            this.Layout.AddFooter(this.Text);

            this.Layout.XPosition = 240;
            this.Text = String.Format("SGS: {0}\n{1}: {2}, PCA: {3}",
                                      this.ReportInfo.Serial,
                                      "White Reference",
                                      this.ReportInfo.WhiteReference,
                                      this.ReportInfo.PCAVersion); 
			this.Layout.AddFooter(this.Text);
		}

        protected override string SubstanceTestType
        {
            get
            {
                string test_type = String.Empty;

                if (this.ReportInfo.IsMeasurable == true)
                {
                    if (this.ReportInfo.IsMatch == true)
                    {
                        if (this.ReportInfo.ClassificationType == ClassificationType.Multiple)
                            test_type = "Complementary tests:";
                        else
                            test_type = "Additional tests:";
                    }
                    else
                    {
                        test_type = "Identity tests:";
                    }
                }
                else
                {
                    test_type = "Identity tests:";
                }

                return test_type;
            }
        }

        protected override CultureInfo Culture { get; set; } = new CultureInfo("en-GB");
    }
}