/**
 * Copyright 2019 The Hyve B.V.
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 */ import { Injectable } from '@angular/core' ; import { forkJoin , Observable , Subject } from 'rxjs' ; import { ResourceService } from './resource.service' ; import { CountItem } from '../models/aggregate-models/count-item' ; import { AppConfig } from '../config/app.config' ; import { Constraint } from '../models/constraint-models/constraint' ; import { TrueConstraint } from '../models/constraint-models/true-constraint' ; import { HttpErrorResponse } from '@angular/common/http' ; import { ErrorHelper } from '../utilities/error-helper' ; import { ConstraintHelper } from '../utilities/constraint-utilities/constraint-helper' ; import { SubjectSetConstraint } from '../models/constraint-models/subject-set-constraint' ; @ Injectable ( { providedIn : 'root' } ) export class CountService { private _currentSelectionCount : CountItem ; private _allCohortsCount : CountItem ; private _cohortSelectionCounts : CountItem ; private _showObservationCounts : boolean ; /**
     * The map that holds the conceptCode -> count item relations
     *  e.g.
     * "EHR:DEM:AGE": {
     *   "observationCount": 3,
     *   "subjectCount": 3
     *  },
     * "EHR:VSIGN:HR": {
     *  "observationCount": 9,
     *  "subjectCount": 3
     * }
     */ private _conceptCountMap : Map < string , CountItem > ; /**
     * The map that holds the studyId -> count item relations
     * e.g.
     * "MIX_HD": {
     *   "observationCount": 12,
     *   "subjectCount": 3
     * }
     */ private _studyCountMap : Map < string , CountItem > ; /**
     * The map that holds the studyId -> conceptCode -> count item relations
     * e.g.
     * "SHARED_CONCEPTS_STUDY_A": {
     *    "DEMO:POB": {
     *        "observationCount": 2,
     *        "subjectCount": 2
     *    },
     *    "VSIGN:HR": {
     *        "observationCount": 3,
     *        "subjectCount": 3
     *    }
     * }
     */ private _studyConceptCountMap : Map < string , Map < string , CountItem > > ; private _selectedStudyConceptCountMap : Map < string , Map < string , CountItem > > ; private _selectedStudyCountMap : Map < string , CountItem > ; private _selectedConceptCountMap : Map < string , CountItem > ; private _selectedConceptCountMapUpdated : Subject < Map < string , CountItem > > = new Subject < Map < string , CountItem > > ( ) ; constructor ( private appConfig , private resourceService ) { this . showObservationCounts = this . appConfig . getConfig ( 'show-observation-counts' ) ; this . initializeCounts ( ) ; } initializeCounts ( ) { this . allCohortsCount = new CountItem ( 0 , 0 ) ; this . currentSelectionCount = new CountItem ( 0 , 0 ) ; } updateAllCounts ( constraint ) { const patientLevelConstraint = ConstraintHelper . ensurePatientLevelConstraint ( constraint ) ; return new Promise ( ( resolve , reject ) => { forkJoin ( this . getCounts ( constraint ) , this . resourceService . getCountsPerStudy ( patientLevelConstraint ) , this . resourceService . getCountsPerStudyAndConcept ( patientLevelConstraint ) , this . resourceService . getCountsPerConcept ( patientLevelConstraint ) ) . subscribe ( res => { this . allCohortsCount = res [ 0 ] ; this . selectedStudyCountMap = res [ 1 ] ; this . selectedStudyConceptCountMap = res [ 2 ] ; this . selectedConceptCountMap = res [ 3 ] ; resolve ( true ) ; } , ( err ) => { reject ( err ) ; } ) ; } ) ; } param constraint getCounts ( constraint ) { if ( ! this . showObservationCounts && constraint instanceof SubjectSetConstraint && constraint . setSize > - 1 ) { let countItem = new CountItem ( constraint . setSize , - 1 ) ; return Observable . of ( countItem ) ; } return this . resourceService . getCounts ( constraint ) ; } updateCurrentSelectionCount ( constraint ) { return new Promise ( ( resolve , reject ) => { this . resourceService . updateCohortSelectionCounts ( constraint ) . then ( ( cohortSelectionCounts ) => { this . currentSelectionCount . subjectCount = cohortSelectionCounts . subjectCount ; resolve ( true ) ; } ) . catch ( err => { reject ( err ) ; } ) ; } ) ; } loadCountMaps ( ) { return new Promise ( ( resolve , reject ) => { let promise1 = this . loadConceptCountMap ( ) ; let promise2 = this . loadStudyCountMap ( ) ; let promise3 = this . loadStudyConceptCountMap ( ) ; Promise . all ( [ promise1 , promise2 , promise3 ] ) . then ( ( ) => { resolve ( true ) ; } ) . catch ( ( err ) => { reject ( err ) ; } ) ; } ) ; } loadConceptCountMap ( ) { return new Promise ( ( resolve , reject ) => { this . resourceService . getCountsPerConcept ( new TrueConstraint ( ) ) . subscribe ( ( map ) => { this . conceptCountMap = map ; resolve ( true ) ; } , ( err ) => { ErrorHelper . handleError ( err ) ; reject ( 'Fail to load concept count map from server.' ) ; } ) ; } ) ; } loadStudyCountMap ( ) { return new Promise ( ( resolve , reject ) => { this . resourceService . getCountsPerStudy ( new TrueConstraint ( ) ) . subscribe ( ( map ) => { this . studyCountMap = map ; resolve ( true ) ; } , ( err ) => { ErrorHelper . handleError ( err ) ; reject ( 'Fail to load study count map from server.' ) ; } ) ; } ) ; } loadStudyConceptCountMap ( ) { return new Promise ( ( resolve , reject ) => { this . resourceService . getCountsPerStudyAndConcept ( new TrueConstraint ( ) ) . subscribe ( ( map ) => { this . studyConceptCountMap = map ; resolve ( true ) ; } , ( err ) => { ErrorHelper . handleError ( err ) ; reject ( 'Fail to load study-concept count map from server.' ) ; } ) ; } ) ; } get currentSelectionCount ( ) : CountItem { return this . _currentSelectionCount ; } set currentSelectionCount ( value ) { this . _currentSelectionCount = value ; } get allCohortsCount ( ) : CountItem { return this . _allCohortsCount ; } set allCohortsCount ( value ) { this . _allCohortsCount = value ; } get cohortSelectionCounts ( ) : CountItem { return this . _cohortSelectionCounts ; } set cohortSelectionCounts ( value ) { this . _cohortSelectionCounts = value ; } get showObservationCounts ( ) : boolean { return this . _showObservationCounts ; } set showObservationCounts ( value ) { this . _showObservationCounts = value ; } get conceptCountMap ( ) : Map < string , CountItem > { return this . _conceptCountMap ; } set conceptCountMap ( value ) { this . _conceptCountMap = value ; } get studyCountMap ( ) : Map < string , CountItem > { return this . _studyCountMap ; } set studyCountMap ( value ) { this . _studyCountMap = value ; } get studyConceptCountMap ( ) : Map < string , Map < string , CountItem > > { return this . _studyConceptCountMap ; } set studyConceptCountMap ( value ) { this . _studyConceptCountMap = value ; } get selectedConceptCountMap ( ) : Map < string , CountItem > { return this . _selectedConceptCountMap ; } set selectedConceptCountMap ( value ) { this . _selectedConceptCountMap = value ; this . selectedConceptCountMapUpdated . next ( value ) ; } get selectedConceptCountMapUpdated ( ) : Subject < Map < string , CountItem > > { return this . _selectedConceptCountMapUpdated ; } set selectedConceptCountMapUpdated ( value ) { this . _selectedConceptCountMapUpdated = value ; } get selectedStudyCountMap ( ) : Map < string , CountItem > { return this . _selectedStudyCountMap ; } set selectedStudyCountMap ( value ) { this . _selectedStudyCountMap = value ; } get selectedStudyConceptCountMap ( ) : Map < string , Map < string , CountItem > > { return this . _selectedStudyConceptCountMap ; } set selectedStudyConceptCountMap ( value ) { this . _selectedStudyConceptCountMap = value ; } }