using Ato.CD.Inbound.Shared;
using Ato.EN.IntegrationServices.CodeGenerationCGNFT;
using Ato.EN.IntegrationServices.CodeGenerationCTR;
using Ato.EN.IntegrationServices.CodeGenerationDIS;
using Ato.EN.IntegrationServices.CodeGenerationDISTBENTRT;
using Ato.EN.IntegrationServices.CodeGenerationIDS;
using Ato.EN.IntegrationServices.CodeGenerationIEE;
using Ato.EN.IntegrationServices.CodeGenerationPSS;
using Ato.EN.IntegrationServices.CodeGenerationRDTIS;
using Ato.EN.IntegrationServices.CodeGenerationRPTTAXPOS;
using VaTS;
using DataContracts;
using System;
using System.Collections.Generic;
using System.Linq;

namespace Ato.CD.Inbound.CTR202502
{
    public class CrossFormValidator
    {
        private CTR2025 ParentDocument { get; }
        private BusinessDocumentCollection ChildDocuments { get; }
        private IEnumerable<IEE2021> IEEChildDocuments { get; }
        private IEnumerable<DIS2018> DISChildDocuments { get; }
        private IEnumerable<CGNFT2018> CGNFTChildDocuments { get; }
        private IEnumerable<IDS2025> IDSChildDocuments { get; }
        private IEnumerable<RDTIS2023> RDTISChildDocuments { get; }
        private IEnumerable<RPTTAXPOS2019> RPTTAXPOSChildDocuments { get; }
        private IEnumerable<DISTBENTRT2024> DISTBENTRTChildDocuments { get; }
        public List<ProcessMessageDocument> response { get; private set; }
        public CrossFormValidator(CTR2025 report, BusinessDocumentCollection childDocuments)
        {
            ParentDocument = report;
            ChildDocuments = childDocuments ?? new BusinessDocumentCollection();
            IEEChildDocuments = ChildDocuments
                 .Where(s => s.DocumentName.Equals(Schedule.IEE.ToString()))
                 .Select(p => (IEE2021)p.ConsumedReport);
            DISChildDocuments = ChildDocuments
                 .Where(s => s.DocumentName.Equals(Schedule.DIS.ToString()))
                 .Select(p => (DIS2018)p.ConsumedReport);
            CGNFTChildDocuments = ChildDocuments
                .Where(s => s.DocumentName.Equals(Schedule.CGNFT.ToString()))
                .Select(p => (CGNFT2018)p.ConsumedReport);

            IDSChildDocuments = ChildDocuments
               .Where(s => s.DocumentName.Equals(Schedule.IDS.ToString()))
               .Select(p => (IDS2025)p.ConsumedReport);

            RDTISChildDocuments = ChildDocuments
                .Where(s => s.DocumentName.Equals(Schedule.RDTIS.ToString()))
                .Select(p => (RDTIS2023)p.ConsumedReport);

            RPTTAXPOSChildDocuments = ChildDocuments
               .Where(s => s.DocumentName.Equals(Schedule.RPTTAXPOS.ToString()))
               .Select(p => (RPTTAXPOS2019)p.ConsumedReport);

            DISTBENTRTChildDocuments = ChildDocuments
               .Where(s => s.DocumentName.Equals(Schedule.DISTBENTRT.ToString()))
               .Select(p => (DISTBENTRT2024)p.ConsumedReport);
        }

        public List<ProcessMessageDocument> ValidateCrossFormRules()
        {
            var response = new List<ProcessMessageDocument>();
            //CTR-CGTS2018
            VRATOCTR428096(response);
            //CTR-LS2017
            VRATOCTR428099(response);
            VRATOCTR428034(response);
            //CTR-CGLS2017
            VRATOCTR428135(response);
            VRATOCTR428100(response);
            //CTR-PSS
            VRATOCTR428278(response);
            VRATOCTR428040(response);
            VRATOCTR428109(response);
            VRATOCTR428101(response);
            //CTR-IEE
            VRATOCTR428037(response);
            VRATOCTR428039(response);
            //CGNFT-CTR
            VRATOCGNFT000100(response);
            VRATOCGNFT000019(response);
            //CTR_IDS
            VRATOCTR430014(response);
            VRATOCTR430020(response);
            VRATOCTR448352(response);
            VRATOCTR448353(response);
            VRATOCTR430015(response);
            VRATOCTR500003(response);
            //CTR_RTDIS
            VRATOCTR428404(response);
            VRATOCTR428354(response);
            VRATOCTR428355(response);
            VRATOCTR428398(response);
            VRATOCTR428399(response);
            VRATOCTR500006(response);
            VRATOCTR500307(response);
            VRATOCTR500382(response);
            VRATOCTR500304(response);
            VRATOCTR500305(response);
            //CTR_RTPS
            VRATOCTR500002(response);
            VRATOCTR500004(response);
            VRATOCTR500005(response);
            //CTR_DISTBENTRT
            VRATOCTR500391(response);

            // "EMPTY" = This value will be used in place of any parameter values that result in a null or empty value.
            foreach (ProcessMessageDocument currentProcessMessage in response)
            {
                if (currentProcessMessage.Parameters != null)
                {
                    foreach (ProcessMessageParameter currentParameter in currentProcessMessage.Parameters)
                    {
                        if (string.IsNullOrEmpty(currentParameter.Name))
                        {
                            currentParameter.Name = "EMPTY";
                        }

                        if (string.IsNullOrEmpty(currentParameter.Value))
                        {
                            currentParameter.Value = "EMPTY";
                        }
                    }
                }
            }

            return response;
        }

        #region  CTR-RDTIS 

        #region VR.ATO.CTR.428398

        /*  VR.ATO.CTR.428398
             IF [CTR328] <> [RDTIS48] AND (COUNT(SCHEDULE = "RDTIS") = 1) 
               RETURN VALIDATION MESSAGE
            ENDIF

          */
        protected void VRATOCTR428398(List<ProcessMessageDocument> response)
        {
            ProcessMessageDocument processMessage;

            bool assertion = RDTISChildDocuments.Count() == 1 &&
                            (ParentDocument.CTR328.GetValueOrDefault() != RDTISChildDocuments.First().RDTIS48.GetValueOrDefault());
            if (assertion)
            {
                processMessage = new ProcessMessageDocument()
                {
                    Code = "CMN.ATO.CTR.428355",
                    Severity = ProcessMessageSeverity.Error,
                    Description = @"R&D label mismatch",
                    LongDescription = @"R&D labels do not equal their matching labels in the Research and Development Tax Incentive schedule.",
                    Location = "/xbrli:xbrl/tns:TaxConcession.ResearchAndDevelopment.TaxOffsetNonRefundable.Amount[@contextRef='" + ParentDocument.RPId + "']",
                    Parameters = new ProcessMessageParameters() { new ProcessMessageParameter() { Name = "RuleIdentifier", Value = "VR.ATO.CTR.428398" } },
                };
                processMessage.Parameters.Add(new ProcessMessageParameter { Name = "CTR328", Value = ParentDocument.CTR328.GetValueOrDefault().ToString() });

                response.Add(processMessage);
            }
        }
        #endregion // VR.ATO.CTR.428398

        #region VR.ATO.CTR.428399

        /*  VR.ATO.CTR.428399

                IF [CTR210] <> [RDTIS46] AND (COUNT(SCHEDULE = "RDTIS") = 1) 
                   RETURN VALIDATION MESSAGE
                ENDIF
        */
        protected void VRATOCTR428399(List<ProcessMessageDocument> response)
        {
            ProcessMessageDocument processMessage;

            bool assertion = RDTISChildDocuments.Count() == 1 &&
                         (ParentDocument.CTR210.GetValueOrDefault() != RDTISChildDocuments.First().RDTIS46.GetValueOrDefault());
            if (assertion)
            {
                processMessage = new ProcessMessageDocument()
                {
                    Code = "CMN.ATO.CTR.428355",
                    Severity = ProcessMessageSeverity.Error,
                    Description = @"R&D label mismatch",
                    LongDescription = @"R&D labels do not equal their matching labels in the Research and Development Tax Incentive schedule.",
                    Location = "/xbrli:xbrl/tns:TaxConcession.ResearchAndDevelopment.TaxOffsetRefundable.Amount",
                    Parameters = new ProcessMessageParameters() { new ProcessMessageParameter() { Name = "RuleIdentifier", Value = "VR.ATO.CTR.428399" } },
                };
                processMessage.Parameters.Add(new ProcessMessageParameter { Name = "CTR210", Value = ParentDocument.CTR210.GetValueOrDefault().ToString() });

                response.Add(processMessage);
            }
        }
        #endregion // VR.ATO.CTR.428399 

        #region VR.ATO.CTR.428400

        /*  VR.ATO.CTR.428400

               IF [CTR321] <> [RDTIS31] AND (COUNT(SCHEDULE = "RDTIS") = 1) 
                  RETURN VALIDATION MESSAGE
               ENDIF
          */
        /*     protected void VRATOCTR428400(List<ProcessMessageDocument> response)
             {
                 ProcessMessageDocument processMessage;

                 bool assertion = RDTISChildDocuments.Count() == 1 &&
                            (ParentDocument.CTR321.GetValueOrDefault() != RDTISChildDocuments.First().RDTIS31.GetValueOrDefault());
                 if (assertion)
                 {
                     processMessage = new ProcessMessageDocument()
                     {
                         Code = "CMN.ATO.CTR.428355",
                         Severity = ProcessMessageSeverity.Error,
                         Description = @"R&D label mismatch",
                         LongDescription = @"R&D labels do not equal their matching labels in the Research and Development Tax Incentive schedule.",
                         Location = "/xbrli:xbrl/tns:IncomeTax.ResearchAndDevelopmentRecoupment.Amount",
                         Parameters = new ProcessMessageParameters() { new ProcessMessageParameter() { Name = "RuleIdentifier", Value = "VR.ATO.CTR.428400" } },
                     };
                     processMessage.Parameters.Add(new ProcessMessageParameter { Name = "CTR321", Value = ParentDocument.CTR321.GetValueOrDefault().ToString() });
                     response.Add(processMessage);
                 }
             }
        */
        #endregion // VR.ATO.CTR.428400

        #region VR.ATO.CTR.428355

        /*  VR.ATO.CTR.428355

                 IF [CTR97] <> [RDTIS3] AND (COUNT(SCHEDULE = "RDTIS") = 1) 
                    RETURN VALIDATION MESSAGE
                 ENDIF
        */
        protected void VRATOCTR428355(List<ProcessMessageDocument> response)
        {
            ProcessMessageDocument processMessage;

            bool assertion = RDTISChildDocuments.Count() == 1 &&
                (ParentDocument.CTR97.GetValueOrDefault() != RDTISChildDocuments.First().RDTIS3.GetValueOrDefault());
            if (assertion)
            {
                processMessage = new ProcessMessageDocument()
                {
                    Code = "CMN.ATO.CTR.428355",
                    Severity = ProcessMessageSeverity.Error,
                    Description = @"R&D label mismatch",
                    LongDescription = @"R&D labels do not equal their matching labels in the Research and Development Tax Incentive schedule.",
                    Location = "/xbrli:xbrl/tns:TaxConcession.ResearchAndDevelopment.WriteBackOfAccountingExpenditure.Amount",
                    Parameters = new ProcessMessageParameters() { new ProcessMessageParameter() { Name = "RuleIdentifier", Value = "VR.ATO.CTR.428355" } },
                };
                processMessage.Parameters.Add(new ProcessMessageParameter { Name = "CTR97", Value = ParentDocument.CTR97.GetValueOrDefault().ToString() });
                response.Add(processMessage);
            }
        }
        #endregion // VR.ATO.CTR.428355

        #region VR.ATO.CTR.428354

        /*  VR.ATO.CTR.428354

                IF ([CTR97] <> NULL OR [CTR328] <> NULL OR [CTR210] <> NULL) AND (COUNT(SCHEDULE = "RDTIS") = 0)
                   RETURN VALIDATION MESSAGE
                ENDIF
         */
        protected void VRATOCTR428354(List<ProcessMessageDocument> response)
        {
            ProcessMessageDocument processMessage;

            bool assertion = (ParentDocument.CTR97.HasValue || ParentDocument.CTR328.HasValue || ParentDocument.CTR210.HasValue)
                           && RDTISChildDocuments.Count() == 0;
            if (assertion)
            {
                processMessage = new ProcessMessageDocument()
                {
                    Code = "CMN.ATO.CTR.428354",
                    Severity = ProcessMessageSeverity.Error,
                    Description = @"Research and Development Tax Incentive schedule must be attached",
                    LongDescription = @"Where R&D labels have been completed a Research and Development Tax Incentive schedule must be attached.",
                    Location = "/xbrli:xbrl/tns:TaxConcession.ResearchAndDevelopment.WriteBackOfAccountingExpenditure.Amount",
                    Parameters = new ProcessMessageParameters() { new ProcessMessageParameter() { Name = "RuleIdentifier", Value = "VR.ATO.CTR.428354" } },
                };
                processMessage.Parameters.Add(new ProcessMessageParameter { Name = "CTR97", Value = ParentDocument.CTR97.GetValueOrDefault().ToString() });
                processMessage.Parameters.Add(new ProcessMessageParameter { Name = "CTR328", Value = ParentDocument.CTR328.GetValueOrDefault().ToString() });
                processMessage.Parameters.Add(new ProcessMessageParameter { Name = "CTR210", Value = ParentDocument.CTR210.GetValueOrDefault().ToString() });
                response.Add(processMessage);
            }
        }
        #endregion // VR.ATO.CTR.428354

        #region VR.ATO.CTR.428404

        /*  VR.ATO.CTR.428404
             IF (COUNT(SCHEDULE = "RDTIS") = 1) AND [RDTIS1] = TRUE AND [CTR298] <> TRUE
               RETURN VALIDATION MESSAGE
            ENDIF
          */
        protected void VRATOCTR428404(List<ProcessMessageDocument> response)
        {
            ProcessMessageDocument processMessage;

            bool assertion = RDTISChildDocuments.Count() == 1 && (RDTISChildDocuments.First().RDTIS1.HasValue && RDTISChildDocuments.First().RDTIS1.Value == true)
                 && (!ParentDocument.CTR298.HasValue || ParentDocument.CTR298.GetValueOrDefault() != true);
            if (assertion)
            {
                processMessage = new ProcessMessageDocument()
                {
                    Code = "CMN.ATO.CTR.428404",
                    Severity = ProcessMessageSeverity.Error,
                    Description = @"An amended R&D tax incentive schedule may only be attached to an amended main form",
                    Location = "/xbrli:xbrl/tns:Report.Amendment.Indicator",
                    Parameters = new ProcessMessageParameters() { new ProcessMessageParameter() { Name = "RuleIdentifier", Value = "VR.ATO.CTR.428404" } },
                };

                processMessage.Parameters.Add(new ProcessMessageParameter { Name = "CTR298", Value = GetValueOrEmpty(ParentDocument.CTR298) });
                processMessage.Parameters.Add(new ProcessMessageParameter { Name = "RDTIS1", Value = RDTISChildDocuments.First().RDTIS1.GetValueOrDefault().ToString() });
                response.Add(processMessage);
            }
        }
        #endregion // VR.ATO.CTR.428404 

        #region VR.ATO.CTR.500006

        /*  VR.ATO.CTR.500006
                    AusIndustry Innovation Australia number must be provided for lodgements made on or after the year 2019.

                Legacy Rule Format:
                    IF (COUNT(SCHEDULE = "RDTIS") = 1) AND [RDTIS2] = NULLORBLANK
                       RETURN VALIDATION MESSAGE
                    ENDIF

            Technical Business Rule Format:
                    (CountDocument('RDTIS') = 1) AND ^RDTIS2 = BLANK

        Data Elements:
    
            ^RDTIS2 = RDTIS2
            */
        protected void VRATOCTR500006(List<ProcessMessageDocument> response)
        {
            ProcessMessageDocument processMessage;
            bool assertion = (RDTISChildDocuments.Count() == 1 && string.IsNullOrWhiteSpace(RDTISChildDocuments.First().RDTIS2));
            if (assertion)
            {
                processMessage = new ProcessMessageDocument()
                {
                    Code = "CMN.ATO.GEN.001001",
                    Severity = ProcessMessageSeverity.Error,
                    Description = @"Mandatory field not supplied",
                    Location = "/tns:RDTIS/tns:RP/tns:InnovationRegistrationNumberId",
                    Parameters = new ProcessMessageParameters() { new ProcessMessageParameter() { Name = "RuleIdentifier", Value = "VR.ATO.CTR.500006" } },
                };

                processMessage.Parameters.Add(new ProcessMessageParameter { Name = "RDTIS2", Value = RDTISChildDocuments.First().RDTIS2 });
                response.Add(processMessage);
            }
        }
        #endregion // VR.ATO.CTR.500006


        #region VR.ATO.CTR.500307

        /*  VR.ATO.CTR.500307
                   IF [CTR375] = TRUE AND (COUNT(SCHEDULE = "RDTIS") = 1) AND ([RDTIS78] <> NULL AND [RDTIS78] <> SET("25", "25.00"))
                RETURN VALIDATION MESSAGE
                ENDIF

                [CTR375] = CTR:RP:rvctc3.02.40:Elections.BaseRateEntityElection.Indicator
                [RDTIS78] = /tns:RDTIS/tns:RP/tns:TaxRateDesignationR
            */
        protected void VRATOCTR500307(List<ProcessMessageDocument> response)
        {
            ProcessMessageDocument processMessage;
            bool assertion = (ParentDocument.CTR375.GetValueOrDefault() == true) && (RDTISChildDocuments.Count() == 1 &&
                (RDTISChildDocuments.First().RDTIS78.HasValue && RDTISChildDocuments.First().RDTIS78.Value != 25));
            if (assertion)
            {
                processMessage = new ProcessMessageDocument()
                {
                    Code = "CMN.ATO.CTR.500307",
                    Severity = ProcessMessageSeverity.Error,
                    Description = @"Tax rate in Research and Development Tax Incentive schedule is incorrect",

                    Location = "/xbrli:xbrl/tns:Elections.BaseRateEntityElection.Indicator",
                    Parameters = new ProcessMessageParameters() { new ProcessMessageParameter() { Name = "RuleIdentifier", Value = "VR.ATO.CTR.500307" } },

                };

                processMessage.Parameters.Add(new ProcessMessageParameter { Name = "CTR375", Value = ParentDocument.CTR375.GetValueOrDefault().ToString() });
                processMessage.Parameters.Add(new ProcessMessageParameter { Name = "RDTIS78", Value = RDTISChildDocuments.First().RDTIS78.GetValueOrDefault().ToString() });
                response.Add(processMessage);
            }
        }
        #endregion // VR.ATO.CTR.500307

        #region VR.ATO.CTR.500382

        /*  VR.ATO.CTR.500382
               If the base rate entity indicator response is not provided, the tax rate in Research and Development Tax Incentive schedule should be 30%

               Legacy Rule Format:
                  IF ([CTR375] = FALSE OR  [CTR375] = NULL) AND (COUNT(SCHEDULE = "RDTIS") = 1) AND ([RDTIS78] <> NULL AND [RDTIS78] <> SET("30", "30.00"))
                    RETURN VALIDATION MESSAGE
                  ENDIF                  
            
           Technical Business Rule Format:                          
                    (^CTR375 = FALSE OR  ^CTR375 = NULL) AND (COUNT(SCHEDULE = "RDTIS") = 1) AND (^RDTIS78 <> NULL AND ^RDTIS78 <> SET("30", "30.00"))                              

       Data Elements:
        ^CTR375 = RP:Elections.BaseRateEntityElection.Indicator
        ^RDTIS78 =  /tns:RDTIS/tns:RP/tns:TaxRateDesignationR
           */

        public void VRATOCTR500382(List<ProcessMessageDocument> response)
        {
            ProcessMessageDocument processMessage;
            bool assertion = (ParentDocument.CTR375.GetValueOrDefault() == false || ParentDocument.CTR375 == null) && (RDTISChildDocuments.Count() == 1 &&
               (RDTISChildDocuments.First().RDTIS78.HasValue && RDTISChildDocuments.First().RDTIS78.Value != 30));

            if (assertion)
            {
                processMessage = new ProcessMessageDocument()
                {
                    Code = "CMN.ATO.CTR.500382",
                    Severity = ProcessMessageSeverity.Error,
                    Description = @"Tax rate in Research and Development Tax Incentive schedule is incorrect",
                    Location = "/xbrli:xbrl/tns:Elections.BaseRateEntityElection.Indicator",
                    Parameters = new ProcessMessageParameters() { new ProcessMessageParameter() { Name = "RuleIdentifier", Value = "VR.ATO.CTR.500382" } },
                };

                processMessage.Parameters.Add(new ProcessMessageParameter { Name = "CTR375", Value = ParentDocument.CTR375.GetValueOrDefault().ToString() });
                processMessage.Parameters.Add(new ProcessMessageParameter { Name = "RDTIS78", Value = RDTISChildDocuments.First().RDTIS78.GetValueOrDefault().ToString() });

                response.Add(processMessage);
            }
        }

        #endregion // VR.ATO.CTR.500382

        #region VR.ATO.CTR.500304

        /*  VR.ATO.CTR.500304
                  IF [CTR450] <> [RDTIS76] AND (COUNT(SCHEDULE = "RDTIS") = 1) 
                   RETURN VALIDATION MESSAGE
                ENDIF

                [CTR450] = CTR:RP:bafpr3.02.28:Income.ResearchAndDevelopment.Clawback.Amount
                [RDTIS76] = /tns:RDTIS/tns:RP/tns:TotalclawbackIncomeResearchAndDevelopmentClawbackA          
            */
        protected void VRATOCTR500304(List<ProcessMessageDocument> response)
        {
            ProcessMessageDocument processMessage;

            bool bothParamsAreNull = false;

            if (RDTISChildDocuments.FirstOrDefault() != null)
            {

                bothParamsAreNull = RDTISChildDocuments.First().RDTIS76 == null && ParentDocument.CTR450 == null;
            }

            //bool bothParamsAreNull = RDTISChildDocuments.First().RDTIS76 == null && ParentDocument.CTR450 == null;

            bool assertion = !bothParamsAreNull &&
                            ((RDTISChildDocuments.Count() == 1 && RDTISChildDocuments.First().RDTIS76.GetValueOrDefault() != ParentDocument.CTR450.GetValueOrDefault())
                            || (RDTISChildDocuments.Count() == 1 && RDTISChildDocuments.First().RDTIS76.GetValueOrDefault() == 0 && ParentDocument.CTR450 == null)
                            || (RDTISChildDocuments.Count() == 1 && RDTISChildDocuments.First().RDTIS76 == null && ParentDocument.CTR450 == 0))
                            ;
            if (assertion)
            {
                processMessage = new ProcessMessageDocument()
                {
                    Code = "CMN.ATO.CTR.428355",
                    Severity = ProcessMessageSeverity.Error,
                    Description = @"R&D label mismatch",
                    LongDescription = @"R&D labels do not equal their matching labels in the Research and Development Tax Incentive schedule.",
                    Location = "/xbrli:xbrl/tns:Income.ResearchAndDevelopment.Clawback.Amount",
                    Parameters = new ProcessMessageParameters() { new ProcessMessageParameter() { Name = "RuleIdentifier", Value = "VR.ATO.CTR.500304" } },
                };

                processMessage.Parameters.Add(new ProcessMessageParameter
                { Name = "CTR450", Value = GetValueOrEmpty(ParentDocument.CTR450) });

                processMessage.Parameters.Add(new ProcessMessageParameter
                { Name = "RDTIS76", Value = GetValueOrEmpty(RDTISChildDocuments.First().RDTIS76) });

                response.Add(processMessage);
            }
        }
        #endregion // VR.ATO.CTR.500304

        #region VR.ATO.CTR.500305

        /*  VR.ATO.CTR.500305
                              IF [CTR451] <> [RDTIS77] AND (COUNT(SCHEDULE = "RDTIS") = 1) 
               RETURN VALIDATION MESSAGE
            ENDIF

            [CTR451] = CTR:RP:bafpr3.02.28:Expense.ResearchAndDevelopment.AdjustmentBalance.Amount
            [RDTIS77] = /tns:RDTIS/tns:RP/tns:DeductiblebalancingadjustmentsExpenseResearchAndDevelopmentAdjustmentBalanceA

            */
        protected void VRATOCTR500305(List<ProcessMessageDocument> response)
        {
            ProcessMessageDocument processMessage;
            bool bothParamsAreNull = false;

            if (RDTISChildDocuments.FirstOrDefault() != null)
            {

                bothParamsAreNull = RDTISChildDocuments.First().RDTIS77 == null && ParentDocument.CTR451 == null;
            }

            bool assertion = !bothParamsAreNull &&
                            ((RDTISChildDocuments.Count() == 1 && RDTISChildDocuments.First().RDTIS77.GetValueOrDefault() != ParentDocument.CTR451.GetValueOrDefault())
                            || (RDTISChildDocuments.Count() == 1 && RDTISChildDocuments.First().RDTIS77.GetValueOrDefault() == 0 && ParentDocument.CTR451 == null)
                            || (RDTISChildDocuments.Count() == 1 && RDTISChildDocuments.First().RDTIS77 == null && ParentDocument.CTR451 == 0));


            if (assertion)
            {
                processMessage = new ProcessMessageDocument()
                {
                    Code = "CMN.ATO.CTR.428355",
                    Severity = ProcessMessageSeverity.Error,
                    Description = @"R&D label mismatch",
                    LongDescription = @"R&D labels do not equal their matching labels in the Research and Development Tax Incentive schedule.",
                    Location = "/xbrli:xbrl/tns:Expense.ResearchAndDevelopment.AdjustmentBalance.Amount",
                    Parameters = new ProcessMessageParameters() { new ProcessMessageParameter() { Name = "RuleIdentifier", Value = "VR.ATO.CTR.500305" } },
                };
                processMessage.Parameters.Add(new ProcessMessageParameter { Name = "CTR451", Value = GetValueOrEmpty(ParentDocument.CTR451) });
                processMessage.Parameters.Add(new ProcessMessageParameter { Name = "RDTIS77", Value = GetValueOrEmpty(RDTISChildDocuments.First().RDTIS77) });
                response.Add(processMessage);
            }
        }
        #endregion // VR.ATO.CTR.500305

        #endregion //  CTR-RDTIS

        #region  CGNFT-CTR
        #region VR.ATO.CGNFT.000100

        /*  VR.ATO.CGNFT.000100

                    IF COUNT(SCHEDULE(CGNFT)) > 1
                        RETURN VALIDATION MESSAGE
                    ENDIF
        */
        protected void VRATOCGNFT000100(List<ProcessMessageDocument> response)
        {
            ProcessMessageDocument processMessage;
            bool assertion = CGNFTChildDocuments.Count() > 1;

            if (assertion)
            {
                processMessage = new ProcessMessageDocument()
                {
                    Code = "CMN.ATO.CGNFT.000100",
                    Severity = ProcessMessageSeverity.Error,
                    Description = @"The number of Consolidated Group Notification schedules must not exceed 1",
                    //Location = "/xbrli:xbrl",
                    Parameters = new ProcessMessageParameters() { new ProcessMessageParameter() { Name = "RuleIdentifier", Value = "VR.ATO.CGNFT.000100" } },
                };
                response.Add(processMessage);
            }
        }

        #endregion // VR.ATO.CGNFT.000100

        #region VR.ATO.CGNFT.000019

        /*  VR.ATO.CGNFT.000019

                    IF (PARENT RETURN <> NULL) AND (CTR:RP:OrganisationDetails.TaxConsolidationStatus.Code <> "1")
                       RETURN VALIDATION MESSAGE
                    ENDIF

                    */
        protected void VRATOCGNFT000019(List<ProcessMessageDocument> response)
        {
            ProcessMessageDocument processMessage;

            bool assertion = (string.IsNullOrWhiteSpace(ParentDocument.CTR53) || !ParentDocument.CTR53.Equals("1")) && CGNFTChildDocuments.Count() > 0;

            if (assertion)
            {
                processMessage = new ProcessMessageDocument()
                {
                    Code = "CMN.ATO.CGNFT.000019",
                    Severity = ProcessMessageSeverity.Error,
                    Description = @"Consolidated group status absent or incorrect on Parent form",
                    LongDescription = @"The Consolidated group status indicator on the Parent company return form must be present and equal to '1' for the Head company if the Notification of formation of a consolidated group schedule is present",
                    Location = "/xbrli:xbrl/tns:OrganisationDetails.TaxConsolidationStatus.Code",
                    Parameters = new ProcessMessageParameters() { new ProcessMessageParameter() { Name = "RuleIdentifier", Value = "VR.ATO.CGNFT.000019" } },
                };

                response.Add(processMessage);
            }
        }

        #endregion // VR.ATO.CGNFT.000019

        #endregion //  CTR-CGNFT

        #region CTR-CGTS
        #region VR.ATO.CTR.428096

        /*  VR.ATO.CTR.428096
                
                    IF (([CTR91] > 10000) AND 
                        (COUNT(SCHEDULE = "CGTS") = 0))
                            RETURN VALIDATION MESSAGE
                    ENDIF
                    
                    [CTR91] = CTR:RP:bafpr1.02.00:Income.CapitalGainsNet.Amount
                    */
        protected void VRATOCTR428096(List<ProcessMessageDocument> response)
        {
            bool assertion = !ChildDocuments.Any(c => c.DocumentName.Equals("CGTS")) && ParentDocument.CTR91.HasValue &&
                             ParentDocument.CTR91.Value > 10000;

            if (assertion)
            {
                var processMessage = new ProcessMessageDocument
                {
                    Code = "CMN.ATO.CTR.428379",
                    Severity = ProcessMessageSeverity.Error,
                    Description = "Capital Gains Tax schedule required, where net capital gains exceeds $10,000",
                    LongDescription = "When Net capital gains is in excess of $10,000, a Capital Gains Tax schedule must be attached",
                    Location = "/xbrli:xbrl/tns:Income.CapitalGainsNet.Amount",
                    Parameters = new ProcessMessageParameters { new ProcessMessageParameter { Name = "RuleIdentifier", Value = "VR.ATO.CTR.428096" } }
                };

                processMessage.Parameters.Add(new ProcessMessageParameter
                {
                    Name = "CTR91",
                    Value = ParentDocument.CTR91.GetValueOrDefault().ToString()
                });

                processMessage.Parameters.Add(new ProcessMessageParameter
                {
                    Name = "CTR53",
                    Value = ParentDocument.CTR53
                });

                response.Add(processMessage);
            }
        }

        #endregion // VR.ATO.CTR.428096
        #region VR.ATO.CTR.428034

        /*  VR.ATO.CTR.428034
            IF ([CTR53] = "1") AND (COUNT(SCHEDULE = "LS") = 1)
               RETURN VALIDATION MESSAGE
            ENDIF

            [CTR53] = CTR:RP:pyde.02.03:OrganisationDetails.TaxConsolidationStatus.Code
        */
        protected void VRATOCTR428034(List<ProcessMessageDocument> response)
        {
            bool assertion = ChildDocuments.Any(c => c.DocumentName.Equals("LS")) && ParentDocument.CTR53 == "1";

            if (assertion)
            {
                var processMessage = new ProcessMessageDocument
                {
                    Code = "CMN.ATO.CTR.428034",
                    Severity = ProcessMessageSeverity.Error,
                    Description = "Losses schedule BP cannot be lodged with a consolidated Head company return",
                    LongDescription = "A consolidated head company is not required to lodge a Losses schedule for unconsolidated entities",
                    Location = "/xbrli:xbrl/tns:OrganisationDetails.TaxConsolidationStatus.Code",
                    Parameters = new ProcessMessageParameters { new ProcessMessageParameter { Name = "RuleIdentifier", Value = "VR.ATO.CTR.428034" } },
                };

                processMessage.Parameters.Add(new ProcessMessageParameter { Name = "CTR53", Value = ParentDocument.CTR53 });
                response.Add(processMessage);
            }
        }
        #endregion // VR.ATO.CTR.428034
        #region VR.ATO.CTR.428099

        /*  VR.ATO.CTR.428099
           IF ([CTR175] + [CTR176] > 100000) AND 
        ([CTR53] = NULLORBLANK) AND (COUNT(SCHEDULE = "LS") = 0)
           RETURN VALIDATION MESSAGE
        ENDIF

        [CTR53] = CTR:RP:pyde.02.03:OrganisationDetails.TaxConsolidationStatus.Code
        [CTR175] = CTR:RP:rvctc3.02.00:Tax.Losses.CarriedForward.Total.Amount
        [CTR176] = CTR:RP(Instant):rvctc3.02.16:Capital.Losses.CarriedForward.Net.Amount
     */
        protected void VRATOCTR428099(List<ProcessMessageDocument> response)
        {
            bool assertion = !ChildDocuments.Any(c => c.DocumentName.Equals("LS")) &&
                             string.IsNullOrWhiteSpace(ParentDocument.CTR53) &&
                             ParentDocument.CTR175.GetValueOrDefault() + ParentDocument.CTR176.GetValueOrDefault() > 100000;
            if (assertion)
            {
                var processMessage = new ProcessMessageDocument
                {
                    Code = "CMN.ATO.CTR.428099",
                    Severity = ProcessMessageSeverity.Error,
                    Description = "Losses schedule must be attached where total of tax losses and net capital losses exceeds $100000",
                    LongDescription = "Where the total of tax losses and net capital losses exceeds $100000 and the company is not part of a consolidated group, a Losses schedule must be attached",
                    Location = "/xbrli:xbrl/tns:Capital.Losses.CarriedForward.Net.Amount",
                    Parameters = new ProcessMessageParameters { new ProcessMessageParameter { Name = "RuleIdentifier", Value = "VR.ATO.CTR.428099" } }
                };

                processMessage.Parameters.Add(new ProcessMessageParameter { Name = "CTR175", Value = ParentDocument.CTR175.GetValueOrDefault().ToString() });
                processMessage.Parameters.Add(new ProcessMessageParameter { Name = "CTR176", Value = ParentDocument.CTR176.GetValueOrDefault().ToString() });
                response.Add(processMessage);
            }
        }
        #endregion // VR.ATO.CTR.428099
        #endregion CTR-CGTS

        #region CTR-CGLS
        #region VR.ATO.CTR.428135

        /*  VR.ATO.CTR.428135

                    IF (([CTR117] > 100000) AND ([CTR53] = "1") AND (COUNT(SCHEDULE = "CGLS") = 0))
                       RETURN VALIDATION MESSAGE
                    ENDIF

                    [CTR53] = CTR:RP:pyde.02.03:OrganisationDetails.TaxConsolidationStatus.Code
                    [CTR117] = CTR:RP:rvctc2.02.00:IncomeTax.Deduction.TaxLossesDeducted.Amount
                    */
        protected void VRATOCTR428135(List<ProcessMessageDocument> response)
        {
            bool assertion = !ChildDocuments.Any(c => c.DocumentName.Equals("CGLS")) &&
                             ParentDocument.CTR117.GetValueOrDefault() > 100000 &&
                             ParentDocument.CTR53 == "1";
            if (assertion)
            {
                var processMessage = new ProcessMessageDocument
                {
                    Code = "CMN.ATO.CTR.428135",
                    Severity = ProcessMessageSeverity.Error,
                    Description = "Consolidated losses schedule may be required",
                    LongDescription = "If the amount of Tax losses deducted is greater than $100000 and the Consolidated group status indicator is equal to \"1\" for head company then a Consolidated losses schedule must be completed",
                    Location = "/xbrli:xbrl/tns:IncomeTax.Deduction.TaxLossesDeducted.Amount",
                    Parameters = new ProcessMessageParameters() { new ProcessMessageParameter() { Name = "RuleIdentifier", Value = "VR.ATO.CTR.428135" } },
                };
                processMessage.Parameters.Add(new ProcessMessageParameter { Name = "CTR117", Value = ParentDocument.CTR117.GetValueOrDefault().ToString() });
                processMessage.Parameters.Add(new ProcessMessageParameter { Name = "CTR53", Value = ParentDocument.CTR53 });

                response.Add(processMessage);
            }
        }
        #endregion // VR.ATO.CTR.428135
        #region VR.ATO.CTR.428100

        /*  VR.ATO.CTR.428100

                    IF ([CTR175] + [CTR176] > 100000) AND ([CTR53] = "1") AND (COUNT(SCHEDULE = "CGLS") = 0)
                       RETURN VALIDATION MESSAGE
                    ENDIF

                    [CTR53] = CTR:RP:pyde.02.03:OrganisationDetails.TaxConsolidationStatus.Code
                    [CTR175] = CTR:RP:rvctc3.02.00:Tax.Losses.CarriedForward.Total.Amount
                    [CTR176] = CTR:RP(Instant):rvctc3.02.16:Capital.Losses.CarriedForward.Net.Amount

                    */
        protected void VRATOCTR428100(List<ProcessMessageDocument> response)
        {
            bool assertion = !ChildDocuments.Any(c => c.DocumentName.Equals("CGLS")) &&
                                       (ParentDocument.CTR175.GetValueOrDefault() + ParentDocument.CTR176.GetValueOrDefault()) > 100000 &&
                                        ParentDocument.CTR53 == "1";
            if (assertion)
            {
                var processMessage = new ProcessMessageDocument
                {
                    Code = "CMN.ATO.CTR.428100",
                    Severity = ProcessMessageSeverity.Error,
                    Description = "Consolidated losses schedule must be attached where Tax Losses and Net Capital Losses greater than $100000",
                    LongDescription = "Consolidated losses schedule must be attached where total of tax losses and net capital losses exceeds $100000 and the Head company indicator is complete at Consolidated group status field",
                    Location = "/xbrli:xbrl/tns:Capital.Losses.CarriedForward.Net.Amount",
                    Parameters = new ProcessMessageParameters() { new ProcessMessageParameter() { Name = "RuleIdentifier", Value = "VR.ATO.CTR.428100" } },
                };

                processMessage.Parameters.Add(new ProcessMessageParameter { Name = "CTR175", Value = ParentDocument.CTR175.GetValueOrDefault().ToString() });
                processMessage.Parameters.Add(new ProcessMessageParameter { Name = "CTR176", Value = ParentDocument.CTR176.GetValueOrDefault().ToString() });
                processMessage.Parameters.Add(new ProcessMessageParameter { Name = "CTR53", Value = ParentDocument.CTR53 });
                response.Add(processMessage);
            }
        }
        #endregion // VR.ATO.CTR.428100
        #endregion CTR-CGLS 

        #region CTR-PSS

        #region VR.ATO.CTR.428278

        /*  VR.ATO.CTR.428278
            IF (([CTR57] > 0) AND (COUNT(SCHEDULE = "PSS") = 0)) OR ((SUM[PSS18]) <> [CTR57])
               RETURN VALIDATION MESSAGE
            ENDIF

            [CTR57] = CTR:RP:lrla.02.00:Remuneration.PaymentToForeignResidentGross.Amount
            [PSS18] = PSS:RP.Payer.{PSSeqNum}:lrla.02.00:Remuneration.PaymentToForeignResidentGross.Amount

          */
        protected void VRATOCTR428278(List<ProcessMessageDocument> response)
        {

            PSS2018 PSSChildDocument = null;
            if (ChildDocuments.Where(c => c.DocumentName.Equals("PSS")).Count() == 1)
            {
                var PSSChildDocuments = ChildDocuments.Where(c => c.DocumentName.Equals("PSS")).First();
                PSSChildDocument = (PSS2018)PSSChildDocuments.ConsumedReport;
            }

            bool assertion = ((PSSChildDocument == null) && ParentDocument.CTR57.GetValueOrDefault() > 0)
                            || (PSSChildDocument != null && ParentDocument.CTR57.GetValueOrDefault() != PSSChildDocument.RPPayerPSSeqNumContextCollection.Select(Item => Item.PSS18).Sum());


            if (assertion)
            {
                var processMessage = new ProcessMessageDocument()
                {
                    Code = "CMN.ATO.CTR.438075",
                    Severity = ProcessMessageSeverity.Error,
                    Description = "Gross payments are required on Payment Summary Schedule, where amount entered at Gross payments subject to foreign resident withholding (excluding capital gains).",
                    LongDescription = "An amount has been entered at gross payment where Gross payments are subject to foreign resident withholding (excluding capital gains) and there is no corresponding amounts on the Payment Summary Schedule.",
                    Location = "/xbrli:xbrl/tns:Remuneration.PaymentToForeignResidentGross.Amount",
                    Parameters = new ProcessMessageParameters() { new ProcessMessageParameter() { Name = "RuleIdentifier", Value = "VR.ATO.CTR.428278" } },
                };
                processMessage.Parameters.Add(new ProcessMessageParameter { Name = "CTR57", Value = ParentDocument.CTR57.GetValueOrDefault().ToString() });
                response.Add(processMessage);
            }
        }
        #endregion // VR.ATO.CTR.428278

        #region VR.ATO.CTR.428040

        /*  VR.ATO.CTR.428040
               Legacy Rule Format:
                    IF (([CTR58] > 0)  AND (COUNT(SCHEDULE = "PSS") = 0)) OR ((SUM[PSS19]) <> [CTR58])
                       RETURN VALIDATION MESSAGE
                    ENDIF

                    [CTR58] = CTR:RP:lrla.02.00:Remuneration.ABNNotQuotedPaymentGross.Amount
                    [PSS19] = PSS:RP.Payer.{PSSeqNum}:lrla.02.00:Remuneration.ABNNotQuotedPaymentGross.Amount

                    */
        protected void VRATOCTR428040(List<ProcessMessageDocument> response)
        {
            PSS2018 PSSChildDocument = null;
            if (ChildDocuments.Where(c => c.DocumentName.Equals("PSS")).Count() == 1)
            {
                var PSSChildDocuments = ChildDocuments.Where(c => c.DocumentName.Equals("PSS")).First();
                PSSChildDocument = (PSS2018)PSSChildDocuments.ConsumedReport;
            }
            bool assertion = ((PSSChildDocument == null) && ParentDocument.CTR58.GetValueOrDefault() > 0)
                          || (PSSChildDocument != null && ParentDocument.CTR58.GetValueOrDefault() != PSSChildDocument.RPPayerPSSeqNumContextCollection.Select(Item => Item.PSS19).Sum());

            if (assertion)
            {
                var processMessage = new ProcessMessageDocument()
                {
                    Code = "CMN.ATO.CTR.428040",
                    Severity = ProcessMessageSeverity.Error,
                    Description = "Gross payments are required on Payment Summary Schedule, where amount entered at Gross Payments where ABN not quoted",
                    LongDescription = "An amount has been entered at gross payment where ABN is not quoted and there are no corresponding amounts on the Payment Summary Schedule",
                    Location = "/xbrli:xbrl/tns:Remuneration.ABNNotQuotedPaymentGross.Amount",
                    Parameters = new ProcessMessageParameters() { new ProcessMessageParameter() { Name = "RuleIdentifier", Value = "VR.ATO.CTR.428040" } },
                };
                processMessage.Parameters.Add(new ProcessMessageParameter { Name = "CTR58", Value = ParentDocument.CTR58.GetValueOrDefault().ToString() });
                response.Add(processMessage);
            }
        }
        #endregion // VR.ATO.CTR.428040

        #region VR.ATO.CTR.428109

        /*  VR.ATO.CTR.428109
                     IF (([CTR57] > 0) AND (COUNT(SCHEDULE = "PSS") = 0)) OR ([CTR207] < SUM[PSS22])
                       RETURN VALIDATION MESSAGE
                    ENDIF

                    [CTR57] = CTR:RP:lrla.02.00:Remuneration.PaymentToForeignResidentGross.Amount
                    [CTR207] = CTR:RP:rvctc2.02.12:IncomeTax.PayAsYouGoWithholding.TaxWithheld.Amount WHERE (rvctc2.02.00:IncomeTax.PayAsYouGoWithholding.PaymentType.Code = "DFRW") IN TUPLE(ctr.0009.lodge.req.02.00:ITPAYGWithholdingDetails)
                    [PSS22] = PSS:RP.Payer.{PSSeqNum}:rvctc2.02.14:IncomeTax.PayAsYouGoWithholding.CreditTaxWithheldBusinessForeignResident.Amount                 
                    */
        protected void VRATOCTR428109(List<ProcessMessageDocument> response)
        {
            PSS2018 PSSChildDocument = null;
            if (ChildDocuments.Where(c => c.DocumentName.Equals("PSS")).Count() == 1)
            {
                var PSSChildDocuments = ChildDocuments.Where(c => c.DocumentName.Equals("PSS")).First();
                PSSChildDocument = (PSS2018)PSSChildDocuments.ConsumedReport;
            }
            bool assertion = ((PSSChildDocument == null) && ParentDocument.CTR57.GetValueOrDefault() > 0)
                          || (PSSChildDocument != null && ParentDocument.CTR207.GetValueOrDefault() < PSSChildDocument.RPPayerPSSeqNumContextCollection.Select(Item => Item.PSS22).Sum());

            if (assertion)
            {
                var processMessage = new ProcessMessageDocument()
                {
                    Code = "CMN.ATO.CTR.438074",
                    Severity = ProcessMessageSeverity.Error,
                    Description = "Credit for tax withheld-foreign resident withholding (excluding capital gains) must not be less than the amount present in the schedule.",
                    LongDescription = "There is an amount present at Gross payments subject to foreign resident withholding (excluding capital gains) and Credit for tax withheld - foreign resident withholding (excluding capital gains) (Calculation Statement) on the return form does not equal the sum of the amounts on the Payment Summary schedule.",
                    Location = "/xbrli:xbrl/tns:ITPAYGWithholdingDetails" + OccurrenceIndex(ParentDocument.ItpaygWithholdingDetailsCollection_DFRW_RPOccurrenceIndex) + "/tns:IncomeTax.PayAsYouGoWithholding.TaxWithheld.Amount",
                    Parameters = new ProcessMessageParameters() { new ProcessMessageParameter() { Name = "RuleIdentifier", Value = "VR.ATO.CTR.428109" } },
                };
                processMessage.Parameters.Add(new ProcessMessageParameter { Name = "CTR57", Value = ParentDocument.CTR57.GetValueOrDefault().ToString() });
                processMessage.Parameters.Add(new ProcessMessageParameter { Name = "CTR207", Value = ParentDocument.CTR207.GetValueOrDefault().ToString() });
                response.Add(processMessage);
            }
        }
        #endregion // VR.ATO.CTR.428109

        #region VR.ATO.CTR.428101

        /*  VR.ATO.CTR.428101
           Legacy Rule Format:
               IF ([CTR208] > 0) AND (((COUNT(SCHEDULE = "PSS") = 0) OR (SUM([PSS23]) <> [CTR208])))
                  RETURN VALIDATION MESSAGE
               ENDIF    
               [CTR208] = CTR:RP:rvctc2.02.12:IncomeTax.PayAsYouGoWithholding.TaxWithheld.Amount WHERE (rvctc2.02.00:IncomeTax.PayAsYouGoWithholding.PaymentType.Code = "DNOABN") IN TUPLE(ctr.0009.lodge.req.02.00:ITPAYGWithholdingDetails)
               [PSS23] = PSS:RP.Payer.{PSSeqNum}:rvctc2.02.14:IncomeTax.PayAsYouGoWithholding.CreditTaxWithheldBusinessABNNotQuoted.Amount
        IF ([CTR208] > 0) AND (((COUNT(SCHEDULE = "PSS") = 0) OR (SUM([PSS23]) <> [CTR208])))
RETURN VALIDATION MESSAGE
ENDIF

[CTR208] = CTR:RP:rvctc2.02.12:IncomeTax.PayAsYouGoWithholding.TaxWithheld.Amount WHERE (rvctc2.02.00:IncomeTax.PayAsYouGoWithholding.PaymentType.Code = "DNOABN") IN TUPLE(ctr.0009.lodge.req.02.00:ITPAYGWithholdingDetails)
[PSS23] = PSS:RP.Payer.{PSSeqNum}:rvctc2.02.14:IncomeTax.PayAsYouGoWithholding.CreditTaxWithheldBusinessABNNotQuoted.Amount


        */
        protected void VRATOCTR428101(List<ProcessMessageDocument> response)
        {
            PSS2018 PSSChildDocument = null;
            if (ChildDocuments.Where(c => c.DocumentName.Equals("PSS")).Count() == 1)
            {
                var PSSChildDocuments = ChildDocuments.Where(c => c.DocumentName.Equals("PSS")).First();
                PSSChildDocument = (PSS2018)PSSChildDocuments.ConsumedReport;
            }
            bool assertion = ParentDocument.CTR208.GetValueOrDefault() > 0 &&
                   (PSSChildDocument == null || ParentDocument.CTR208.GetValueOrDefault() != PSSChildDocument.RPPayerPSSeqNumContextCollection.Select(Item => Item.PSS23).Sum());

            if (assertion)
            {
                var processMessage = new ProcessMessageDocument()
                {
                    Code = "CMN.ATO.CTR.428101",
                    Severity = ProcessMessageSeverity.Error,
                    Description = "Amount withheld required on Payment Summary schedule",
                    LongDescription = "An amount has been entered at tax withheld from payments where ABN no quoted in the calculation statement and on the Payment Summary schedule there are no corresponding amounts and the payment type is \"N\"",
                    Location = "/xbrli:xbrl/tns:ITPAYGWithholdingDetails" + OccurrenceIndex(ParentDocument.ItpaygWithholdingDetailsCollection_DNOABN_RPOccurrenceIndex) + "/tns:IncomeTax.PayAsYouGoWithholding.TaxWithheld.Amount",
                    Parameters = new ProcessMessageParameters() { new ProcessMessageParameter() { Name = "RuleIdentifier", Value = "VR.ATO.CTR.428101" } },
                };
                processMessage.Parameters.Add(new ProcessMessageParameter { Name = "CTR208", Value = ParentDocument.CTR208.GetValueOrDefault().ToString() });
                response.Add(processMessage);
            }
        }
        #endregion // VR.ATO.CTR.428101
        #endregion CTR-PSS

        #region CTR-IEE

        #region VR.ATO.CTR.428037

        /*  VR.ATO.CTR.428037

                    IF ([CTR55] = NULL) AND (COUNT(SCHEDULE = "IEE") > 0)
                       RETURN VALIDATION MESSAGE
                    ENDIF

                    */
        protected void VRATOCTR428037(List<ProcessMessageDocument> response)
        {
            ProcessMessageDocument processMessage;

            bool assertion = ParentDocument.CTR55 == null && IEEChildDocuments.Count() > 0;
            if (assertion)
            {
                processMessage = new ProcessMessageDocument()
                {
                    Code = "CMN.ATO.CTR.428037",
                    Severity = ProcessMessageSeverity.Error,
                    Description = @"IEE specified income year to be completed when IEE schedule is attached",
                    LongDescription = @"An IEE schedule is attached: however the IEE specified income year has not been completed on the Company Income Tax Return",
                    Location = "/xbrli:xbrl/tns:Elections.InterposedEntityElectionStatus.Year",
                    Parameters = new ProcessMessageParameters() { new ProcessMessageParameter() { Name = "RuleIdentifier", Value = "VR.ATO.CTR.428037" } },
                };


                response.Add(processMessage);
            }
        }
        #endregion // VR.ATO.CTR.428037

        #region VR.ATO.CTR.428039

        /*  VR.ATO.CTR.428039
                    IF ([CTR56] = "R") AND (COUNT(SCHEDULE = "IEE") = 0)
                       RETURN VALIDATION MESSAGE
                    ENDIF

                    [CTR56] = CTR:RP:rvctc3.02.02:Elections.InterposedEntityElectionOrRevocation.Code


                    */
        protected void VRATOCTR428039(List<ProcessMessageDocument> response)
        {
            ProcessMessageDocument processMessage;

            bool assertion = !string.IsNullOrWhiteSpace(ParentDocument.CTR56)
            && ParentDocument.CTR56.ToUpper() == "R" && IEEChildDocuments.Count() == 0;
            if (assertion)
            {
                processMessage = new ProcessMessageDocument()
                {
                    Code = "CMN.ATO.CTR.428039",
                    Severity = ProcessMessageSeverity.Error,
                    Description = @"Interposed Entity Election or Revocation schedule required where a revocation is being made",
                    LongDescription = @"The Interposed Entity Election code indicates a revocation is being made, however no schedule is attached",
                    Location = "/xbrli:xbrl/tns:Elections.InterposedEntityElectionOrRevocation.Code",
                    Parameters = new ProcessMessageParameters() { new ProcessMessageParameter() { Name = "RuleIdentifier", Value = "VR.ATO.CTR.428039" } },
                };

                response.Add(processMessage);
            }
        }
        #endregion // VR.ATO.CTR.428039


        #endregion CTR-IEE

        #region  CTR-IDS

        #region VR.ATO.CTR.430014

        /*  VR.ATO.CTR.430014
                  
                    IF [CTR81] > 0 AND (COUNT(SCHEDULE = "IDS") = 0) 
                       RETURN VALIDATION MESSAGE
                    ENDIF
                    
                    [CTR81] = CTR:RP.JFOREIGN:bafpr2.02.17:Expense.Operating.Interest.Amount

          
                    */
        protected void VRATOCTR430014(List<ProcessMessageDocument> response)
        {
            ProcessMessageDocument processMessage;
            bool assertion = ParentDocument.CTR81.GetValueOrDefault() > 0 && IDSChildDocuments.Count() == 0;
            if (assertion)
            {
                processMessage = new ProcessMessageDocument()
                {
                    Code = "CMN.ATO.CTR.430014",
                    Severity = ProcessMessageSeverity.Error,
                    Description = @"International dealings schedule required",
                    LongDescription = @"International dealings schedule must be attached if interest expenses overseas amount is greater than zero",
                    Location = "/xbrli:xbrl/tns:Expense.Operating.Interest.Amount[@contextRef='" + ParentDocument.RPJFOREIGNId + "']",
                    Parameters = new ProcessMessageParameters() { new ProcessMessageParameter() { Name = "RuleIdentifier", Value = "VR.ATO.CTR.430014" } },
                };
                processMessage.Parameters.Add(new ProcessMessageParameter { Name = "CTR81", Value = ParentDocument.CTR81.GetValueOrDefault().ToString() });
                response.Add(processMessage);
            }
        }
        #endregion // VR.ATO.CTR.430014

        #region VR.ATO.CTR.430020

        /*  VR.ATO.CTR.430020
             
                    IF [CTR98] > 0 AND (COUNT(SCHEDULE = "IDS") = 0) 
                       RETURN VALIDATION MESSAGE
                    ENDIF
                   
                    */
        protected void VRATOCTR430020(List<ProcessMessageDocument> response)
        {
            ProcessMessageDocument processMessage;
            bool assertion = ParentDocument.CTR98.GetValueOrDefault() > 0 && IDSChildDocuments.Count() == 0;
            if (assertion)
            {
                processMessage = new ProcessMessageDocument()
                {
                    Code = "CMN.ATO.CTR.430020",
                    Severity = ProcessMessageSeverity.Error,
                    Description = @"International dealings schedule required",
                    LongDescription = @"International dealings schedule must be attached if section 46FA deduction for flow-on dividends amount is greater than zero",
                    Location = "/xbrli:xbrl/tns:Expense.FlowOnDividendDeduction.Amount",
                    Parameters = new ProcessMessageParameters() { new ProcessMessageParameter() { Name = "RuleIdentifier", Value = "VR.ATO.CTR.430020" } },
                };
                processMessage.Parameters.Add(new ProcessMessageParameter { Name = "CTR98", Value = ParentDocument.CTR98.GetValueOrDefault().ToString() });
                response.Add(processMessage);
            }
        }
        #endregion // VR.ATO.CTR.430020

        # region VR.ATO.CTR.448352

        /*  VR.ATO.CTR.448352
                   
                    IF ([CTR194] = TRUE OR [CTR195] = TRUE OR [CTR196] = TRUE) 
                    AND
                    (COUNT(SCHEDULE = "IDS") = 0)
                    RETURN VALIDATION MESSAGE
                    ENDIF
                    
                    [CTR194] = CTR:RP:rvctc4.02.10:InternationalDealings.RelatedPartiesTransactionsExcessAggregateValue.Indicator
                    [CTR195] = CTR:RP:rvctc4.02.03:InternationalDealings.DirectOrIndirectOverseasInterest.Indicator
                    [CTR196] = CTR:RP:bafpo6.02.15:Liabilities.ThinCapitalisation.ProvisionsApplied.Indicator
      
                    */
        protected void VRATOCTR448352(List<ProcessMessageDocument> response)
        {
            ProcessMessageDocument processMessage;

            bool assertion = IDSChildDocuments.Count() == 0 &&
                             (ParentDocument.CTR194.GetValueOrDefault() || ParentDocument.CTR195.GetValueOrDefault() || ParentDocument.CTR196.GetValueOrDefault());
            if (assertion)
            {
                processMessage = new ProcessMessageDocument()
                {
                    Code = "CMN.ATO.CTR.458352",
                    Severity = ProcessMessageSeverity.Error,
                    Description = @"International Dealings Schedule is required",
                    LongDescription = @"When there is a 'yes' response to any of the questions concerning whether the value of dealings with international related parties is greater than $2 million, or whether the entity had either a direct or indirect interest in a foreign trust, foreign company, controlled foreign entity or transferor trust, or a 'yes' response to the question ""Were the thin capitalisation or debt deduction creation rules applicable to you"", an International Dealings Schedule is required",

                    Location = "/xbrli:xbrl/tns:InternationalDealings.RelatedPartiesTransactionsExcessAggregateValue.Indicator",
                    Parameters = new ProcessMessageParameters() { new ProcessMessageParameter() { Name = "RuleIdentifier", Value = "VR.ATO.CTR.448353" } },
                };
                processMessage.Parameters.Add(new ProcessMessageParameter { Name = "CTR194", Value = ParentDocument.CTR194.GetValueOrDefault().ToString() });
                processMessage.Parameters.Add(new ProcessMessageParameter { Name = "CTR195", Value = ParentDocument.CTR195.GetValueOrDefault().ToString() });
                processMessage.Parameters.Add(new ProcessMessageParameter { Name = "CTR196", Value = ParentDocument.CTR196.GetValueOrDefault().ToString() });


                response.Add(processMessage);
            }
        }
        #endregion // VR.ATO.CTR.448352

        #region VR.ATO.CTR.448353

        /*  VR.ATO.CTR.448353
                  
                    IF (([CTR81] = NULL OR [CTR81] = 0) AND ([CTR366] = NULL OR [CTR366] = 0) AND ([CTR98] = NULL OR [CTR98] = 0)) AND ([CTR194] = FALSE AND [CTR195] = FALSE AND [CTR196] = FALSE) 
                    AND (COUNT(SCHEDULE = "IDS") = 1)
                    RETURN VALIDATION MESSAGE
                    ENDIF

       
        */
        protected void VRATOCTR448353(List<ProcessMessageDocument> response)
        {
            ProcessMessageDocument processMessage;

            bool assertion = ((!ParentDocument.CTR81.HasValue || ParentDocument.CTR81.Value == 0) &&
                             (!ParentDocument.CTR366.HasValue || ParentDocument.CTR366.Value == 0) &&
                             (!ParentDocument.CTR98.HasValue || ParentDocument.CTR98.Value == 0)) &&
                              !ParentDocument.CTR194.GetValueOrDefault() &&
                              !ParentDocument.CTR195.GetValueOrDefault() &&
                              !ParentDocument.CTR196.GetValueOrDefault() && IDSChildDocuments.Count() == 1;

            if (assertion)
            {
                processMessage = new ProcessMessageDocument()
                {
                    Code = "CMN.ATO.CTR.458353",
                    Severity = ProcessMessageSeverity.Error,
                    Description = @"International Dealings Schedule is not required",
                    LongDescription = @"When 'Interest expenses overseas', 'Royalty expenses overseas' and 'Section 46fa deduction for flowon dividends' are not present, and there is a ""no"" response to the questions concerning whether the value of dealings with international related parties is greater than $2 million, and whether the entity had either a direct or indirect interest in a foreign trust, foreign company, controlled foreign entity or transferor trust, and there is a ""no"" response to the question 'Were the thin capitalisation or debt deduction creation rules applicable to you', an International Dealings Schedule is not required",
                    Location = "/xbrli:xbrl/tns:InternationalDealings.RelatedPartiesTransactionsExcessAggregateValue.Indicator",
                    Parameters = new ProcessMessageParameters() { new ProcessMessageParameter() { Name = "RuleIdentifier", Value = "VR.ATO.CTR.448353" } },
                };
                processMessage.Parameters.Add(new ProcessMessageParameter { Name = "CTR81", Value = ParentDocument.CTR81.GetValueOrDefault().ToString() });
                processMessage.Parameters.Add(new ProcessMessageParameter { Name = "CTR366", Value = ParentDocument.CTR366.GetValueOrDefault().ToString() });
                processMessage.Parameters.Add(new ProcessMessageParameter { Name = "CTR98", Value = ParentDocument.CTR98.GetValueOrDefault().ToString() });
                processMessage.Parameters.Add(new ProcessMessageParameter { Name = "CTR194", Value = ParentDocument.CTR194.GetValueOrDefault().ToString() });
                processMessage.Parameters.Add(new ProcessMessageParameter { Name = "CTR195", Value = ParentDocument.CTR195.GetValueOrDefault().ToString() });
                processMessage.Parameters.Add(new ProcessMessageParameter { Name = "CTR196", Value = ParentDocument.CTR196.GetValueOrDefault().ToString() });

                response.Add(processMessage);
            }
        }
        #endregion // VR.ATO.CTR.448353

        #region VR.ATO.CTR.430015

        /*  VR.ATO.CTR.430015
                
                    IF [CTR366] > 0 AND (COUNT(SCHEDULE = "IDS") = 0) 
                       RETURN VALIDATION MESSAGE
                    ENDIF
                 
                    */
        protected void VRATOCTR430015(List<ProcessMessageDocument> response)
        {
            ProcessMessageDocument processMessage;
            bool assertion = ParentDocument.CTR366.GetValueOrDefault() > 0 && IDSChildDocuments.Count() == 0;
            if (assertion)
            {
                processMessage = new ProcessMessageDocument()
                {
                    Code = "CMN.ATO.CTR.430015",
                    Severity = ProcessMessageSeverity.Error,
                    Description = @"International dealings schedule required",
                    LongDescription = @"International dealings schedule must be attached if royalty expenses overseas amount is greater than zero",
                    Location = "/xbrli:xbrl/tns:Expense.Royalties.Amount[@contextRef='" + ParentDocument.RPJFOREIGNId + "']",
                    Parameters = new ProcessMessageParameters() { new ProcessMessageParameter() { Name = "RuleIdentifier", Value = "VR.ATO.CTR.430015" } },
                };
                processMessage.Parameters.Add(new ProcessMessageParameter { Name = "CTR366", Value = ParentDocument.CTR366.GetValueOrDefault().ToString() });
                response.Add(processMessage);
            }
        }
        #endregion // VR.ATO.CTR.430015

        #region VR.ATO.CTR.500003

        /*  VR.ATO.CTR.500003
              
                   IF [CTR370] = TRUE AND (COUNT(SCHEDULE = "IDS") = 1 AND [IDS425] = TRUE)
                    RETURN VALIDATION MESSAGE
                    ENDIF
              */
        protected void VRATOCTR500003(List<ProcessMessageDocument> response)
        {
            ProcessMessageDocument processMessage;
            bool assertion = ParentDocument.CTR370.GetValueOrDefault() && (IDSChildDocuments.Count() == 1 && IDSChildDocuments.First().IDS425.GetValueOrDefault());
            if (assertion)
            {
                processMessage = new ProcessMessageDocument()
                {
                    Code = "CMN.ATO.CTR.500003",
                    Severity = ProcessMessageSeverity.Error,
                    Description = @"Significant Global Entity question on the International Dealings Schedule (IDS) form must not be 'TRUE'.",
                    LongDescription = @"If the entity has self-assessed as a Significant Global Entity (SGE), then 'Are you a small business entity, not a significant global entity and your international related party dealings do not exceed 50% of your current year aggregated turnover?' must not be 'TRUE' on the International Dealings Schedule (IDS) form.",
                    Location = "/xbrli:xbrl/tns:OrganisationDetails.SignificantGlobalEntityStatus.Indicator",

                    Parameters = new ProcessMessageParameters() { new ProcessMessageParameter() { Name = "RuleIdentifier", Value = "VR.ATO.CTR.500003" } },
                };
                processMessage.Parameters.Add(new ProcessMessageParameter { Name = "CTR370", Value = ParentDocument.CTR370.GetValueOrDefault().ToString() });
                processMessage.Parameters.Add(new ProcessMessageParameter { Name = "IDS425", Value = IDSChildDocuments.First().IDS425.GetValueOrDefault().ToString() });
                response.Add(processMessage);
            }
        }
        #endregion // VR.ATO.CTR.500003

        #endregion //  CTR-IDS

        #region CTR-RPTTAXPOS

        #region VR.ATO.CTR.500002

        /*  VR.ATO.CTR.500002

                    IF ([CTR319] = TRUE) AND (COUNT(SCHEDULE = "RTPS") = 0)
                       RETURN VALIDATION MESSAGE
                    ENDIF

                    */
        protected void VRATOCTR500002(List<ProcessMessageDocument> response)
        {
            ProcessMessageDocument processMessage;

            bool assertion = ParentDocument.CTR319.GetValueOrDefault() && RPTTAXPOSChildDocuments.Count() == 0;
            if (assertion)
            {
                processMessage = new ProcessMessageDocument()
                {
                    Code = "CMN.ATO.CTR.500002",
                    Severity = ProcessMessageSeverity.Error,
                    Description = @"Reportable Tax Position Schedule must be attached",
                    LongDescription = @"Reportable Tax Position Schedule must be attached if there is a 'Yes' response to 'Are you required to lodge a reportable tax position schedule?'",
                    Location = "/xbrli:xbrl/tns:RegulatoryDisclosures.ReportableTaxPosition.Indicator",
                    Parameters = new ProcessMessageParameters() { new ProcessMessageParameter() { Name = "RuleIdentifier", Value = "VR.ATO.CTR.500002" } },
                };


                response.Add(processMessage);
            }
        }
        #endregion // VR.ATO.CTR.500002 


        #region VR.ATO.CTR.500004

        /*  VR.ATO.CTR.500004

                   IF (RP:entity.identifier.TFN <> NULLORBLANK) AND (COUNT(SCHEDULE = "RPTTAXPOS") > 0) AND (RP:entity.identifier.TFN <> [RPTTAXPOS1])
                       RETURN VALIDATION MESSAGE
                    ENDIF

                    [RPTTAXPOS1] = RPTTAXPOS:RP:pyid.02.00:Identifiers.TaxFileNumber.Identifier
                    */
        protected void VRATOCTR500004(List<ProcessMessageDocument> response)
        {
            bool assertion = RPTTAXPOSChildDocuments.Count() > 0 && !ParentDocument.RPIdentifierTFN.Equals(RPTTAXPOSChildDocuments.First().RPIdentifierTFN);

            if (assertion)
            {
                var processMessage = new ProcessMessageDocument
                {
                    Code = "CMN.ATO.GEN.402009",
                    Severity = ProcessMessageSeverity.Error,
                    Description = @"Your supplied TFN does not match the TFN supplied on the form it was submitted with",
                    LongDescription = @"Your supplied TFN does not match the TFN supplied on the parent form it was submitted with",
                    Location = "/xbrli:xbrl/xbrli:context/xbrli:entity/xbrli:identifier",
                    Parameters = new ProcessMessageParameters { new ProcessMessageParameter { Name = "RuleIdentifier", Value = "VR.ATO.CTR.500004" } }
                };
                response.Add(processMessage);
            }
        }
        #endregion // VR.ATO.CTR.500004

        #region VR.ATO.CTR.500005

        /*  VR.ATO.CTR.500005
                   IF [CTR2] <> NULL AND COUNT(SCHEDULE = "RPTTAXPOS") = 1 AND ANY OCCURRENCE OF (RPTTAXPOS:RP:bafot.xx.xx:RegulatoryDisclosures.ReportableTaxPositionCategoryReferenceNumber.Identifier <> CONTAINS [CTR2])
                      RETURN VALIDATION MESSAGE
                    ENDIF

                    [CTR2] = CTR:RP:pyin.02.37:Report.TargetFinancial.Year
            */
        protected void VRATOCTR500005(List<ProcessMessageDocument> response)
        {
            if (RPTTAXPOSChildDocuments.Count() == 1)
            {
                if (RPTTAXPOSChildDocuments.First().ReportableTaxPositionCategoryAAndBCollection != null)
                    response.AddRange(from rptCategoryAAndB in RPTTAXPOSChildDocuments.First().ReportableTaxPositionCategoryAAndBCollection
                                      where rptCategoryAAndB.RPTTAXPOS4 != null && rptCategoryAAndB.RPTTAXPOS4.Substring(0, 4).ToString() != ParentDocument.CTR2.GetValueOrDefault().ToString()
                                      select new ProcessMessageDocument
                                      {
                                          Code = "CMN.ATO.CTR.500005",
                                          Severity = ProcessMessageSeverity.Error,
                                          Description = @"The first four digits of RTP Category Number must refer to your current financial year.",
                                          LongDescription = @"The first four digits of RTP Category Number must refer to your current financial year.",
                                          Location = "/xbrli:xbrl/tns:Report.TargetFinancial.Year",
                                          Parameters = new ProcessMessageParameters() { new ProcessMessageParameter() { Name = "RuleIdentifier", Value = "VR.ATO.CTR.500005" } },
                                      });

                if (RPTTAXPOSChildDocuments.First().ReportableTaxPositionCategoryCCollection != null)
                    response.AddRange(from rptCategoryC in RPTTAXPOSChildDocuments.First().ReportableTaxPositionCategoryCCollection
                                      where rptCategoryC.RPTTAXPOS11 != null && rptCategoryC.RPTTAXPOS11.Substring(0, 4).ToString() != ParentDocument.CTR2.GetValueOrDefault().ToString()
                                      select new ProcessMessageDocument
                                      {
                                          Code = "CMN.ATO.CTR.500005",
                                          Severity = ProcessMessageSeverity.Error,
                                          Description = @"The first four digits of RTP Category Number must refer to your current financial year.",
                                          LongDescription = @"The first four digits of RTP Category Number must refer to your current financial year.",
                                          Location = "/xbrli:xbrl/tns:Report.TargetFinancial.Year",
                                          Parameters = new ProcessMessageParameters() { new ProcessMessageParameter() { Name = "RuleIdentifier", Value = "VR.ATO.CTR.500005" } },
                                      });
            }
        }
        #endregion // VR.ATO.CTR.500005

        #endregion CTR-RPTTAXPOS

        #region CTR-DISTBENTRT

        #region VR.ATO.CTR.500391

        /*  VR.ATO.CTR.500391
            Distributions to Beneficiaries of Trust schedule must be present when Gross distribution from trusts amount is provided

                Legacy Rule Format:
                    IF (COUNT(SCHEDULE= "DISTBENTRT") = 0) AND [CTR61] > 0 
                       RETURN VALIDATION MESSAGE
                    ENDIF

            Technical Business Rule Format:
                    (CountDocument('DISTBENTRT') = 0) AND ^CTR61 > 0 

        Data Elements:
    
            ^CTR61 = RP:TrustDistributionIncome:Income.TrustDistributionGross.Amount
        */
        public void VRATOCTR500391(List<ProcessMessageDocument> response)
        {
            ProcessMessageDocument processMessage;

            bool assertion = DISTBENTRTChildDocuments.Count() == 0 && ParentDocument.CTR61.GetValueOrDefault() > 0;

            if (assertion)
            {
                processMessage = new ProcessMessageDocument()
                {
                    Code = "CMN.ATO.CTR.500391",
                    Severity = ProcessMessageSeverity.Error,
                    Description = @"Distributions to Beneficiaries of Trust schedule must be present",
                    LongDescription = @"Distributions to Beneficiaries of Trust schedule must be present when Gross distribution from trusts amount is provided",
                    Location = "/xbrli:xbrl/tns:TrustDistributionIncome/tns:Income.TrustDistributionGross.Amount",
                    Parameters = new ProcessMessageParameters() { new ProcessMessageParameter() { Name = "RuleIdentifier", Value = "VR.ATO.CTR.500391" },
                                                                { new ProcessMessageParameter() { Name = "CTR61", Value = GetValueOrEmpty(ParentDocument.CTR61) }}}
                };

                response.Add(processMessage);
            }
        }
        #endregion VR.ATO.CTR.500391

        #endregion

        public string OccurrenceIndex(int occurrenceIndex)
        {
            return occurrenceIndex > 0 ? "[" + occurrenceIndex + "]" : "";
        }

        private static string GetValueOrEmpty(bool? val)
        {
            return (val.HasValue) ? val.ToString() : string.Empty;
        }

        private static string GetValueOrEmpty(DateTime? val)
        {
            return (val.HasValue) ? val.ToString() : string.Empty;
        }

        private static string GetValueOrEmpty(decimal? val)
        {
            return (val.HasValue) ? val.ToString() : string.Empty;
        }

        private static string GetValueOrEmpty(int? val)
        {
            return (val.HasValue) ? val.ToString() : string.Empty;
        }
    }
}