import {
  ChartHelper,
  FilterType,
  Indicator,
  IndicatorFilterUtils,
  IndicatorPath,
  IndicatorPathType,
  IndicatorType,
  SourceType,
  Stakeholder, SubCategory,
  Topic,
  Visibility,
} from "../../monitor/entities/stakeholder";
import {AbstractControl, ValidatorFn, Validators} from "@angular/forms";
import {Option} from "../../sharedComponents/input/input.component";
import {Session} from "../../login/utils/helper.class";
import {HelperFunctions} from "../../utils/HelperFunctions.class";
import {properties} from "src/environments/environment";

class Roles {
  manager = 'manager';
  member = 'member';
}

class Entities {
  stakeholder = 'Dashboard';
  funder = 'Funder';
  ri = 'Research Initiative';
  organization = 'Research Institution';
  project = 'Project';
  country = 'National';
  datasource = 'Repository';
  researcher = 'Researcher';

  stakeholders = 'Dashboards';
  funders = 'Funders';
  ris = 'Research Initiatives';
  organizations = 'Research Institutions';
  projects = 'Projects';
  datasources = 'Repositories';
  researchers = 'Researchers';
}

export class StakeholderConfiguration {
  public static ROLES: Roles = new Roles();
  public static ENTITIES: Entities = new Entities();
  public static TYPES: Option[] = [
    {value: 'funder', label: StakeholderConfiguration.ENTITIES.funder},
    {value: 'ri', label: StakeholderConfiguration.ENTITIES.ri},
    {value: 'organization', label: StakeholderConfiguration.ENTITIES.organization},
    {value: 'project', label: StakeholderConfiguration.ENTITIES.project}
  ];
  public static LOCALES: Option[] = [
    {value: "en", label: 'English'},
    {value: "eu", label: 'Europe'}
  ];
  public static FUNDER_TYPES: Option[] = [];
  public static VISIBILITIES: Option[] = [
    {icon: 'earth', value: "PUBLIC", label: 'Public'},
    {icon: 'restricted', value: "RESTRICTED", label: 'Restricted'},
    {icon: 'incognito', value: "PRIVATE", label: 'Private'},
  ];
  public static CACHE_INDICATORS: boolean = true;
  public static NUMBER_MULTI_INDICATOR_PATHS = false;
  public static CHART_MULTI_INDICATOR_PATHS = true;
}

export class StakeholderUtils {
  get roles() {
    return StakeholderConfiguration.ROLES;
  }

  get entities() {
    return StakeholderConfiguration.ENTITIES;
  }

  get types() {
    return StakeholderConfiguration.TYPES
  }

  get funderTypes() {
    return StakeholderConfiguration.FUNDER_TYPES;
  }

  get locales() {
    return StakeholderConfiguration.LOCALES;
  }

  get visibilities() {
    return StakeholderConfiguration.VISIBILITIES;
  }

  get isCachingIndicators() {
    return StakeholderConfiguration.CACHE_INDICATORS;
  }

  get hasMultiNumberIndicatorPaths() {
    return StakeholderConfiguration.NUMBER_MULTI_INDICATOR_PATHS;
  }

  get hasMultiChartIndicatorPaths() {
    return StakeholderConfiguration.CHART_MULTI_INDICATOR_PATHS;
  }

  visibilityIcon: Map<Visibility, string> = new Map<Visibility, string>(this.visibilities.map(option => [option.value, option.icon]));

  defaultValue(options: Option[]) {
    return options.length === 1 ? options[0].value : null;
  }

  showField(options: Option[]) {
    return options.length > 1;
  }

  getLabel(options: Option[], value) {
    let option = options.find(option => option.value === value);
    return option ? option.label : null;
  }

  getTypesByUserRoles(user, id: string = null): Option[] {
    let types = [];
    for (let type of this.types) {
      if (Session.isCurator(type.value, user) || Session.isPortalAdministrator(user) || (id && Session.isManager(type.value, id, user))) {
        types.push(type);
      }
    }
    return types;
  }

  public createFunderFromDefaultProfile(funder: Stakeholder, defaultTopics: Topic[], isDefault: boolean = false): Stakeholder {
    funder.topics = HelperFunctions.copy(defaultTopics);
    for (let topic of funder.topics) {
      topic.defaultId = !isDefault ? topic._id : null;
      topic._id = null;
      for (let category of topic.categories) {
        category.defaultId = !isDefault ? category._id : null;
        category._id = null;
        let subTokeep: SubCategory[] = [];
        for (let subCategory of category.subCategories) {
          subCategory.defaultId = !isDefault ? subCategory._id : null;
          subCategory._id = null;
          subTokeep.push(subCategory);
          for (let section of subCategory.charts) {
            let chartsTokeep: Indicator[] = [];
            section.defaultId = !isDefault ? section._id : null;
            section.stakeholderAlias = funder.alias;
            section._id = null;
            for (let indicator of section.indicators) {
              indicator.defaultId = !isDefault ? indicator._id : null;
              indicator._id = null;
              chartsTokeep.push(indicator);
              for (let indicatorPath of indicator.indicatorPaths) {
                if (indicatorPath.parameters) {
                  Object.keys(indicatorPath.parameters).forEach(key => {
                    if (key == "index_name") {
                      indicatorPath.parameters[key] = funder.index_name;
                    } else if (key == "index_id") {
                      indicatorPath.parameters[key] = funder.index_id;
                    } else if (key == "index_shortName") {
                      indicatorPath.parameters[key] = funder.index_shortName.toLowerCase();
                    }
                  });
                }
              }
            }
            section.indicators = chartsTokeep;
          }
          for (let section of subCategory.numbers) {
            section.defaultId = !isDefault ? section._id : null;
            section.stakeholderAlias = funder.alias;
            section._id = null;
            for (let indicator of section.indicators) {
              indicator.defaultId = !isDefault ? indicator._id : null;
              indicator._id = null;
            }
          }

        }
        category.subCategories = subTokeep;
      }
    }
    return funder;
  }

  aliasValidatorString(elements: string[]): ValidatorFn {
    return (control: AbstractControl): { [key: string]: string } | null => {
      if (control.value && elements.find(element =>
          element === control.value
      )) {
        return {'error': 'Alias already in use'};
      }
      return null;
    }
  }

  aliasValidator(elements: any[]): ValidatorFn {
    return (control: AbstractControl): { [key: string]: string } | null => {
      if (control.value && elements.find(element =>
          element.alias === control.value
      )) {
        return {'error': 'Alias already in use'};
      }
      return null;
    }
  }

  generateAlias(name: string): string {
    let alias = name.toLowerCase();
    while (alias.includes('/') || alias.includes(' ')) {
      alias = alias.replace(' / ', '-');
      alias = alias.replace('/', '-');
      alias = alias.replace(' ', '-');
    }
    return alias;
  }
}

export class IndicatorUtils {

  allChartTypes: Option[] = [
    {value: 'pie', label: 'Pie'},
    {value: 'table', label: 'Table'},
    {value: 'line', label: 'Line'},
    {value: 'column', label: 'Column'},
    {value: 'bar', label: 'Bar'},
    {value: 'other', label: 'Other'}
  ];
  basicChartTypes: IndicatorPathType[] = ["pie", "line", "column", "bar"];
  defaultChartType: IndicatorPathType = "other";
  indicatorSizes: Option[] = [
    {value: 'small', label: 'Small (Enabled only for large screens)'},
    {value: 'medium', label: 'Medium'},
    {value: 'large', label: 'Large'}
  ];

  allSourceTypes: Option[] = [
    {value: 'search', label: 'Search'},
    {value: 'statistics', label: 'Statistics'},
    {value: 'stats-tool', label: 'Statistics tool'}
  ];

  formats: Option[] = [
    {value: "NUMBER", label: "Number"},
    {value: "PERCENTAGE", label: "Percentage"}
  ];

  sourceTypes: Option[] = [
    {value: 'stats-tool', label: 'Statistics tool'}
  ];

  isActive: Option[] = [
    {icon: 'brightness_1', iconClass: '', value: true, label: 'Active'},
    {icon: 'brightness_1', value: false, label: 'Inactive'},
  ];

  parametersValidators: Map<string, any> = new Map<string, any>([
    ['start_year', [Validators.required, Validators.pattern('^\\d+$')]],
    ['end_year', [Validators.required, Validators.pattern('^\\d+$')]]
  ]);
  ignoredParameters = ['index_name', 'index_id', 'index_shortName'];
  statsProfileParameter = 'profile';

  numberSources: Map<SourceType, string[]> = new Map<SourceType, string[]>();
  chartSources: Map<SourceType, string[]> = new Map<SourceType, string[]>();

  constructor() {
    this.numberSources.set('statistics', [properties.statisticsAPIURL]);
    this.numberSources.set('search', [properties.searchAPIURLLAst]);
    this.numberSources.set('stats-tool', [properties.monitorStatsFrameUrl, "http://marilyn.athenarc.gr:8080/stats-api/", "http://88.197.53.71:8080/stats-api/", "https://stats.madgik.di.uoa.gr/stats-api/", "https://beta.services.openaire.eu/stats-tool/", "https://services.openaire.eu/stats-tool/", "https://services.openaire.eu/monitor-stats-tool/"]);
    this.chartSources.set('stats-tool', [properties.monitorStatsFrameUrl, "http://marilyn.athenarc.gr:8080/stats-api/", "http://88.197.53.71:8080/stats-api/", "https://stats.madgik.di.uoa.gr/stats-api/", "https://beta.services.openaire.eu/stats-tool/", "https://services.openaire.eu/stats-tool/", "https://services.openaire.eu/monitor-stats-tool/"]);
    this.chartSources.set('old', [properties.statisticsFrameAPIURL]);
    this.chartSources.set('image', [""]);
  }

  getSourceType(source: string): SourceType {
    let sourceType: SourceType = 'search';
    this.numberSources.forEach((values, key) => {
      if (key == source) {
        sourceType = key;
      }
    });
    return sourceType;
  }

  getChartUrl(source: SourceType, url: string): string {
    return this.chartSources.get(source)[0] + url;
  }

  getNumberUrl(source: SourceType, url: string): string {
    return this.numberSources.get(this.getSourceType(source))[0] + url;
  }

  getNumberSource(url: string): SourceType {
    let source: SourceType = 'search';
    this.numberSources.forEach((values, key) => {
      values.forEach((value) => {
        if (value !== '' && url.indexOf(value) !== -1) {
          source = key;
        }
      });
    });
    return source;
  }

  getChartSource(url: string): SourceType {
    let source: SourceType = 'image';
    this.chartSources.forEach((values, key) => {
      values.forEach((value) => {
        if (value !== '' && url.indexOf(value) !== -1) {
          source = key;
        }
      });
    });
    return source;
  }

  getChartTypes(initialType) {
    let types: Option[] = [];
    if (this.basicChartTypes.indexOf(initialType) != -1) {
      (this.allChartTypes).forEach(option => {
        if (this.basicChartTypes.indexOf(option.value) != -1) {
          types.push(option);
        }
      });
      return types;
    } else if (initialType == "table") {
      (this.allChartTypes).forEach(option => {
        if (initialType == option.value) {
          types.push(option);
        }
      });
      return types;
    } else {
      return this.allChartTypes;
    }
  }

  public getFullUrl(stakeholder: Stakeholder, indicatorPath: IndicatorPath, fundingL0: string = null, startYear: string = null, endYear: string = null): string {
    let replacedUrl = indicatorPath.chartObject ? indicatorPath.chartObject : indicatorPath.url;
    if (indicatorPath.parameters.statsProfile) {
      replacedUrl = replacedUrl.split(ChartHelper.prefix + this.statsProfileParameter + ChartHelper.suffix).join(indicatorPath.parameters.statsProfile)
    } else if (stakeholder.statsProfile) {
      replacedUrl = replacedUrl.split(ChartHelper.prefix + this.statsProfileParameter + ChartHelper.suffix).join(stakeholder.statsProfile)
    }
    replacedUrl = replacedUrl.split(ChartHelper.prefix + 'index_id' + ChartHelper.suffix).join(stakeholder.index_id);
    replacedUrl = replacedUrl.split(ChartHelper.prefix + 'index_shortName' + ChartHelper.suffix).join(stakeholder.index_shortName);
    replacedUrl = replacedUrl.split(ChartHelper.prefix + 'index_name' + ChartHelper.suffix).join(stakeholder.index_name);
    if (indicatorPath.parameters) {
      Object.keys(indicatorPath.parameters).forEach(key => {
        let replacedValue = indicatorPath.parameters[key];
        if (startYear && key == "start_year" && indicatorPath.filters["start_year"]) {
          replacedValue = (replacedValue < startYear) ? startYear : replacedValue;
        }
        if (endYear && key == "end_year" && indicatorPath.filters["end_year"]) {
          replacedValue = (replacedValue > endYear) ? endYear : replacedValue;
        }
        replacedUrl = replacedUrl.split(ChartHelper.prefix + key + ChartHelper.suffix).join(replacedValue)
      });
    }
    if (indicatorPath.chartObject) {
      if (fundingL0 && indicatorPath.filters["fundingL0"]) {
        let newJsonObject = JSON.parse(replacedUrl);
        for (let queries of this.getQueryObjectName(newJsonObject) ? newJsonObject[this.getDescriptionObjectName(newJsonObject)][this.getQueryObjectName(newJsonObject)] : newJsonObject[this.getDescriptionObjectName(newJsonObject)]) {
          if (!queries["query"]["filters"] || queries["query"]["filters"].length == 0) {
            queries["query"]["filters"] = [];
          }
          //TODO check how it works if the query already has a filter
          queries["query"]["filters"].push(JSON.parse(indicatorPath.filters["fundingL0"].replace(ChartHelper.prefix + "fundingL0" + ChartHelper.suffix, fundingL0)));
        }
        replacedUrl = JSON.stringify(newJsonObject);
      }
      if (startYear && indicatorPath.filters["start_year"]) {
        let newJsonObject = JSON.parse(replacedUrl);

        for (let queries of this.getQueryObjectName(newJsonObject) ? newJsonObject[this.getDescriptionObjectName(newJsonObject)][this.getQueryObjectName(newJsonObject)] : newJsonObject[this.getDescriptionObjectName(newJsonObject)]) {
          if (!queries["query"]["filters"] || queries["query"]["filters"].length == 0) {
            queries["query"]["filters"] = [];
          }
          //TODO check how it works if the query already has a filter
          queries["query"]["filters"].push(JSON.parse(indicatorPath.filters["start_year"].replace(ChartHelper.prefix + "start_year" + ChartHelper.suffix, startYear)));
        }
        replacedUrl = JSON.stringify(newJsonObject);
      }
      if (endYear && indicatorPath.filters["end_year"]) {
        let newJsonObject = JSON.parse(replacedUrl);
        for (let queries of this.getQueryObjectName(newJsonObject) ? newJsonObject[this.getDescriptionObjectName(newJsonObject)][this.getQueryObjectName(newJsonObject)] : newJsonObject[this.getDescriptionObjectName(newJsonObject)]) {
          if (!queries["query"]["filters"] || queries["query"]["filters"].length == 0) {
            queries["query"]["filters"] = [];
          }
          //TODO check how it works if the query already has a filter
          queries["query"]["filters"].push(JSON.parse(indicatorPath.filters["end_year"].replace(ChartHelper.prefix + "end_year" + ChartHelper.suffix, endYear)));
        }
        replacedUrl = JSON.stringify(newJsonObject);
      }

    }
    //For numbers (e.g. from stats-api , search service, etc)
    if (replacedUrl.indexOf(ChartHelper.prefix + 'index_id' + ChartHelper.suffix) != -1) {
      replacedUrl = replacedUrl.split(ChartHelper.prefix + 'index_id' + ChartHelper.suffix).join(encodeURIComponent(stakeholder.index_id));
    }
    if (replacedUrl.indexOf(ChartHelper.prefix + 'index_name' + ChartHelper.suffix) != -1) {
      replacedUrl = replacedUrl.split(ChartHelper.prefix + 'index_name' + ChartHelper.suffix).join(encodeURIComponent(stakeholder.index_name));
    }
    if (replacedUrl.indexOf(ChartHelper.prefix + 'index_shortName' + ChartHelper.suffix) != -1) {
      replacedUrl = replacedUrl.split(ChartHelper.prefix + 'index_shortName' + ChartHelper.suffix).join(encodeURIComponent(stakeholder.index_shortName));
    }
    return (indicatorPath.chartObject ? indicatorPath.url + encodeURIComponent(replacedUrl) : replacedUrl);
  }

  public getFullUrlWithFilters(stakeholder: Stakeholder, indicatorPath: IndicatorPath, fundingL0: string = null, startYear: string = null, endYear: string = null, coFunded: boolean = false, foslvl1: string[] = [], foslvl2: string[] = [], publiclyFunded: "all" | "true" | "false" = "all"): string {
    let filterSubtitleText = [];
    indicatorPath.filtersApplied = 0;
    let replacedUrl = indicatorPath.chartObject ? indicatorPath.chartObject : indicatorPath.url;
    if (indicatorPath.parameters.statsProfile) {
      replacedUrl = replacedUrl.split(ChartHelper.prefix + this.statsProfileParameter + ChartHelper.suffix).join(indicatorPath.parameters.statsProfile)
    } else if (stakeholder.statsProfile) {
      replacedUrl = replacedUrl.split(ChartHelper.prefix + this.statsProfileParameter + ChartHelper.suffix).join(stakeholder.statsProfile)
    }
    replacedUrl = replacedUrl.split(ChartHelper.prefix + 'index_id' + ChartHelper.suffix).join(stakeholder.index_id);
    replacedUrl = replacedUrl.split(ChartHelper.prefix + 'index_shortName' + ChartHelper.suffix).join(stakeholder.index_shortName);
    replacedUrl = replacedUrl.split(ChartHelper.prefix + 'index_name' + ChartHelper.suffix).join(stakeholder.index_name);
    if (fundingL0) {
      if (indicatorPath.source == "stats-tool" && indicatorPath.chartObject) {
        let filterResults = this.addFilter(replacedUrl, 'fundingL0', fundingL0);
        replacedUrl = filterResults.url;
        indicatorPath.filtersApplied += filterResults.filtersApplied;
        filterSubtitleText.push("Funding level 0: ");
      }
    }
    if (startYear) {
      if (indicatorPath.source == "stats-tool" && indicatorPath.chartObject) {
        let filterResults = this.addFilter(replacedUrl, 'start_year', startYear);
        replacedUrl = filterResults.url;
        indicatorPath.filtersApplied += filterResults.filtersApplied;
      }
    }
    if (endYear) {
      if (indicatorPath.source == "stats-tool" && indicatorPath.chartObject) {
        let filterResults = this.addFilter(replacedUrl, 'end_year', endYear);
        replacedUrl = filterResults.url;
        indicatorPath.filtersApplied += filterResults.filtersApplied;
      }
    }
    if (startYear || endYear) {
      filterSubtitleText.push(startYear && endYear ? (startYear + ' - ' + endYear) : (endYear ? ('until ' + endYear) : ''));
    }
    if (coFunded) {
      if (indicatorPath.source == "stats-tool" && indicatorPath.chartObject) {
        let filterResults = this.addFilter(replacedUrl, 'co-funded', coFunded);
        replacedUrl = filterResults.url;
        indicatorPath.filtersApplied += filterResults.filtersApplied;
        filterSubtitleText.push("Co-funded: " + (coFunded ? 'yes' : 'no'));
      }
    }
    if (publiclyFunded && publiclyFunded != "all") {
      if (indicatorPath.source == "stats-tool" && indicatorPath.chartObject) {
        let filterResults = this.addFilter(replacedUrl, 'publicly-funded', publiclyFunded);
        replacedUrl = filterResults.url;
        indicatorPath.filtersApplied += filterResults.filtersApplied;
        filterSubtitleText.push("Publicly funded: " + (publiclyFunded ? 'yes' : 'no'));
      }
    }
    if (foslvl1) {
      if (indicatorPath.source == "stats-tool" && indicatorPath.chartObject) {
        let filterResults = this.addFilter(replacedUrl, 'foslvl1', foslvl1);
        replacedUrl = filterResults.url;
        indicatorPath.filtersApplied += filterResults.filtersApplied ? foslvl1.length : 0;
      }
    }
    if (foslvl2) {
      if (indicatorPath.source == "stats-tool" && indicatorPath.chartObject) {
        let filterResults = this.addFilter(replacedUrl, 'foslvl2', foslvl2);
        replacedUrl = filterResults.url;
        indicatorPath.filtersApplied += filterResults.filtersApplied ? foslvl2.length : 0;
      }
    }
    if ((foslvl1 && foslvl1.length > 0) || (foslvl2 && foslvl2.length > 0)) {
      filterSubtitleText.push("Field of Science: " + foslvl1.join(', ') + (foslvl1.length > 0 && foslvl2.length > 0 ? ', ' : '') + foslvl2.join(", "));
    }
    if (indicatorPath.parameters) {
      Object.keys(indicatorPath.parameters).forEach(key => {
        let replacedValue = indicatorPath.parameters[key];
        if (startYear && key == "start_year") {
          replacedValue = (replacedValue < startYear) ? startYear : replacedValue;
          //if there is a parameter that is filtered and the value of the parameter changes, count the filter as applied
          indicatorPath.filtersApplied++;
        }
        if (endYear && key == "end_year") {
          replacedValue = (replacedValue > endYear) ? endYear : replacedValue;
          //if there is a parameter that is filtered and the value of the parameter changes, count the filter as applied
          indicatorPath.filtersApplied++;
        }
        if (key == "subtitle" && filterSubtitleText.length > 0) {
          replacedValue = replacedValue + (replacedValue.length > 0 ? ' - ' : '') + ' Active filters: (' + filterSubtitleText.join(", ") + ')';
        }
        replacedUrl = replacedUrl.split(ChartHelper.prefix + key + ChartHelper.suffix).join(replacedValue)
      });
    }
    //For numbers
    if (replacedUrl.indexOf(ChartHelper.prefix + 'index_id' + ChartHelper.suffix) != -1) {
      replacedUrl = replacedUrl.split(ChartHelper.prefix + 'index_id' + ChartHelper.suffix).join(encodeURIComponent(stakeholder.index_id));
    }
    if (replacedUrl.indexOf(ChartHelper.prefix + 'index_name' + ChartHelper.suffix) != -1) {
      replacedUrl = replacedUrl.split(ChartHelper.prefix + 'index_name' + ChartHelper.suffix).join(encodeURIComponent(stakeholder.index_name));
    }
    if (replacedUrl.indexOf(ChartHelper.prefix + 'index_shortName' + ChartHelper.suffix) != -1) {
      replacedUrl = replacedUrl.split(ChartHelper.prefix + 'index_shortName' + ChartHelper.suffix).join(encodeURIComponent(stakeholder.index_shortName));
    }
    return (indicatorPath.chartObject ? indicatorPath.url + encodeURIComponent(replacedUrl) : replacedUrl);

  }

  private addFilter(replacedUrl, filterType: FilterType, filterValue) {
    let newJsonObject = JSON.parse(replacedUrl);
    let filterApplied: boolean = false;
    let queryIndex = 0;
    for (let queries of this.getQueryObjectName(newJsonObject) ? newJsonObject[this.getDescriptionObjectName(newJsonObject)][this.getQueryObjectName(newJsonObject)] : newJsonObject[this.getDescriptionObjectName(newJsonObject)]) {
      /*Chart with  Named Queries*/
      if (queries["query"]["name"] && !queries["query"]["select"]) {

        if (queries["query"]["name"].indexOf("monitor.") == -1 || !queries["query"]["parameters"]) {
          continue;
        }
        if (filterType == 'fundingL0') {
          let paramFields = queries["query"]["name"].split(".").slice(3);
          let filterPosition = queries["query"]["name"].split(".").indexOf(filterType == "fundingL0" ? 'fl0' : filterType);
          if (filterPosition != -1) {
            //already filtered
            //TODO double check if we need to override if the fl0 is already filtered
            filterPosition -= 3;
            /* //update the value
            if(paramFields.length == queries["query"]["parameters"].length ){
               //ok
               queries["query"]["parameters"][filterPosition] = filterValue;
             }else if((paramFields.length + 2) == queries["query"]["parameters"].length || (paramFields.length*2 + 4) == queries["query"]["parameters"].length){
               queries["query"]["parameters"][filterPosition + 2]=filterValue;
               filterApplied = true;
             }
             if((paramFields.length*2 + 4) == queries["query"]["parameters"].length){
                  queries["query"]["parameters"][(2* filterPosition) + 5]=filterValue;
             }*/
            //if applied with the same value mark as filtered
            if (paramFields.length == queries["query"]["parameters"].length && queries["query"]["parameters"][filterPosition] == filterValue) {
              filterApplied = true;
            } else if ((paramFields.length + 2) == queries["query"]["parameters"].length || (paramFields.length * 2 + 4) == queries["query"]["parameters"].length && queries["query"]["parameters"][filterPosition + 2] == filterValue) {
              filterApplied = true;
            }
          } else {
            // if((paramFields.length*2) == queries["query"]["parameters"].length){
            //   queries["query"]["parameters"].splice(paramFields.length, 0, filterValue);
            // }
            if ((paramFields.length * 2 + 4) == queries["query"]["parameters"].length) {
              queries["query"]["parameters"].splice(paramFields.length + 1, 0, filterValue);
            }
            queries["query"]["name"] = queries["query"]["name"] + ".fl0";
            queries["query"]["parameters"].push(filterValue);
            filterApplied = true;
          }
        } else {
          let paramFields = queries["query"]["name"].split(".").slice(3);
          if ((paramFields.length + 2) == queries["query"]["parameters"].length || (paramFields.length * 2 + 4) == queries["query"]["parameters"].length) {
            filterApplied = true;
            if (filterType == "start_year") {
              queries["query"]["parameters"][0] = parseInt(filterValue);
            } else if (filterType == "end_year") {
              queries["query"]["parameters"][1] = parseInt(filterValue);
            }
          }
          if ((paramFields.length * 2 + 4) == queries["query"]["parameters"].length) {
            filterApplied = true;
            if (filterType == "start_year") {
              queries["query"]["parameters"][paramFields.length + 2] = parseInt(filterValue);
            } else if (filterType == "end_year") {
              queries["query"]["parameters"][paramFields.length + 3] = parseInt(filterValue);
            }
          }
        }
        // it is a name query
        continue;
      }
      if (!queries["query"]["filters"] || queries["query"]["filters"].length == 0) {
        queries["query"]["filters"] = [];
      }
      /*Chart with  proper json object*/
      //apply the filter in any select fields
      for (let select of queries["query"]["select"]) {
        let filterString = IndicatorFilterUtils.getFilter(select["field"], filterType, filterValue);
        if (filterString) {
          let filter = JSON.parse(filterString);
          //check if filter already exists
          let filterposition = IndicatorFilterUtils.filterIndexOf(filter, queries["query"]["filters"]);
          if (filterposition) {
            if (queries["query"]["filters"][filterposition.filter]['groupFilters'][filterposition.groupFilter]["values"][0] != filter['groupFilters'][0]["values"][0].replace(ChartHelper.prefix + filterType + ChartHelper.suffix, filterValue)) {
              //change filter value
              // queries["query"]["filters"][filterposition.filter]['groupFilters'][filterposition.groupFilter]["values"][0] = filter['groupFilters'][0]["values"][0].replace(ChartHelper.prefix + filterType + ChartHelper.suffix, filterValue);
              //add user filter value
              // queries["query"]["filters"].push(JSON.parse(filterString.replace(ChartHelper.prefix + filterType + ChartHelper.suffix, filterValue)));
              // update colors
              //if noit a pie, map and chart has more than one query
              //
              if (!newJsonObject.hasOwnProperty("mapDescription") && queries["type"] != "pie" && this.isComparingChart(newJsonObject, filter)) {
                let activeColors = ["#7CB5EC", "#434348", "#8bbc21", "#910000", "#1aadce", "#492970", "#f28f43", "#77a1e5", "#c42525", "#a6c96a"];
                let inActiveColors = ["#E4EFFB", "#D8D8D9", "#8bbc21", "#910000", "#1aadce", "#492970", "#f28f43", "#77a1e5", "#c42525", "#a6c96a"];
                if (!newJsonObject[this.getDescriptionObjectName(newJsonObject)]["colors"]) {
                  newJsonObject[this.getDescriptionObjectName(newJsonObject)]["colors"] = activeColors;
                }
                newJsonObject[this.getDescriptionObjectName(newJsonObject)]["colors"][queryIndex] = inActiveColors[queryIndex];
                filterApplied = true;
              } else if (filterType == "start_year" || filterType == "end_year") {
                //if has date filter already
                if (filterType == "start_year" && parseInt(filterValue) > parseInt(queries["query"]["filters"][filterposition.filter]['groupFilters'][filterposition.groupFilter]["values"][0])) {
                  queries["query"]["filters"][filterposition.filter]['groupFilters'][filterposition.groupFilter]["values"][0] = filterValue;
                } else if (filterType == "end_year" && parseInt(filterValue) < parseInt(queries["query"]["filters"][filterposition.filter]['groupFilters'][filterposition.groupFilter]["values"][0])) {
                  queries["query"]["filters"][filterposition.filter]['groupFilters'][filterposition.groupFilter]["values"][0] = filterValue;
                }
                filterApplied = true;
              }
            } else {
              filterApplied = true;
            }
          } else {
            queries["query"]["filters"].push(JSON.parse(filterString.replace(ChartHelper.prefix + filterType + ChartHelper.suffix, filterValue)));
            filterApplied = true;
          }
        }
      }
      queryIndex++;
    }
    return {"url": JSON.stringify(newJsonObject), "filtersApplied": (filterApplied) ? 1 : 0};
  }

  isComparingChart(newJsonObject, filter,) {
    let queriesCount = this.getQueryObjectName(newJsonObject) ? newJsonObject[this.getDescriptionObjectName(newJsonObject)][this.getQueryObjectName(newJsonObject)].length : newJsonObject[this.getDescriptionObjectName(newJsonObject)].length;
    let values = [];
    if (queriesCount < 2) {
      return false;
    }
    for (let queries of this.getQueryObjectName(newJsonObject) ? newJsonObject[this.getDescriptionObjectName(newJsonObject)][this.getQueryObjectName(newJsonObject)] : newJsonObject[this.getDescriptionObjectName(newJsonObject)]) {
      let filterposition = IndicatorFilterUtils.filterIndexOf(filter, queries["query"]["filters"]);
      if (filterposition) {
        if (values.indexOf(queries["query"]["filters"][filterposition.filter]['groupFilters'][filterposition.groupFilter]["values"][0]) == -1) {
          values.push(queries["query"]["filters"][filterposition.filter]['groupFilters'][filterposition.groupFilter]["values"][0]);
        }
      }
    }
    return values.length > 1;
  }

  generateIndicatorByForm(form: any, indicatorPaths: IndicatorPath[], type: IndicatorType): Indicator {
    let indicator: Indicator = new Indicator(form.name, form.description, form.additionalDescription, type,
        form.width, form.height, form.visibility, indicatorPaths, form.defaultId);
    indicator._id = form._id;
    form.indicatorPaths.forEach((indicatorPath, index) => {
      indicator.indicatorPaths[index].type = indicatorPath.type;
      indicator.indicatorPaths[index].format = indicatorPath.format;
      indicatorPath.parameters.forEach(parameter => {
        indicator.indicatorPaths[index].parameters[parameter.key] = parameter.value;
        if (parameter.key === 'type') {
          indicator.indicatorPaths[index].type = parameter.value;
        }
      });
    });
    return indicator;
  }

  generateIndicatorByNumberUrl(source: SourceType, url: string, stakeholder: Stakeholder, jsonPath = [], sourceServices: string[] = []): IndicatorPath {
    let indicatorPath = new IndicatorPath(null, source, url, null, jsonPath);
    if (source === 'stats-tool') {
      indicatorPath.url = url.split("json=")[0] + "json=";
      indicatorPath.url = indicatorPath.url.split("/")[indicatorPath.url.split("/").length - 1];
      indicatorPath.chartObject = decodeURIComponent(url.indexOf("json=") != -1 ? url.split("json=")[1] : "");
      let chart = JSON.parse(indicatorPath.chartObject);
      this.parameterizeDefaultQuery(chart, indicatorPath, stakeholder);
      this.extractStakeHolders(chart, indicatorPath, stakeholder);
      this.addProfile(indicatorPath);
      indicatorPath.chartObject = JSON.stringify(chart);
      if (!jsonPath || jsonPath.length == 0 || (jsonPath.length == 1 && jsonPath[0] == "")) {
        indicatorPath.jsonPath = ["data", "0", "0", "0"];
      }
      // this.addResultFilters(chart, indicatorPath);
    } else {
      for (let service of sourceServices) {
        if (url.indexOf(service) != -1) {
          url = url.split(service)[1];
        }
      }
      try {
        if (url.indexOf(encodeURIComponent(stakeholder.index_id)) !== -1) {
          url = url.split(encodeURIComponent(stakeholder.index_id)).join(ChartHelper.prefix + "index_id" + ChartHelper.suffix);
        }
        if (url.indexOf(encodeURIComponent(stakeholder.index_name)) !== -1) {
          url = url.split(encodeURIComponent(stakeholder.index_name)).join(ChartHelper.prefix + "index_name" + ChartHelper.suffix);
        }
        if (url.indexOf(encodeURIComponent(stakeholder.index_shortName)) !== -1) {
          url = url.split(encodeURIComponent(stakeholder.index_shortName)).join(ChartHelper.prefix + "index_shortName" + ChartHelper.suffix);
        }
        indicatorPath.url = url;
      } catch (e) {
        console.error(e);
      }
    }
    return indicatorPath;
  }

  generateIndicatorByChartUrl(source: SourceType, url: string, type: IndicatorPathType = null, stakeholder: Stakeholder): IndicatorPath {
    let indicatorPath = new IndicatorPath(type, source, null, null, []);
    try {
      if (source === 'stats-tool') {
        indicatorPath.url = url.split("json=")[0] + "json=";
        indicatorPath.url = indicatorPath.url.split("/")[indicatorPath.url.split("/").length - 1];
        indicatorPath.chartObject = decodeURIComponent(url.split("json=")[1]);
        let chart = JSON.parse(indicatorPath.chartObject);
        if (indicatorPath.url == "chart?json=") {

          if (chart["library"] && (chart["library"] == "HighCharts" || chart["library"] == "eCharts" || chart["library"] == "HighMaps")) {
            indicatorPath.type = this.extractType(chart, indicatorPath);
          } else {
            indicatorPath.type = this.defaultChartType;
          }

          this.extractTitle(chart, indicatorPath);
          this.extractSubTitle(chart, indicatorPath);
          this.extractXTitle(chart, indicatorPath);
          this.extractYTitle(chart, indicatorPath);
        } else if (indicatorPath.url == "table?json=") {
          indicatorPath.type = "table";
        }
        if (indicatorPath.url == "chart?json=" || indicatorPath.url == "table?json=") {
          // common for tables and other chart types
          this.extractDataTitle(chart, indicatorPath);
          this.parameterizeDefaultQuery(chart, indicatorPath, stakeholder);
          this.extractStakeHolders(chart, indicatorPath, stakeholder);
          this.extractStartYear(chart, indicatorPath);
          this.extractEndYear(chart, indicatorPath);
          this.addProfile(indicatorPath);
          indicatorPath.chartObject = JSON.stringify(chart);
        }
      } else if (source === 'old') {
        indicatorPath.url = url.split("data=")[0].split("/stats/")[1] + "data=";
        indicatorPath.chartObject = decodeURIComponent(url.split("data=")[1].split("&")[0]);
        indicatorPath.type = type;
        let chart = JSON.parse(indicatorPath.chartObject);
        this.extractOldToolTitle(chart, indicatorPath);
        this.extractOldToolXTitle(chart, indicatorPath);
        this.extractOldToolYTitle(chart, indicatorPath);
        indicatorPath.chartObject = JSON.stringify(chart);
      } else {
        indicatorPath.url = url;
        indicatorPath.type = type;
      }
    } catch (e) {
      console.error(e);
      indicatorPath.url = url;
      indicatorPath.type = type;
    }
    if (indicatorPath.type == null) {
      indicatorPath.type = this.defaultChartType;
    }
    return indicatorPath;
  }

  private getQueryObjectName(obj) {
    if ((obj[this.getDescriptionObjectName(obj)]).hasOwnProperty("queriesInfo")) {
      return "queriesInfo";
    } else if ((obj[this.getDescriptionObjectName(obj)]).hasOwnProperty("queries")) {
      return "queries";
    }
  }

  private getDescriptionObjectName(obj) {
    if (obj.hasOwnProperty("mapDescription")) {
      return "mapDescription";
    } else if (obj.hasOwnProperty("chartDescription")) {
      return "chartDescription";
    } else if (obj.hasOwnProperty("tableDescription")) {
      return "tableDescription";
    } else if (obj.hasOwnProperty("series")) {
      return "series";
    }
  }

  private extractType(obj, indicatorPath: IndicatorPath): IndicatorPathType {
    let type = (obj[this.getDescriptionObjectName(obj)] && obj[this.getDescriptionObjectName(obj)][this.getQueryObjectName(obj)][0]["type"]) ? obj[this.getDescriptionObjectName(obj)][this.getQueryObjectName(obj)][0]["type"] : "";
    if (this.basicChartTypes.indexOf(type) == -1) {
      type = this.defaultChartType;
    } else {
      obj[this.getDescriptionObjectName(obj)]["queries"][0]["type"] = ChartHelper.prefix + "type" + ChartHelper.suffix;
      indicatorPath.parameters['type'] = type;
    }
    return type;
  }

  private extractStakeHolders(obj, indicatorPath: IndicatorPath, stakeholder: Stakeholder) {
    this.extractFunder(obj, indicatorPath, stakeholder);
    this.extractRI(obj, indicatorPath, stakeholder);
    this.extractOrganization(obj, indicatorPath, stakeholder);
    this.extractDatasource(obj, indicatorPath, stakeholder);
    this.extractResearcher(obj, indicatorPath, stakeholder);
  }

  private extractFunder(obj, indicatorPath: IndicatorPath, stakeholder: Stakeholder) {
    if (stakeholder.type != "funder") {
      return;
    }
    for (let query of this.getQueryObjectName(obj) ? obj[this.getDescriptionObjectName(obj)][this.getQueryObjectName(obj)] : obj[this.getDescriptionObjectName(obj)]) {
      if (query["query"]["profile"]) {
        query["query"]["profile"] = ChartHelper.prefix + this.statsProfileParameter + ChartHelper.suffix;
      }
      if (!query["query"]["filters"]) {
        return;
      }
      for (let filter of query["query"]["filters"]) {
        for (let gfilter of filter["groupFilters"]) {
          //ignore field No Of Funders
          let replacedValue = this.replaceIndexValues(gfilter["values"][0], stakeholder);
          if (replacedValue) { // don't proceed in replacement if no replaced value matches
            if ((gfilter["field"].indexOf(" funder") != -1 && gfilter["field"].indexOf(" funders") == -1) ||
                (gfilter["field"].indexOf(".funder") != -1) ||
                (gfilter["field"].indexOf(".funder.id") != -1)) {
              gfilter["values"][0] = replacedValue;
            }
          }
        }
      }
    }
  }

  private extractRI(obj, indicatorPath: IndicatorPath, stakeholder: Stakeholder) {
    if (stakeholder.type != "ri") {
      return;
    }
    for (let query of this.getQueryObjectName(obj) ? obj[this.getDescriptionObjectName(obj)][this.getQueryObjectName(obj)] : obj[this.getDescriptionObjectName(obj)]) {
      if (query["query"]["profile"]) {
        query["query"]["profile"] = ChartHelper.prefix + this.statsProfileParameter + ChartHelper.suffix;
      }
      if (!query["query"]["filters"]) {
        return;
      }
      for (let filter of query["query"]["filters"]) {
        for (let gfilter of filter["groupFilters"]) {
          let replacedValue = this.replaceIndexValues(gfilter["values"][0], stakeholder);
          if (replacedValue) { // don't proceed in replacement if no replaced value matches
            if ((gfilter["field"].indexOf(".context.name") != -1)
                || (gfilter["field"].indexOf(".context.id") != -1)) {
              gfilter["values"][0] = replacedValue;
            }
          }
        }
      }
    }
  }

  private extractOrganization(obj, indicatorPath: IndicatorPath, stakeholder: Stakeholder) {
    // works for publication.project.organization.name
    // and publication.organization.name
    if (stakeholder.type != "organization") {
      return;
    }
    for (let query of this.getQueryObjectName(obj) ? obj[this.getDescriptionObjectName(obj)][this.getQueryObjectName(obj)] : obj[this.getDescriptionObjectName(obj)]) {
      if (query["query"]["profile"]) {
        query["query"]["profile"] = ChartHelper.prefix + this.statsProfileParameter + ChartHelper.suffix;
      }
      if (!query["query"]["filters"]) {
        return;
      }
      for (let filter of query["query"]["filters"]) {
        for (let gfilter of filter["groupFilters"]) {
          let replacedValue = this.replaceIndexValues(gfilter["values"][0], stakeholder);
          if (replacedValue) { // don't proceed in replacement if no replaced value matches
            if ((gfilter["field"].indexOf(".organization.name") != -1) ||
                (gfilter["field"].indexOf(".organization.id") != -1)) {
              gfilter["values"][0] = replacedValue;
            }
          }
        }
      }
    }
  }

  private extractDatasource(obj, indicatorPath: IndicatorPath, stakeholder: Stakeholder) {
    // works for .datasource.name and .HostedBy datasource
    // and .datasource.id
    if (stakeholder.type != "datasource") {
      return;
    }
    for (let query of this.getQueryObjectName(obj) ? obj[this.getDescriptionObjectName(obj)][this.getQueryObjectName(obj)] : obj[this.getDescriptionObjectName(obj)]) {
      if (query["query"]["profile"]) {
        query["query"]["profile"] = ChartHelper.prefix + this.statsProfileParameter + ChartHelper.suffix;
      }
      if (!query["query"]["filters"]) {
        return;
      }
      for (let filter of query["query"]["filters"]) {
        for (let gfilter of filter["groupFilters"]) {
          let replacedValue = this.replaceIndexValues(gfilter["values"][0], stakeholder);
          if (replacedValue) { // don't proceed in replacement if no replaced value matches
            if ((gfilter["field"].indexOf(".datasource.name") != -1 || gfilter["field"].indexOf(".HostedBy datasource") != -1) ||
                (gfilter["field"].indexOf(".datasource.id") != -1) || (gfilter["field"].indexOf(".hostedby") != -1)) {
              gfilter["values"][0] = replacedValue;
            }
          }
        }
      }
    }
  }

  private extractResearcher(obj, indicatorPath: IndicatorPath, stakeholder: Stakeholder) {
    // works for  .orcid
    if (stakeholder.type != "researcher") {
      return;
    }
    for (let query of this.getQueryObjectName(obj) ? obj[this.getDescriptionObjectName(obj)][this.getQueryObjectName(obj)] : obj[this.getDescriptionObjectName(obj)]) {
      if (query["query"]["profile"]) {
        query["query"]["profile"] = ChartHelper.prefix + this.statsProfileParameter + ChartHelper.suffix;
      }
      if (!query["query"]["filters"]) {
        return;
      }
      for (let filter of query["query"]["filters"]) {
        for (let gfilter of filter["groupFilters"]) {
          let replacedValue = this.replaceIndexValues(gfilter["values"][0], stakeholder);
          if (replacedValue) { // don't proceed in replacement if no replaced value matches
            if ((gfilter["field"].indexOf(".orcid") != -1)) {
              gfilter["values"][0] = replacedValue;
            }
          }
        }
      }
    }
  }

  private replaceIndexValues(currentValue, stakeholder) {
    if (currentValue == stakeholder.index_name) {
      return ChartHelper.prefix + "index_name" + ChartHelper.suffix;
    } else if (currentValue == stakeholder.index_id) {
      return ChartHelper.prefix + "index_id" + ChartHelper.suffix;
    } else if (currentValue == stakeholder.index_shortName) {
      return ChartHelper.prefix + "index_shortName" + ChartHelper.suffix;
    }

  }

  private extractStartYear(obj, indicatorPath: IndicatorPath) {
    let start_year;
    for (let query of obj[this.getDescriptionObjectName(obj)][this.getQueryObjectName(obj)]) {
      if (!query["query"]["filters"]) {
        return;
      }
      for (let filter of query["query"]["filters"]) {
        for (let gfilter of filter["groupFilters"]) {
          if ((gfilter["field"].indexOf(".year") != -1 || gfilter["field"].indexOf(".start year") != -1) && gfilter["type"].indexOf(">") != -1) {
            start_year = gfilter["values"][0];
            gfilter["values"][0] = ChartHelper.prefix + "start_year" + ChartHelper.suffix;
            indicatorPath.parameters["start_year"] = start_year;
          }
        }
      }
    }
  }

  private extractEndYear(obj, indicatorPath: IndicatorPath) {
    let end_year;
    for (let query of obj[this.getDescriptionObjectName(obj)][this.getQueryObjectName(obj)]) {
      if (!query["query"]["filters"]) {
        return;
      }
      for (let filter of query["query"]["filters"]) {
        for (let gfilter of filter["groupFilters"]) {
          if ((gfilter["field"].indexOf(".year") != -1 || gfilter["field"].indexOf(".start year") != -1) && gfilter["type"].indexOf("<") != -1) {
            end_year = gfilter["values"][0];
            gfilter["values"][0] = ChartHelper.prefix + "end_year" + ChartHelper.suffix;
            indicatorPath.parameters["end_year"] = end_year;
          }
        }
      }
    }
  }

  private addProfile(indicatorPath: IndicatorPath) {
    indicatorPath.parameters['statsProfile'] = null;
  }

  private parameterizeDefaultQuery(obj, indicatorPath: IndicatorPath, stakeholder: Stakeholder) {
    let name = "";
    for (let query of this.getQueryObjectName(obj) ? obj[this.getDescriptionObjectName(obj)][this.getQueryObjectName(obj)] : obj[this.getDescriptionObjectName(obj)]) {
      //monitor.{{stakeholderType}}.{{queryname}}
      //parameters: stakeholderId*, type
      if (query["query"]["name"]) {
        name = query["query"]["name"];
        let parameters = (query["query"]["parameters"]) ? query["query"]["parameters"] : [];
        if (name.split('.')[0] == "rcd" && parameters.length > 0 && stakeholder.type == "ri") {
          //rcd.{{queryname}}
          parameters[0] = ChartHelper.prefix + "index_id" + ChartHelper.suffix;
          indicatorPath.parameters["index_id"] = stakeholder.index_id;
        } else if (name.split('.')[0] == "monitor" && parameters.length == 0 && stakeholder.type == "funder") {
          // old saved queries without params
          //monitor.{{funder_shortName}}.{{type}}.{{queryname}}
          let stakeholderSN = name.split('.')[1];
          query["query"]["name"] = name.split('.' + stakeholderSN + ".")[0] + "." + ChartHelper.prefix + "index_shortName" + ChartHelper.suffix + "." + name.split('.' + stakeholderSN + ".")[1];
          indicatorPath.parameters["index_shortName"] = stakeholder.index_shortName.toLowerCase();
        } else if (name.split('.')[0] == "monitor" && parameters.length > 0 && name.split('.')[1] == stakeholder.type) {
          // new parameterized queries
          //monitor.{{type}}.{{queryname}}.{{param1 - id }}.{{param2 result-type}}.{{fl0}} --> params [start year, end year, id, result type, fl0]

          let index = (name.split('.').slice(3).length + 2 == parameters.length) ? [2] : ((name.split('.').slice(3).length * 2 + 4 == parameters.length) ? [2, name.split('.').slice(3).length + 4] : [0]);
          for (let i of index) {
            if (name.split('.').length > 3 && name.split('.')[3] == "id") {
              parameters[i] = ChartHelper.prefix + "index_id" + ChartHelper.suffix;
            } else if (name.split('.').length > 3 && name.split('.')[3] == "shortname") {
              parameters[i] = ChartHelper.prefix + "index_shortName" + ChartHelper.suffix;
            } else if (name.split('.').length > 3 && name.split('.')[3] == "name") {
              parameters[i] = ChartHelper.prefix + "index_name" + ChartHelper.suffix;
            }
          }
        }
      }
    }
  }

  private extractDataTitle(obj, indicatorPath: IndicatorPath) {
    let index = 0;
    if (!obj[this.getDescriptionObjectName(obj)] || !obj[this.getDescriptionObjectName(obj)][this.getQueryObjectName(obj)]) {
      return;
    }
    for (let query of obj[this.getDescriptionObjectName(obj)][this.getQueryObjectName(obj)]) {
      if (query["name"]) {
        let name = query["name"];
        query["name"] = ChartHelper.prefix + "data_title_" + index + ChartHelper.suffix;
        indicatorPath.parameters["data_title_" + index] = name;
      }
      index++;
    }
  }

  private extractTitle(obj, indicatorPath: IndicatorPath) {
    let title = "";
    if (obj[this.getDescriptionObjectName(obj)]["title"]) {
      title = obj[this.getDescriptionObjectName(obj)]["title"]["text"];
      obj[this.getDescriptionObjectName(obj)]["title"]["text"] = ChartHelper.prefix + "title" + ChartHelper.suffix;
    } else if (obj[this.getDescriptionObjectName(obj)]["options"] && obj[this.getDescriptionObjectName(obj)]["options"]["title"]) {
      title = obj[this.getDescriptionObjectName(obj)]["options"]["title"];
      obj[this.getDescriptionObjectName(obj)]["options"]["title"] = ChartHelper.prefix + "title" + ChartHelper.suffix;
    }
    indicatorPath.parameters["title"] = title ? title : "";
  }

  private extractSubTitle(obj, indicatorPath: IndicatorPath) {
    let subtitle = "";
    if (obj[this.getDescriptionObjectName(obj)]["subtitle"]) {
      subtitle = obj[this.getDescriptionObjectName(obj)]["subtitle"]["text"];
      obj[this.getDescriptionObjectName(obj)]["subtitle"]["text"] = ChartHelper.prefix + "subtitle" + ChartHelper.suffix;
      indicatorPath.parameters["subtitle"] = subtitle ? subtitle : "";
    } else if (obj[this.getDescriptionObjectName(obj)]["title"] && obj[this.getDescriptionObjectName(obj)]["title"] && obj[this.getDescriptionObjectName(obj)]["title"]["subtext"]) {
      subtitle = obj[this.getDescriptionObjectName(obj)]["title"]["subtext"];
      obj[this.getDescriptionObjectName(obj)]["title"]["subtext"] = ChartHelper.prefix + "subtitle" + ChartHelper.suffix;
      indicatorPath.parameters["subtitle"] = subtitle ? subtitle : "";
    }
  }

  private extractXTitle(obj, indicatorPath: IndicatorPath) {
    let title = "";
    if (obj[this.getDescriptionObjectName(obj)]["xAxis"] && obj[this.getDescriptionObjectName(obj)]["xAxis"]["title"]) {
      title = obj[this.getDescriptionObjectName(obj)]["xAxis"]["title"]["text"];
      obj[this.getDescriptionObjectName(obj)]["xAxis"]["title"]["text"] = ChartHelper.prefix + "xAxisTitle" + ChartHelper.suffix;
    } else if (obj[this.getDescriptionObjectName(obj)]["options"] && obj[this.getDescriptionObjectName(obj)]["options"]["hAxis"] && obj[this.getDescriptionObjectName(obj)]["options"]["hAxis"]["title"]) {
      title = obj[this.getDescriptionObjectName(obj)]["options"]["hAxis"]["title"];
      obj[this.getDescriptionObjectName(obj)]["options"]["hAxis"]["title"] = ChartHelper.prefix + "xAxisTitle" + ChartHelper.suffix;
    } else if (obj[this.getDescriptionObjectName(obj)]["xAxis"] && obj[this.getDescriptionObjectName(obj)]["xAxis"]["name"]) {
      title = obj[this.getDescriptionObjectName(obj)]["xAxis"]["name"];
      obj[this.getDescriptionObjectName(obj)]["xAxis"]["name"] = ChartHelper.prefix + "xAxisTitle" + ChartHelper.suffix;
    }
    indicatorPath.parameters["xAxisTitle"] = title ? title : "";
  }

  private extractYTitle(obj, indicatorPath: IndicatorPath) {
    let title = "";
    if (obj[this.getDescriptionObjectName(obj)]["yAxis"] && obj[this.getDescriptionObjectName(obj)]["yAxis"]["title"]) {
      title = obj[this.getDescriptionObjectName(obj)]["yAxis"]["title"]["text"];
      obj[this.getDescriptionObjectName(obj)]["yAxis"]["title"]["text"] = ChartHelper.prefix + "yAxisTitle" + ChartHelper.suffix;
    } else if (obj[this.getDescriptionObjectName(obj)]["options"] && obj[this.getDescriptionObjectName(obj)]["options"]["vAxis"] && obj[this.getDescriptionObjectName(obj)]["options"]["vAxis"]["title"]) {
      title = obj[this.getDescriptionObjectName(obj)]["options"]["vAxis"]["title"];
      obj[this.getDescriptionObjectName(obj)]["options"]["vAxis"]["title"] = ChartHelper.prefix + "yAxisTitle" + ChartHelper.suffix;
    } else if (obj[this.getDescriptionObjectName(obj)]["yAxis"] && obj[this.getDescriptionObjectName(obj)]["yAxis"]["name"]) {
      title = obj[this.getDescriptionObjectName(obj)]["yAxis"]["name"];
      obj[this.getDescriptionObjectName(obj)]["yAxis"]["name"] = ChartHelper.prefix + "xAxisTitle" + ChartHelper.suffix;
    }
    indicatorPath.parameters["yAxisTitle"] = title ? title : "";
  }

  private extractOldToolTitle(obj, indicatorPath: IndicatorPath) {
    let title = "";
    if (obj["title"]) {
      title = obj["title"];
      obj["title"] = ChartHelper.prefix + "title" + ChartHelper.suffix;
      indicatorPath.parameters["title"] = title;

    }
  }

  private extractOldToolXTitle(obj, indicatorPath: IndicatorPath) {
    let title = "";
    if (obj["xaxistitle"]) {
      title = obj["xaxistitle"];
      obj["xaxistitle"] = ChartHelper.prefix + "xAxisTitle" + ChartHelper.suffix;
      indicatorPath.parameters["xAxisTitle"] = title;
    }
  }

  private extractOldToolYTitle(obj, indicatorPath: IndicatorPath) {
    let title = "";
    if (obj["fieldsheaders"]) {
      title = Array.isArray(obj["fieldsheaders"]) ? obj["fieldsheaders"][0] : obj["fieldsheaders"];
      if (Array.isArray(obj["fieldsheaders"])) {
        obj["fieldsheaders"][0] = ChartHelper.prefix + "yAxisTitle" + ChartHelper.suffix;
      } else {
        obj["fieldsheaders"] = ChartHelper.prefix + "yAxisTitle" + ChartHelper.suffix;
      }
      indicatorPath.parameters["yAxisTitle"] = title;
    }
  }

  public checkForSchemaEnhancements(url: string): boolean {
    return url != this.applySchemaEnhancements(url);
  }

  public applySchemaEnhancements(url: string): string {
    let resultEnhancements = [
      [".project.acronym", ".project acronym"],
      [".project.title", ".project title"],
      [".project.funder", ".project funder"],
      [".project.funding level 0", ".project funding level 0"],
      [".datasource.name", ".HostedBy datasource"],
      [".datasource.type", ".HostedBy datasource type"]
    ];
    let changes = "";
    for (let field of resultEnhancements) {
      for (let type of ["publication", "software", "dataset", "other", "result"]) {
        if (url.indexOf(encodeURIComponent(type + field[0])) != -1) {
          changes += "Changed  " + type + field[0] + " to " + type + field[1] + "\n";
          url = url.split(encodeURIComponent(type + field[0])).join(encodeURIComponent(type + field[1]));
        }
      }
    }

    if (url.split('json=').length > 1) {
      let obj = JSON.parse(decodeURIComponent(url.split('json=')[1]));
      for (let query of this.getQueryObjectName(obj) ? obj[this.getDescriptionObjectName(obj)][this.getQueryObjectName(obj)] : obj[this.getDescriptionObjectName(obj)]) {
        if (!query["query"]["profile"] || query["query"]["profile"] == 'OpenAIRE All-inclusive' || query["query"]["profile"] == 'OpenAIRE original') {
          changes += (query["query"]["profile"] ? ("Changed profile \"" + query["query"]["profile"] + "\" to ") : "Added profile ") + " \"monitor\"";
          query["query"]["profile"] = 'monitor';
        }
      }
      url = url.split('json=')[0] + "json=" + encodeURIComponent(JSON.stringify(obj));
    }
    return url;
  }
}
