
using System;
using System.Collections.Generic;
using Au.Gov.Sbr.Xbrl.Document;
using Au.Gov.Sbr.Xbrl.Metadata;
using System.Linq;
using System.Xml;
using System.Text.RegularExpressions;
using DataContracts;

namespace Ato.EN.IntegrationServices.CodeGenerationCGNFT
{
    public class CGNFT2018Consumer
    {

        private static Regex StripWhitespace = new Regex(@"\s*");

        #region Helper/Validation Methods
        private static bool? ToBoolean(string str)
        {
            bool returnValue;
            string value = (str ?? "").Trim();
            if (value == "0" || value == "1")
                return Convert.ToBoolean(Convert.ToInt32(value));

            if (Boolean.TryParse(value, out returnValue))
                return returnValue;
            return null;
        }

        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;
        }

        /// <summary>
        /// Derives the SBR element location.
        /// </summary>
        /// <param name="sbrElement">The SBR element.</param>
        /// <param name="addOccurrenceIndex">if set to <c>true</c> [add occurrence the occurrence index to the path].</param>
        /// <returns></returns>
        private static string DeriveSbrElementLocation(SBRElement sbrElement, bool addOccurrenceIndex = false)
        {
            if (sbrElement == null) return "/xbrli:xbrl";
            int xpathOccurrence = sbrElement.OccurrenceIndex + 1;
            string location;

            if (addOccurrenceIndex)
            {
                location = "/" + sbrElement.NamespacePrefix + ":" + sbrElement.Name + "[" +
                           xpathOccurrence + "]";
            }
            else
            {
                location = "/" + sbrElement.NamespacePrefix + ":" + sbrElement.Name;
            }

            if (sbrElement.IsInTuple)
            {
                location = DeriveSbrElementLocation(sbrElement.ParentTuple, true) + location;
            }
            else
            {
                location = "/xbrli:xbrl" + location;
            }

            return location;
        }

        private static bool IsMatch(int? field, string expression, RegexOptions options = RegexOptions.None)
        {
            if (field == null)
                return false;
            else
                return Regex.IsMatch(Convert.ToString(field.Value), expression, options);
        }

        private static bool IsMatch(string field, string expression, RegexOptions options = RegexOptions.None)
        {
            if (field == null)
                return false;
            else
                return Regex.IsMatch(field, expression, options);
        }

        public DateTime AsDate(string dateAsString)
        {
            DateTime response = DateTime.MinValue;
            DateTime date;

            if (DateTime.TryParse(dateAsString, out date))
            {
                response = date;
            }

            return response;
        }

        #endregion

        public CGNFT2018 Consume(SBRDocument sbrDocument)
        {
            List<ProcessMessageDocument> errors;
            return Consume(sbrDocument, false, out errors);
        }

        /// <summary>
        /// Allows for validation of rules that can not be generated and must run at a lower level.
        /// A sub-class will need to be created with an override for this method - which does nothing in its base implementation.
        /// </summary>
        /// <param name="sbrDocument">The SBR document.</param>
        /// <param name="populatedReportElementsMap">The populated report elements map can be used to find data elements and tuples.</param>
        /// <param name="contextArray">The context array can be used to find context values.</param>
        /// <param name="errors">The errors collection is to be populated with validation results.</param>
        protected virtual void ValidateUnsupportedRules(SBRDocument sbrDocument, IDictionary<string, SBRElement> populatedReportElementsMap, SBRContext[] contextArray, List<ProcessMessageDocument> errors)
        {

        }

        public CGNFT2018 Consume(SBRDocument sbrDocument, bool validationMode, out List<ProcessMessageDocument> errors)
        {
            CGNFT2018 report;
            report = new CGNFT2018();
            errors = new List<ProcessMessageDocument>();

            SBRContext[] contextArray;
            IDictionary<string, SBRElement> populatedReportElementsMap;

            contextArray = sbrDocument.ContextsMap.Values.ToArray();
            populatedReportElementsMap = sbrDocument.PopulatedChildElementsMap ?? new Dictionary<string, SBRElement>();

            if (validationMode) ValidateUnsupportedRules(sbrDocument, populatedReportElementsMap, contextArray, errors);

            /// <summary>
            /// Current element being extracted
            /// </summary>
            SBRElement currentValue = null;
            /// <summary>
            /// Current elements being extracted
            /// </summary>
            IList<SBRElement> currentValues = null;
            /// <summary>
            /// Current occurrances being extracted
            /// </summary>
            IList<SBRElement> currentOccurrences = null;
            /// <summary>
            /// Working Variable for date time variables
            /// </summary>
            DateTime currentDateTimeValue;
            /// <summary>
            /// Working Variable for boolean variables
            /// </summary>
            bool currentBooleanValue;
            /// <summary>
            /// Working Variable for decimal variables
            /// </summary>
            decimal currentDecimalValue;
            /// <summary>
            /// Working Variable for integer variables
            /// </summary>
            int currentIntValue;
            /// <summary>
            /// Working Variable for long variables
            /// </summary>
            long currentLongValue;
            XmlDocumentFragment currentSegment;
            XmlNamespaceManager currentNamespaceManager;
            XmlNode currentNode;

            #region sbrRPContext
            IEnumerable<SBRContext> sbrRPContexts = null;
            SBRContext sbrRPContext = null;

            sbrRPContexts = contextArray.Where(
                c => c.Period != null && c.Period.PeriodType == SBRPeriod_PeriodType.DURATION &&
                c.Segment != null && c.Segment.ExplicitOrTypedDimensionDomains.Count == 1 &&
                (c.Segment.ExplicitOrTypedDimensionDomains.Any(dd => dd.DimensionType == SBRExplicitOrTypedDimensionDomain_Type.EXPLICIT && dd.Dimension.EndsWith("}ReportPartyTypeDimension") && ((SBRExplicitDimensionDomain)dd).Domain.EndsWith("}ReportingParty"))));
            Dictionary<string, IList<SBRElement>> sbrPopulatedRPElementsMap = new Dictionary<string, IList<SBRElement>>();
            if (sbrRPContexts != null && sbrRPContexts.Count() > 0)
            {
                sbrRPContext = sbrRPContexts.First();

                report.RPId = sbrRPContext.Id;
                report.RPIdentifier = sbrRPContext.EntityIdentifier;
                report.RPIdentifierScheme = sbrRPContext.EntityScheme;

                report.RPCount = sbrRPContexts.Count();
                report.RPExists = true;
                report.RPOccurrenceIndex = Array.IndexOf(contextArray, sbrRPContext) + 1;
                report.RPLastOccurrenceIndex = Array.IndexOf(contextArray, sbrRPContexts.Last()) + 1;


                if (report.RPIdentifierScheme == "http://www.abr.gov.au/abn") report.RPIdentifierABN = report.RPIdentifier;

                report.RPStartDate = ((SBRDurationPeriod)sbrRPContext.Period).DurationStartAsDateObject;
                report.RPEndDate = ((SBRDurationPeriod)sbrRPContext.Period).DurationEndAsDateObject;

                sbrPopulatedRPElementsMap = new System.Collections.Generic.Dictionary<string, IList<SBRElement>>();
                for (int i = 0; i < sbrRPContexts.Count(); i++)
                {
                    sbrRPContext = sbrRPContexts.ElementAt(i);

                    IList<SBRElement> elements = sbrDocument.ElementsByContextId[sbrRPContext.Id];
                    if (elements != null)
                    {
                        for (int e = 0; e < elements.Count(); e++)
                        {
                            SBRElement currentElement = elements[e];
                            if (currentElement == null || currentElement.IsInTuple) continue; // Don't add tuple elements here, they will be found through a different map.
                            if (sbrPopulatedRPElementsMap.ContainsKey("{" + currentElement.Namespace + "}" + currentElement.Name))
                            {
                                sbrPopulatedRPElementsMap["{" + currentElement.Namespace + "}" + currentElement.Name].Add(currentElement);
                            }
                            else
                            {
                                sbrPopulatedRPElementsMap.Add("{" + currentElement.Namespace + "}" + currentElement.Name, new List<SBRElement> { currentElement });
                            }
                        }
                    }
                    report.CGNFT32 = report.RPIdentifier;

                    if (sbrPopulatedRPElementsMap.TryGetValue("{http://www.sbr.gov.au/ato/cgnft}Identifiers.TaxFileNumber.Identifier", out currentValues))
                    {
                        if (!currentValues[0].IsNil) report.CGNFT3 = currentValues[0].Value;
                    }

                    if (sbrPopulatedRPElementsMap.TryGetValue("{http://www.sbr.gov.au/ato/cgnft}OrganisationNameDetails.OrganisationalName.Text", out currentValues))
                    {
                        if (!currentValues[0].IsNil) report.CGNFT4 = currentValues[0].Value;
                    }

                    if (sbrPopulatedRPElementsMap.TryGetValue("{http://www.sbr.gov.au/ato/cgnft}OrganisationDetails.TaxConsolidation.Date", out currentValues))
                    {
                        if (!currentValues[0].IsNil) report.CGNFT6 = DateTime.Parse(currentValues[0].Value);
                    }

                    if (sbrPopulatedRPElementsMap.TryGetValue("{http://www.sbr.gov.au/ato/cgnft}OrganisationDetails.TaxConsolidationMultipleEntryConsolidatedGroup.Indicator", out currentValues))
                    {
                        if (!currentValues[0].IsNil) report.CGNFT7 = ToBoolean(currentValues[0].Value);
                    }
                }
            }
            #endregion End of Context sbrRPContext

            #region sbrCPContext
            IEnumerable<SBRContext> sbrCPContexts = null;
            SBRContext sbrCPContext = null;

            sbrCPContexts = contextArray.Where(
                c => c.Period != null && c.Period.PeriodType == SBRPeriod_PeriodType.DURATION &&
                c.Segment != null && c.Segment.ExplicitOrTypedDimensionDomains.Count == 1 &&
                (c.Segment.ExplicitOrTypedDimensionDomains.Any(dd => dd.DimensionType == SBRExplicitOrTypedDimensionDomain_Type.EXPLICIT && dd.Dimension.EndsWith("}ReportPartyTypeDimension") && ((SBRExplicitDimensionDomain)dd).Domain.EndsWith("}ConsolidatedParty"))));
            Dictionary<string, IList<SBRElement>> sbrPopulatedCPElementsMap = new Dictionary<string, IList<SBRElement>>();
            if (sbrCPContexts != null && sbrCPContexts.Count() > 0)
            {

                report.CPContextCollection = new List<CGNFT2018.CPContext>();
                for (int i = 0; i < sbrCPContexts.Count(); i++)
                {
                    sbrCPContext = sbrCPContexts.ElementAt(i);
                    CGNFT2018.CPContext cpContext = new CGNFT2018.CPContext();
                    report.CPContextCollection.Add(cpContext);

                    cpContext.Id = sbrCPContext.Id;
                    cpContext.Identifier = sbrCPContext.EntityIdentifier;
                    cpContext.IdentifierScheme = sbrCPContext.EntityScheme;

                    cpContext.Count = sbrCPContexts.Count();
                    cpContext.Exists = true;
                    cpContext.OccurrenceIndex = Array.IndexOf(contextArray, sbrCPContext) + 1;
                    cpContext.LastOccurrenceIndex = Array.IndexOf(contextArray, sbrCPContexts.Last()) + 1;


                    if (cpContext.IdentifierScheme == "http://www.ato.gov.au/tfn") cpContext.IdentifierTFN = cpContext.Identifier;

                    cpContext.StartDate = ((SBRDurationPeriod)sbrCPContext.Period).DurationStartAsDateObject;
                    cpContext.EndDate = ((SBRDurationPeriod)sbrCPContext.Period).DurationEndAsDateObject;

                    sbrPopulatedCPElementsMap = new System.Collections.Generic.Dictionary<string, IList<SBRElement>>();

                    IList<SBRElement> elements = sbrDocument.ElementsByContextId[sbrCPContext.Id];
                    if (elements != null)
                    {
                        for (int e = 0; e < elements.Count(); e++)
                        {
                            SBRElement currentElement = elements[e];
                            if (currentElement == null) continue; // Don't add tuple elements here, they will be found through a different map.
                            if (sbrPopulatedCPElementsMap.ContainsKey("{" + currentElement.Namespace + "}" + currentElement.Name))
                            {
                                sbrPopulatedCPElementsMap["{" + currentElement.Namespace + "}" + currentElement.Name].Add(currentElement);
                            }
                            else
                            {
                                sbrPopulatedCPElementsMap.Add("{" + currentElement.Namespace + "}" + currentElement.Name, new List<SBRElement> { currentElement });
                            }
                        }
                    }
                    cpContext.CGNFT33 = cpContext.Identifier;

                    if (sbrPopulatedCPElementsMap.TryGetValue("{http://www.sbr.gov.au/ato/cgnft}OrganisationNameDetails.OrganisationalName.Text", out currentValues))
                    {
                        if (!currentValues[0].IsNil) cpContext.CGNFT10 = currentValues[0].Value;
                    }

                    if (sbrPopulatedCPElementsMap.TryGetValue("{http://www.sbr.gov.au/ato/cgnft}Identifiers.AustralianBusinessNumber.Identifier", out currentValues))
                    {
                        if (!currentValues[0].IsNil) cpContext.CGNFT11 = currentValues[0].Value;
                    }

                    if (sbrPopulatedCPElementsMap.TryGetValue("{http://www.sbr.gov.au/ato/cgnft}Identifiers.AustralianRegisteredBodyNumber.Identifier", out currentValues))
                    {
                        if (!currentValues[0].IsNil) cpContext.CGNFT12 = currentValues[0].Value;
                    }

                    if (sbrPopulatedCPElementsMap.TryGetValue("{http://www.sbr.gov.au/ato/cgnft}Identifiers.AustralianCompanyNumber.Identifier", out currentValues))
                    {
                        if (!currentValues[0].IsNil) cpContext.CGNFT13 = currentValues[0].Value;
                    }

                    if (sbrPopulatedCPElementsMap.TryGetValue("{http://www.sbr.gov.au/ato/cgnft}OrganisationDetails.TaxConsolidationSubsidiaryMemberEntry.Date", out currentValues))
                    {
                        if (!currentValues[0].IsNil) cpContext.CGNFT14 = DateTime.Parse(currentValues[0].Value);
                    }

                    if (sbrPopulatedCPElementsMap.TryGetValue("{http://www.sbr.gov.au/ato/cgnft}OrganisationDetails.TaxConsolidationSubsidiaryMemberExit.Date", out currentValues))
                    {
                        if (!currentValues[0].IsNil) cpContext.CGNFT15 = DateTime.Parse(currentValues[0].Value);
                    }

                    if (sbrPopulatedCPElementsMap.TryGetValue("{http://www.sbr.gov.au/ato/cgnft}OrganisationDetails.TaxConsolidationSubsidiaryMemberExit.Code", out currentValues))
                    {
                        if (!currentValues[0].IsNil) cpContext.CGNFT16 = currentValues[0].Value;
                    }

                    if (sbrPopulatedCPElementsMap.TryGetValue("{http://www.sbr.gov.au/ato/cgnft}OrganisationDetails.TaxConsolidationSubsidiaryMemberExit.Description", out currentValues))
                    {
                        if (!currentValues[0].IsNil) cpContext.CGNFT17 = currentValues[0].Value;
                    }
                }
            }
            #endregion End of Context sbrCPContext

            #region sbrCPPEContext
            IEnumerable<SBRContext> sbrCPPEContexts = null;
            SBRContext sbrCPPEContext = null;

            sbrCPPEContexts = contextArray.Where(
            c => c.Period != null && c.Period.PeriodType == SBRPeriod_PeriodType.DURATION &&
            c.Segment != null && c.Segment.ExplicitOrTypedDimensionDomains.Count == 2 &&
            (c.Segment.ExplicitOrTypedDimensionDomains.Any(dd => dd.DimensionType == SBRExplicitOrTypedDimensionDomain_Type.EXPLICIT && dd.Dimension.EndsWith("}ReportPartyTypeDimension") && ((SBRExplicitDimensionDomain)dd).Domain.EndsWith("}ConsolidatedParty")) &&
            (c.Segment.ExplicitOrTypedDimensionDomains.Any(dd => dd.DimensionType == SBRExplicitOrTypedDimensionDomain_Type.EXPLICIT && dd.Dimension.EndsWith("}SecondaryPartyTypeDimension") && ((SBRExplicitDimensionDomain)dd).Domain.EndsWith("}PurchasingEntity")))));
            Dictionary<string, IList<SBRElement>> sbrPopulatedCPPEElementsMap = new Dictionary<string, IList<SBRElement>>();
            if (sbrCPPEContexts != null && sbrCPPEContexts.Count() > 0)
            {
                report.CPPEContextCollection = new List<CGNFT2018.CPPEContext>();
                for (int i = 0; i < sbrCPPEContexts.Count(); i++)
                {
                    sbrCPPEContext = sbrCPPEContexts.ElementAt(i);
                    CGNFT2018.CPPEContext cppeContext = new CGNFT2018.CPPEContext();
                    report.CPPEContextCollection.Add(cppeContext);

                    cppeContext.CPPEId = sbrCPPEContext.Id;
                    cppeContext.CPPEIdentifier = sbrCPPEContext.EntityIdentifier;
                    cppeContext.CPPEIdentifierScheme = sbrCPPEContext.EntityScheme;

                    cppeContext.CPPECount = sbrCPPEContexts.Count();
                    cppeContext.CPPEExists = true;
                    cppeContext.CPPEOccurrenceIndex = Array.IndexOf(contextArray, sbrCPPEContext) + 1;
                    cppeContext.CPPELastOccurrenceIndex = Array.IndexOf(contextArray, sbrCPPEContexts.Last()) + 1;


                    if (cppeContext.CPPEIdentifierScheme == "http://www.ato.gov.au/tfn") cppeContext.CPPEIdentifierTFN = cppeContext.CPPEIdentifier;

                    cppeContext.CPPEStartDate = ((SBRDurationPeriod)sbrCPPEContext.Period).DurationStartAsDateObject;
                    cppeContext.CPPEEndDate = ((SBRDurationPeriod)sbrCPPEContext.Period).DurationEndAsDateObject;

                    sbrPopulatedCPPEElementsMap = new System.Collections.Generic.Dictionary<string, IList<SBRElement>>();

                    IList<SBRElement> elements = sbrDocument.ElementsByContextId[sbrCPPEContext.Id];
                    if (elements != null)
                    {
                        for (int e = 0; e < elements.Count(); e++)
                        {
                            SBRElement currentElement = elements[e];
                            if (currentElement == null) continue; // Don't add tuple elements here, they will be found through a different map.
                            if (sbrPopulatedCPPEElementsMap.ContainsKey("{" + currentElement.Namespace + "}" + currentElement.Name))
                            {
                                sbrPopulatedCPPEElementsMap["{" + currentElement.Namespace + "}" + currentElement.Name].Add(currentElement);
                            }
                            else
                            {
                                sbrPopulatedCPPEElementsMap.Add("{" + currentElement.Namespace + "}" + currentElement.Name, new List<SBRElement> { currentElement });
                            }
                        }
                    }

                    if (sbrPopulatedCPPEElementsMap.TryGetValue("{http://www.sbr.gov.au/ato/cgnft}OrganisationNameDetails.OrganisationalName.Text", out currentValues))
                    {
                        if (!currentValues[0].IsNil) cppeContext.CGNFT19 = currentValues[0].Value;
                    }

                    if (sbrPopulatedCPPEElementsMap.TryGetValue("{http://www.sbr.gov.au/ato/cgnft}Identifiers.AustralianBusinessNumber.Identifier", out currentValues))
                    {
                        if (!currentValues[0].IsNil) cppeContext.CGNFT20 = currentValues[0].Value;
                    }

                    if (sbrPopulatedCPPEElementsMap.TryGetValue("{http://www.sbr.gov.au/ato/cgnft}Identifiers.AustralianRegisteredBodyNumber.Identifier", out currentValues))
                    {
                        if (!currentValues[0].IsNil) cppeContext.CGNFT27 = currentValues[0].Value;
                    }

                    if (report.CPContextCollection != null && report.CPContextCollection.Any(cp => cp.Identifier == cppeContext.CPPEIdentifier && string.IsNullOrEmpty(cp.CPPEContext.CPPEIdentifier)))
                    {
                        report.CPContextCollection.First(cp => cp.Identifier == cppeContext.CPPEIdentifier && string.IsNullOrEmpty(cp.CPPEContext.CPPEIdentifier)).CPPEContext = cppeContext;
                    }
                }
            }
            #endregion End of Context sbrCPPEContext

            //#region sbrCPPEContext
            //IEnumerable<SBRContext> sbrCPPEContexts = null;
            //SBRContext sbrCPPEContext = null;

            //sbrCPPEContexts = contextArray.Where(
            //    c => c.Period != null && c.Period.PeriodType == SBRPeriod_PeriodType.DURATION &&
            //    c.Segment != null && c.Segment.ExplicitOrTypedDimensionDomains.Count == 2 &&
            //    (c.Segment.ExplicitOrTypedDimensionDomains.Any(dd => dd.DimensionType == SBRExplicitOrTypedDimensionDomain_Type.EXPLICIT && dd.Dimension.EndsWith("}ReportPartyTypeDimension") && ((SBRExplicitDimensionDomain)dd).Domain.EndsWith("}ConsolidatedParty")) &&
            //    (c.Segment.ExplicitOrTypedDimensionDomains.Any(dd => dd.DimensionType == SBRExplicitOrTypedDimensionDomain_Type.EXPLICIT && dd.Dimension.EndsWith("}SecondaryPartyTypeDimension") && ((SBRExplicitDimensionDomain)dd).Domain.EndsWith("}PurchasingEntity")))));
            //Dictionary<string, IList<SBRElement>> sbrPopulatedCPPEElementsMap = new Dictionary<string, IList<SBRElement>>();
            //if (sbrCPPEContexts != null && sbrCPPEContexts.Count() > 0)
            //{
            //    sbrCPPEContext = sbrCPPEContexts.First();

            //    report.CPPEId = sbrCPPEContext.Id;
            //    report.CPPEIdentifier = sbrCPPEContext.EntityIdentifier;
            //    report.CPPEIdentifierScheme = sbrCPPEContext.EntityScheme;

            //    report.CPPECount = sbrCPPEContexts.Count();
            //    report.CPPEExists = true;
            //    report.CPPEOccurrenceIndex = Array.IndexOf(contextArray, sbrCPPEContext) + 1;
            //    report.CPPELastOccurrenceIndex = Array.IndexOf(contextArray, sbrCPPEContexts.Last()) + 1;


            //    if (report.CPPEIdentifierScheme == "http://www.ato.gov.au/tfn") report.CPPEIdentifierTFN = report.CPPEIdentifier;

            //    report.CPPEStartDate = ((SBRDurationPeriod)sbrCPPEContext.Period).DurationStartAsDateObject;
            //    report.CPPEEndDate = ((SBRDurationPeriod)sbrCPPEContext.Period).DurationEndAsDateObject;

            //    sbrPopulatedCPPEElementsMap = new System.Collections.Generic.Dictionary<string, IList<SBRElement>>();
            //    for (int i = 0; i < sbrCPPEContexts.Count(); i++)
            //    {
            //        sbrCPPEContext = sbrCPPEContexts.ElementAt(i);

            //        IList<SBRElement> elements = sbrDocument.ElementsByContextId[sbrCPPEContext.Id];
            //        if (elements != null)
            //        {
            //            for (int e = 0; e < elements.Count(); e++)
            //            {
            //                SBRElement currentElement = elements[e];
            //                if (currentElement == null || currentElement.IsInTuple) continue; // Don't add tuple elements here, they will be found through a different map.
            //                if (sbrPopulatedCPPEElementsMap.ContainsKey("{" + currentElement.Namespace + "}" + currentElement.Name))
            //                {
            //                    sbrPopulatedCPPEElementsMap["{" + currentElement.Namespace + "}" + currentElement.Name].Add(currentElement);
            //                }
            //                else
            //                {
            //                    sbrPopulatedCPPEElementsMap.Add("{" + currentElement.Namespace + "}" + currentElement.Name, new List<SBRElement> { currentElement });
            //                }
            //            }
            //        }

            //        if (sbrPopulatedCPPEElementsMap.TryGetValue("{http://www.sbr.gov.au/ato/cgnft}OrganisationNameDetails.OrganisationalName.Text", out currentValues))
            //        {
            //            if (!currentValues[0].IsNil) report.CGNFT19 = currentValues[0].Value;
            //        }

            //        if (sbrPopulatedCPPEElementsMap.TryGetValue("{http://www.sbr.gov.au/ato/cgnft}Identifiers.AustralianBusinessNumber.Identifier", out currentValues))
            //        {
            //            if (!currentValues[0].IsNil) report.CGNFT20 = currentValues[0].Value;
            //        }

            //        if (sbrPopulatedCPPEElementsMap.TryGetValue("{http://www.sbr.gov.au/ato/cgnft}Identifiers.AustralianRegisteredBodyNumber.Identifier", out currentValues))
            //        {
            //            if (!currentValues[0].IsNil) report.CGNFT27 = currentValues[0].Value;
            //        }
            //    }
            //}
            //#endregion End of Context sbrCPPEContext

            #region sbrRPTrueAndCorrectContext
            IEnumerable<SBRContext> sbrRPTrueAndCorrectContexts = null;
            SBRContext sbrRPTrueAndCorrectContext = null;

            sbrRPTrueAndCorrectContexts = contextArray.Where(
                c => c.Period != null && c.Period.PeriodType == SBRPeriod_PeriodType.DURATION &&
                c.Segment != null && c.Segment.ExplicitOrTypedDimensionDomains.Count == 2 &&
                (c.Segment.ExplicitOrTypedDimensionDomains.Any(dd => dd.DimensionType == SBRExplicitOrTypedDimensionDomain_Type.EXPLICIT && dd.Dimension.EndsWith("}ReportPartyTypeDimension") && ((SBRExplicitDimensionDomain)dd).Domain.EndsWith("}ReportingParty")) &&
                (c.Segment.ExplicitOrTypedDimensionDomains.Any(dd => dd.DimensionType == SBRExplicitOrTypedDimensionDomain_Type.EXPLICIT && dd.Dimension.EndsWith("}DeclarationTypeDimension") && ((SBRExplicitDimensionDomain)dd).Domain.EndsWith("}TrueAndCorrect")))));
            Dictionary<string, IList<SBRElement>> sbrPopulatedRPTrueAndCorrectElementsMap = new Dictionary<string, IList<SBRElement>>();
            if (sbrRPTrueAndCorrectContexts != null && sbrRPTrueAndCorrectContexts.Count() > 0)
            {
                sbrRPTrueAndCorrectContext = sbrRPTrueAndCorrectContexts.First();

                report.RPTrueAndCorrectId = sbrRPTrueAndCorrectContext.Id;
                report.RPTrueAndCorrectIdentifier = sbrRPTrueAndCorrectContext.EntityIdentifier;
                report.RPTrueAndCorrectIdentifierScheme = sbrRPTrueAndCorrectContext.EntityScheme;

                report.RPTrueAndCorrectCount = sbrRPTrueAndCorrectContexts.Count();
                report.RPTrueAndCorrectExists = true;
                report.RPTrueAndCorrectOccurrenceIndex = Array.IndexOf(contextArray, sbrRPTrueAndCorrectContext) + 1;
                report.RPTrueAndCorrectLastOccurrenceIndex = Array.IndexOf(contextArray, sbrRPTrueAndCorrectContexts.Last()) + 1;


                if (report.RPTrueAndCorrectIdentifierScheme == "http://www.abr.gov.au/abn") report.RPTrueAndCorrectIdentifierABN = report.RPTrueAndCorrectIdentifier;

                report.RPTrueAndCorrectStartDate = ((SBRDurationPeriod)sbrRPTrueAndCorrectContext.Period).DurationStartAsDateObject;
                report.RPTrueAndCorrectEndDate = ((SBRDurationPeriod)sbrRPTrueAndCorrectContext.Period).DurationEndAsDateObject;

                sbrPopulatedRPTrueAndCorrectElementsMap = new System.Collections.Generic.Dictionary<string, IList<SBRElement>>();
                for (int i = 0; i < sbrRPTrueAndCorrectContexts.Count(); i++)
                {
                    sbrRPTrueAndCorrectContext = sbrRPTrueAndCorrectContexts.ElementAt(i);

                    IList<SBRElement> elements = sbrDocument.ElementsByContextId[sbrRPTrueAndCorrectContext.Id];
                    if (elements != null)
                    {
                        for (int e = 0; e < elements.Count(); e++)
                        {
                            SBRElement currentElement = elements[e];
                            if (currentElement == null || currentElement.IsInTuple) continue; // Don't add tuple elements here, they will be found through a different map.
                            if (sbrPopulatedRPTrueAndCorrectElementsMap.ContainsKey("{" + currentElement.Namespace + "}" + currentElement.Name))
                            {
                                sbrPopulatedRPTrueAndCorrectElementsMap["{" + currentElement.Namespace + "}" + currentElement.Name].Add(currentElement);
                            }
                            else
                            {
                                sbrPopulatedRPTrueAndCorrectElementsMap.Add("{" + currentElement.Namespace + "}" + currentElement.Name, new List<SBRElement> { currentElement });
                            }
                        }
                    }
                    report.CGNFT34 = report.RPTrueAndCorrectIdentifier;

                    if (sbrPopulatedRPTrueAndCorrectElementsMap.TryGetValue("{http://www.sbr.gov.au/ato/cgnft}PersonUnstructuredName.FullName.Text", out currentValues))
                    {
                        if (!currentValues[0].IsNil) report.CGNFT23 = currentValues[0].Value;
                    }

                    if (sbrPopulatedRPTrueAndCorrectElementsMap.TryGetValue("{http://www.sbr.gov.au/ato/cgnft}PersonNameDetails.Position.Text", out currentValues))
                    {
                        if (!currentValues[0].IsNil) report.CGNFT24 = currentValues[0].Value;
                    }

                    if (sbrPopulatedRPTrueAndCorrectElementsMap.TryGetValue("{http://www.sbr.gov.au/ato/cgnft}ElectronicContact.Telephone.Area.Code", out currentValues))
                    {
                        if (!currentValues[0].IsNil) report.CGNFT25 = currentValues[0].Value;
                    }

                    if (sbrPopulatedRPTrueAndCorrectElementsMap.TryGetValue("{http://www.sbr.gov.au/ato/cgnft}ElectronicContact.Telephone.Minimal.Number", out currentValues))
                    {
                        if (!currentValues[0].IsNil) report.CGNFT26 = currentValues[0].Value;
                    }

                    if (sbrPopulatedRPTrueAndCorrectElementsMap.TryGetValue("{http://www.sbr.gov.au/ato/cgnft}Identifiers.TaxAgentNumber.Identifier", out currentValues))
                    {
                        if (!currentValues[0].IsNil) report.CGNFT28 = currentValues[0].Value;
                    }

                    if (sbrPopulatedRPTrueAndCorrectElementsMap.TryGetValue("{http://www.sbr.gov.au/ato/cgnft}Declaration.Signature.Date", out currentValues))
                    {
                        if (!currentValues[0].IsNil) report.CGNFT29 = DateTime.Parse(currentValues[0].Value);
                    }

                    if (sbrPopulatedRPTrueAndCorrectElementsMap.TryGetValue("{http://www.sbr.gov.au/ato/cgnft}Declaration.StatementAccepted.Indicator", out currentValues))
                    {
                        if (!currentValues[0].IsNil) report.CGNFT30 = ToBoolean(currentValues[0].Value);
                    }

                    if (sbrPopulatedRPTrueAndCorrectElementsMap.TryGetValue("{http://www.sbr.gov.au/ato/cgnft}Declaration.SignatoryIdentifier.Text", out currentValues))
                    {
                        if (!currentValues[0].IsNil) report.CGNFT31 = currentValues[0].Value;
                    }
                }
            }
            #endregion End of Context sbrRPTrueAndCorrectContext

            #region sbrINTTrueAndCorrectContext
            IEnumerable<SBRContext> sbrINTTrueAndCorrectContexts = null;
            SBRContext sbrINTTrueAndCorrectContext = null;

            sbrINTTrueAndCorrectContexts = contextArray.Where(
                c => c.Period != null && c.Period.PeriodType == SBRPeriod_PeriodType.DURATION &&
                c.Segment != null && c.Segment.ExplicitOrTypedDimensionDomains.Count == 2 &&
                (c.Segment.ExplicitOrTypedDimensionDomains.Any(dd => dd.DimensionType == SBRExplicitOrTypedDimensionDomain_Type.EXPLICIT && dd.Dimension.EndsWith("}ReportPartyTypeDimension") && ((SBRExplicitDimensionDomain)dd).Domain.EndsWith("}Intermediary")) &&
                (c.Segment.ExplicitOrTypedDimensionDomains.Any(dd => dd.DimensionType == SBRExplicitOrTypedDimensionDomain_Type.EXPLICIT && dd.Dimension.EndsWith("}DeclarationTypeDimension") && ((SBRExplicitDimensionDomain)dd).Domain.EndsWith("}TrueAndCorrect")))));
            Dictionary<string, IList<SBRElement>> sbrPopulatedINTTrueAndCorrectElementsMap = new Dictionary<string, IList<SBRElement>>();
            if (sbrINTTrueAndCorrectContexts != null && sbrINTTrueAndCorrectContexts.Count() > 0)
            {
                sbrINTTrueAndCorrectContext = sbrINTTrueAndCorrectContexts.First();

                report.INTTrueAndCorrectId = sbrINTTrueAndCorrectContext.Id;
                report.INTTrueAndCorrectIdentifier = sbrINTTrueAndCorrectContext.EntityIdentifier;
                report.INTTrueAndCorrectIdentifierScheme = sbrINTTrueAndCorrectContext.EntityScheme;

                report.INTTrueAndCorrectCount = sbrINTTrueAndCorrectContexts.Count();
                report.INTTrueAndCorrectExists = true;
                report.INTTrueAndCorrectOccurrenceIndex = Array.IndexOf(contextArray, sbrINTTrueAndCorrectContext) + 1;
                report.INTTrueAndCorrectLastOccurrenceIndex = Array.IndexOf(contextArray, sbrINTTrueAndCorrectContexts.Last()) + 1;


                if (report.INTTrueAndCorrectIdentifierScheme == "http://www.abr.gov.au/abn") report.INTTrueAndCorrectIdentifierABN = report.INTTrueAndCorrectIdentifier;

                report.INTTrueAndCorrectStartDate = ((SBRDurationPeriod)sbrINTTrueAndCorrectContext.Period).DurationStartAsDateObject;
                report.INTTrueAndCorrectEndDate = ((SBRDurationPeriod)sbrINTTrueAndCorrectContext.Period).DurationEndAsDateObject;

                sbrPopulatedINTTrueAndCorrectElementsMap = new System.Collections.Generic.Dictionary<string, IList<SBRElement>>();
                for (int i = 0; i < sbrINTTrueAndCorrectContexts.Count(); i++)
                {
                    sbrINTTrueAndCorrectContext = sbrINTTrueAndCorrectContexts.ElementAt(i);

                    IList<SBRElement> elements = sbrDocument.ElementsByContextId[sbrINTTrueAndCorrectContext.Id];
                    if (elements != null)
                    {
                        for (int e = 0; e < elements.Count(); e++)
                        {
                            SBRElement currentElement = elements[e];
                            if (currentElement == null || currentElement.IsInTuple) continue; // Don't add tuple elements here, they will be found through a different map.
                            if (sbrPopulatedINTTrueAndCorrectElementsMap.ContainsKey("{" + currentElement.Namespace + "}" + currentElement.Name))
                            {
                                sbrPopulatedINTTrueAndCorrectElementsMap["{" + currentElement.Namespace + "}" + currentElement.Name].Add(currentElement);
                            }
                            else
                            {
                                sbrPopulatedINTTrueAndCorrectElementsMap.Add("{" + currentElement.Namespace + "}" + currentElement.Name, new List<SBRElement> { currentElement });
                            }
                        }
                    }
                    report.CGNFT35 = report.INTTrueAndCorrectIdentifier;

                    if (sbrPopulatedINTTrueAndCorrectElementsMap.TryGetValue("{http://www.sbr.gov.au/ato/cgnft}PersonUnstructuredName.FullName.Text", out currentValues))
                    {
                        if (!currentValues[0].IsNil) report.CGNFT36 = currentValues[0].Value;
                    }

                    if (sbrPopulatedINTTrueAndCorrectElementsMap.TryGetValue("{http://www.sbr.gov.au/ato/cgnft}PersonNameDetails.Position.Text", out currentValues))
                    {
                        if (!currentValues[0].IsNil) report.CGNFT37 = currentValues[0].Value;
                    }

                    if (sbrPopulatedINTTrueAndCorrectElementsMap.TryGetValue("{http://www.sbr.gov.au/ato/cgnft}ElectronicContact.Telephone.Area.Code", out currentValues))
                    {
                        if (!currentValues[0].IsNil) report.CGNFT38 = currentValues[0].Value;
                    }

                    if (sbrPopulatedINTTrueAndCorrectElementsMap.TryGetValue("{http://www.sbr.gov.au/ato/cgnft}ElectronicContact.Telephone.Minimal.Number", out currentValues))
                    {
                        if (!currentValues[0].IsNil) report.CGNFT39 = currentValues[0].Value;
                    }

                    if (sbrPopulatedINTTrueAndCorrectElementsMap.TryGetValue("{http://www.sbr.gov.au/ato/cgnft}Identifiers.TaxAgentNumber.Identifier", out currentValues))
                    {
                        if (!currentValues[0].IsNil) report.CGNFT40 = currentValues[0].Value;
                    }

                    if (sbrPopulatedINTTrueAndCorrectElementsMap.TryGetValue("{http://www.sbr.gov.au/ato/cgnft}Declaration.Signature.Date", out currentValues))
                    {
                        if (!currentValues[0].IsNil) report.CGNFT41 = DateTime.Parse(currentValues[0].Value);
                    }

                    if (sbrPopulatedINTTrueAndCorrectElementsMap.TryGetValue("{http://www.sbr.gov.au/ato/cgnft}Declaration.StatementAccepted.Indicator", out currentValues))
                    {
                        if (!currentValues[0].IsNil) report.CGNFT42 = ToBoolean(currentValues[0].Value);
                    }

                    if (sbrPopulatedINTTrueAndCorrectElementsMap.TryGetValue("{http://www.sbr.gov.au/ato/cgnft}Declaration.SignatoryIdentifier.Text", out currentValues))
                    {
                        if (!currentValues[0].IsNil) report.CGNFT43 = currentValues[0].Value;
                    }
                }
            }
            #endregion End of Context sbrINTTrueAndCorrectContext
            return report;

        } // Of Consume Method
    } // Of Class
} // Of Namespace