private static CoreDataSetProvider Provider(int id)
 {
     Area area = new Area { AreaTypeId = id };
     var provider = new CoreDataSetProviderFactory().New(area);
     return provider;
 }
        public override IWorkbook BuildWorkbook()
        {
            writer = new PracticeProfileDataWriter(AreaTypeId);

            CheckParameters();

            Area area = areasReader.GetAreaFromCode(AreaCode);

            IList<string> practiceCodes = GetPracticeCodes(area);
            writer.AddPracticeCodes(practiceCodes);

            InitPracticeToParentAreaMaps(area, practiceCodes);

            IList<IndicatorMetadata> metadataList;
            writer.AddParentsToPracticeSheet(practiceCodeToParentMap, false);
            IEnumerable<Area> parentAreas = GetUniqueAreaCodesOfValues(practiceCodeToParentMap);
            parentAreas = from a in parentAreas orderby a.Name select a;
            writer.AddAreaNamesCodestoParentAreaSheet(parentAreas, AreaTypeId);

            coreDataSetProviderFactory = new CoreDataSetProviderFactory
            {
                CcgPopulationProvider = new CcgPopulationProvider(pholioReader)
            };

            metadataList = usePopulationData ? AddPopulationData(area, parentAreas) : AddTopicData(area, parentAreas);

            writer.AddIndicatorMetadata(metadataList);
            AddPracticeAddresses(area, practiceCodes);

            writer.FinaliseBeforeWrite();

            return writer.Workbook;
        }
        private void WriteCoreData(GroupData data, ParentArea parentArea)
        {
            if (data.IsDataOk)
            {
                var valueNoteLookUp = ValueNotes.ToDictionary(x => x.Id, x => x.Text);

                // Child areas
                var childAreaCodes = data.Areas.Select(x => x.Code).ToArray();
                var childAreaCodeToAreaMap = data.Areas.ToDictionary(area => area.Code);

                // Worksheets
                WorksheetInfo childAreaWorksheet = _profileDataWriter.GetWorksheetInfo(_childAreaTypeSheetName);
                WorksheetInfo subnationalWorksheet = _profileDataWriter.GetWorksheetInfo(_subnationalAreaTypeSheetName);
                WorksheetInfo nationalWorksheet = _profileDataWriter.GetWorksheetInfo(NationalLabel);

                // Subnational areas
                ParentDataWriter parentDataWriter = ParentDataWriterFactory.New(_areasReader, _groupDataReader,
                    subnationalWorksheet, _profileDataWriter, _subnationalAreaType);
                var parentAreaDataProvider = new CoreDataSetProviderFactory().New(_parentArea);

                // No subnational sheet if direct parent area is country
                var isSubnationalSheet = subnationalWorksheet != null;

                var areMultipleSubnationalAreasRequired = AreMultipleSubnationalAreasRequired();

                foreach (var groupRoot in data.GroupRoots)
                {
                    // Check this data has not already been writen
                    var key = new GroupRootUniqueKey(groupRoot).Key + parentArea.AreaCode;
                    if (_groupRootKeys.Contains(key))
                    {
                        // This added has already been written
                        continue;
                    }
                    _groupRootKeys.Add(key);

                    var indicatorMetadata = data.GetIndicatorMetadataById(groupRoot.IndicatorId);

                    // Adding here means order in metadata sheet is same as in data sheet
                    AddMetadata(indicatorMetadata);

                    var timePeriodFormatter = new TimePeriodTextFormatter(indicatorMetadata);
                    var coreDataCollector = new CoreDataCollector();

                    var grouping = groupRoot.Grouping.FirstOrDefault();
                    if (grouping != null)
                    {
                        var sex = _labelReader.LookUpSexLabel(grouping.SexId);
                        var age = _labelReader.LookUpAgeLabel(grouping.AgeId);

                        var timePeriods = grouping.GetTimePeriodIterator(indicatorMetadata.YearType).TimePeriods;

                        // Write core data
                        foreach (TimePeriod timePeriod in timePeriods)
                        {
                            string timeString = timePeriodFormatter.Format(timePeriod);

                            var rowLabels = new RowLabels
                            {
                                Age = age,
                                Sex = sex,
                                TimePeriod = timeString,
                                IndicatorName = indicatorMetadata.Descriptive[IndicatorMetadataTextColumnNames.Name],
                                ValueNoteLookUp = valueNoteLookUp
                            };

                            // Write child area data
                            var coreDataList = _groupDataReader.GetCoreData(grouping, timePeriod, childAreaCodes);
                            _profileDataWriter.AddData(childAreaWorksheet, rowLabels, coreDataList, childAreaCodeToAreaMap, _areaCodeToParentMap);

                            // Subnational data
                            if (isSubnationalSheet)
                            {
                                if (areMultipleSubnationalAreasRequired)
                                {
                                    // Multiple parent areas
                                    var dataList = parentDataWriter.AddMultipleAreaData(rowLabels, grouping, timePeriod,
                                        indicatorMetadata, _areaCodeToParentMap);
                                    coreDataCollector.AddDataList(dataList);
                                }
                                else
                                {
                                    // One parent area
                                    var coreData = parentAreaDataProvider.GetData(grouping, timePeriod, indicatorMetadata);
                                    _profileDataWriter.AddData(subnationalWorksheet, rowLabels, coreData, _parentArea);
                                    coreDataCollector.AddData(coreData);
                                }
                            }

                            // Write national data
                            var nationalData = new CoreDataSetProviderFactory().New(_nationalArea).GetData(grouping, timePeriod, indicatorMetadata);
                            _profileDataWriter.AddData(nationalWorksheet, rowLabels, nationalData, _nationalArea);
                        }

                        // Write trend data
                        var trendMarkerWriter = TrendMarkerWriterFactory.New(_profileDataWriter, groupRoot.PolarityId, timePeriods, _profile.HasTrendMarkers);

                        // Child area trend markers
                        trendMarkerWriter.WriteChildTrendMarkers(childAreaWorksheet, groupRoot.RecentTrends, childAreaCodes);

                        // Subnational trend markers
                        if (isSubnationalSheet)
                        {
                            if (areMultipleSubnationalAreasRequired)
                            {
                                trendMarkerWriter.WriteMultipleSubnationalTrendMarkers(subnationalWorksheet, grouping,
                                    indicatorMetadata, coreDataCollector, parentDataWriter.CategoryIdAndAreaCodes);
                            }
                            else
                            {
                                trendMarkerWriter.WriteSingleSubnationalTrendMarker(subnationalWorksheet, grouping,
                                    indicatorMetadata, coreDataCollector);
                            }
                        }

                        // National trend markers
                        trendMarkerWriter.WriteNationalTrendMarkers(nationalWorksheet, groupRoot.RecentTrends,
                            _nationalArea.Code);
                    }
                }
            }
        }
        public Dictionary<string, IList<SimpleAreaData>> Build()
        {
            IndicatorMetadataRepository indicatorMetadataRepository = IndicatorMetadataRepository.Instance;
            IList<Grouping> groupings = groupDataReader.GetGroupingsByGroupIdAndAreaTypeIdOrderedBySequence(GroupId, AreaTypeId);
            GroupRootBuilder rootBuilder = new GroupRootBuilder();
            IList<GroupRoot> roots = rootBuilder.BuildGroupRoots(groupings);

            CoreDataSetProviderFactory coreDataSetProviderFactory = new CoreDataSetProviderFactory();

            Dictionary<string, IList<SimpleAreaData>> responseObjects = new Dictionary<string, IList<SimpleAreaData>>();

            foreach (IArea area in Areas)
            {
                List<SimpleAreaData> dataObjects = new List<SimpleAreaData>();
                responseObjects.Add(area.Code, dataObjects);

                var isAreaCcg = area.IsCcg;

                bool isAreaAggregate = isAreaCcg || area.IsGpDeprivationDecile || area.IsShape;

                CoreDataSetProvider coreDataSetProvider = coreDataSetProviderFactory.New(area);

                var indicatorComparerFactory =
                    new IndicatorComparerFactory { PholioReader = pholioReader };
                foreach (GroupRoot root in roots)
                {
                    Grouping grouping = root.FirstGrouping;

                    IndicatorComparer comparer = indicatorComparerFactory.New(grouping);
                    IndicatorMetadata metadata = indicatorMetadataRepository.GetIndicatorMetadata(grouping.IndicatorId);

                    var formatter = NumericFormatterFactory.New(metadata, groupDataReader);
                    var dataProcessor = new ValueWithCIsDataProcessor(formatter);

                    List<ValueData> dataList = new List<ValueData>();

                    ITimePeriodTextListBuilder timePeriodTextListBuilder =
                        TimePeriodTextListBuilderFactory.New(IncludeTimePeriods, metadata);

                    Dictionary<string, List<int?>> significanceHash = null;
                    if (isAreaAggregate == false || isAreaCcg)
                    {
                        significanceHash = GetSignificanceHash(ComparatorAreaCodes);
                    }

                    var timePeriods = GetTimePeriods(grouping, metadata.YearType);
                    foreach (TimePeriod timePeriod in timePeriods)
                    {
                        timePeriodTextListBuilder.Add(timePeriod);

                        CoreDataSet areaData = coreDataSetProvider.GetData(grouping, timePeriod, metadata);

                        if (areaData != null)
                        {
                            ValueWithCIsData data = areaData.GetValueWithCIsData();
                            dataProcessor.FormatAndTruncate(data);

                            if (isAreaAggregate && isAreaCcg == false)
                            {
                                dataList.Add(data.GetValueData());
                            }
                            else
                            {
                                dataList.Add(data);

                                foreach (var comparatorAreaCode in ComparatorAreaCodes)
                                {
                                    CoreDataSet comparatorData =
                                        groupDataReader.GetCoreData(grouping, timePeriod, comparatorAreaCode)
                                            .FirstOrDefault();
                                    try
                                    {
                                        int significance;
                                        if (comparer is ICategoryComparer)
                                        {
                                            var d = new ChildAreaValuesBuilder(indicatorComparerFactory,
                                                groupDataReader, areasReader, profileReader)
                                            {
                                                ParentAreaCode = comparatorAreaCode,
                                                AreaTypeId = AreaTypeId,
                                                ComparatorId = grouping.ComparatorId
                                            }.Build(grouping);
                                            var coreData = d.First(x => x.AreaCode.Equals(area.Code));
                                            significance = coreData.Significance.Values.First();
                                        }
                                        else
                                        {
                                            significance =
                                                (int)comparer.Compare(areaData, comparatorData, metadata);
                                        }

                                        var significanceList = significanceHash[comparatorAreaCode];
                                        significanceList.Add(significance);
                                    }
                                    catch (Exception ex)
                                    {
                                        ExceptionLog.LogException(ex, string.Empty);
                                    }
                                }
                            }
                        }
                        else
                        {
                            // Placeholders for missing data
                            dataList.Add(null);
                            if (significanceHash != null)
                            {
                                foreach (var comparatorAreaCode in ComparatorAreaCodes)
                                {
                                    significanceHash[comparatorAreaCode].Add(null);
                                }
                            }
                        }
                    }

                    SimpleAreaData dataObject;
                    if (IncludeTimePeriods)
                    {
                        // Only attach metadata when requested (hybrid of GroupRoot & CoreDataSet)
                        //TODO this is difficult to keep aligned with Grouping class
                        dataObject = new FullAreaData
                        {
                            IndicatorId = grouping.IndicatorId,
                            Significances = significanceHash,
                            Data = dataList,
                            StateSex = root.StateSex,
                            Sex = grouping.Sex,
                            Age = grouping.Age,
                            ComparatorConfidence = grouping.ComparatorConfidence,
                            ComparatorMethodId = grouping.ComparatorMethodId,
                            Periods = timePeriodTextListBuilder.GetTimePeriodStrings()
                        };
                    }
                    else
                    {
                        dataObject = new SimpleAreaData
                        {
                            IndicatorId = grouping.IndicatorId,
                            Significances = significanceHash,
                            Data = dataList
                        };
                    }
                    dataObjects.Add(dataObject);
                }
            }

            return responseObjects;
        }