import {
  ChangeDetectorRef,
  Component,
  ElementRef, EventEmitter, Inject,
  Input,
  OnChanges,
  OnDestroy,
  OnInit, Output, PLATFORM_ID,
  SimpleChanges,
  ViewChild
} from '@angular/core';
import {isPlatformServer, Location} from '@angular/common';
import {ActivatedRoute, Router} from '@angular/router';
import {Meta, Title} from '@angular/platform-browser';

import {AdvancedField, Filter, Value} from './searchHelperClasses.class';
import {SearchCustomFilter, SearchUtilsClass} from './searchUtils.class';
import {ModalLoading} from '../../utils/modal/loading.component';
import {Dates, Identifier, StringUtils} from '../../utils/string-utils.class';
import {ErrorCodes} from '../../utils/properties/errorCodes';
import {RouterHelper} from '../../utils/routerHelper.class';

import {PiwikService} from '../../utils/piwik/piwik.service';
import {EnvProperties} from '../../utils/properties/env-properties';
import {SEOService} from '../../sharedComponents/SEO/SEO.service';
import {HelperService} from "../../utils/helper/helper.service";
import {OpenaireEntities, SearchFields} from "../../utils/properties/searchFields";
import {RefineResultsUtils} from "../../services/servicesUtils/refineResults.class";
import {RangeFilter} from "../../utils/rangeFilter/rangeFilterHelperClasses.class";
import {ZenodoInformationClass} from "../../deposit/utils/zenodoInformation.class";
import {Breadcrumb} from "../../utils/breadcrumbs/breadcrumbs.component";
import {HelperFunctions} from "../../utils/HelperFunctions.class";
import {properties} from "../../../../environments/environment";
import {AlertModal} from "../../utils/modal/alert";
import {Subscriber} from "rxjs";
import {IndexInfoService} from "../../utils/indexInfo.service";
import {Background} from "../../utils/background-utils";
import {LayoutService} from "../../dashboard/sharedComponents/sidebar/layout.service";
import {Platform} from "@angular/cdk/platform";

export interface SearchForm extends Background {}

declare var UIkit: any;

@Component({
  selector: 'new-search-page',
  templateUrl: 'newSearchPage.component.html'
})
export class NewSearchPageComponent implements OnInit, OnDestroy, OnChanges {
  @ViewChild('mobileFilters') mobileFilters: ElementRef;
  @Input() hasPrefix: boolean = true;
  @Input() prefix: string = "OpenAIRE | ";
  @Input() pageTitle = "";
  pageTitleWithFilters = "";
  @Input() results = [];
  @Input() type;
  @Input() entityType;
  @Input() searchUtils: SearchUtilsClass = new SearchUtilsClass();
  @Input() fieldIds: string[];
  @Input() fieldIdsMap;//:{ [key:string]:{ name:string, operator:string, type:string, indexField:string, equalityOperator:string  }} ;
  @Input() selectedFields: AdvancedField[];
  @ViewChild(ModalLoading) loading: ModalLoading;
  @Input() csvParams: string;
  @Input() csvPath: string;
  @Input() simpleSearchLink: string = "";
  @Input() advancedSearchLink: string = "";
  @Input() disableForms: boolean = false;
  @Input() disableRefineForms: boolean = false;
  @Input() loadPaging: boolean = true;
  @Input() oldTotalResults: number = 0;
  @Input() openaireLink: string;
  @Input() customFilters: SearchCustomFilter[] = null;
  @Input()
  set customFilter(customFilter: SearchCustomFilter | SearchCustomFilter[]) {
    if(!Array.isArray(customFilter)) {
      this.customFilters = customFilter?[customFilter]:null;
    }else{
      this.customFilters = customFilter;
    }
  }
  @Input() sort: boolean = true;
  @Input() sortedByChanged: string = "";
  @Input() searchForm: SearchForm = {class: 'search-form', dark: true};
  //From simple:
  @Input() orderedFilters = [];
  @Input() rangeFilters: RangeFilter[] = [];
  @Input() rangeFields: string[][] = [];
  @Input() refineFields = [];
  @Input() filters: Filter[] = [];
  @Input() staticFields = [];
  @Input() staticFilters: Filter[] = [];
  @Input() staticFieldValues: { [key: string]: {"name": string, "id": string, "count": string}[] } = {};
  selectedFilters: number = 0;
  selectedRangeFilters: number = 0;
  selectedStaticFilters: number = 0;
  private searchFieldsHelper: SearchFields = new SearchFields();
  @Input() newQueryButton: boolean = true;
  public showUnknownFilters: boolean = false; // when a filter exists in query but has no results, so no filters returned from the query
  URLCreatedFilters: Filter[] = [];
  URLCreatedRangeFilters: RangeFilter[] = [];
  URLCreatedStaticFilters: Filter[] = [];
  @Input() showRefine: boolean = true;
  @Input() tableViewLink: string;
  @Input() usedBy: string = "search";
  @Input() public zenodoInformation: ZenodoInformationClass = new ZenodoInformationClass();
  @Input() showIndexInfo: boolean = true;
  @Input() showResultCount: boolean = true;
  @Input() showMoreFilterValuesInline: boolean = true;
  @Input() filterValuesNum: number = 6;
  @Input() keywordFields = [];
  @Input() simpleView: boolean = true;
  @Input() formPlaceholderText = "Type Keywords...";
  @Input() resultTypes: Filter = null;
  resultTypeOptions = {
    // "publications": {"id": "publication", "name": OpenaireEntities.PUBLICATIONS},
    // "datasets": {"id": "dataset", "name": OpenaireEntities.DATASETS},
    // "software": {"id": "software", "name": OpenaireEntities.SOFTWARE},
    // "other": {"id": "other", "name": OpenaireEntities.OTHER}
  };
  serviceTypeOptions = {
    // "datasources": {"id": "datasource", "name": OpenaireEntities.DATASOURCES},
    // "services": {"id": "service", "name": "Other "+OpenaireEntities.SERVICES}
  }
  selectedTypesNum = 0;
  @Input() quickFilter: { filter: Filter, selected: boolean, filterId: string, value: string };
  @Input() includeOnlyResultsAndFilter: boolean = false;
  @Input() showBreadcrumb: boolean = false;
  @Input() showDownload: boolean = true;
  @Input() breadcrumbs: Breadcrumb[] = [];
  private subscriptions = [];
  public parameterNames: string[] = [];
  public parameterValues: string[] = [];
  
  filterPillCharactersLimit: number = 35;
  public csvLimit: number = 0;
  public pagingLimit: number = 0;
  public resultsPerPage: number = 0;
  properties: EnvProperties = properties;
  public pageContents = null;
  public divContents = null;
  public routerHelper: RouterHelper = new RouterHelper();
  public errorCodes: ErrorCodes = new ErrorCodes();
  url = null;
  metaDescription = "";
  public pageOptions: number[] = [5, 10, 20, 50];
  @Input() basicMetaDescription = [];
  
  @Input() entitiesSelection: boolean = false;
  @Input() showSwitchSearchLink: boolean = true;
  
  // on 1st load, do not show filters until results query returns.
  public hideFilters: boolean = true;
  
  //Dashboard
  filterToggle = false;
  //stickyform
  @Input() stickyForm: boolean = false;

  currentValueToRemove;
  currentFilterToRemove;
  public indexUpdateDate: Date;
  showOffCanvas:boolean = false;
	isMobile: boolean = false;
	isServer: boolean;
  searchTerm: string = null;
  advancedSearchTerms: number = 0;

  @Output() filterRequestAll = new EventEmitter();

  constructor(private route: ActivatedRoute,
              private location: Location,
              private _meta: Meta,
              private _title: Title,
              private _piwikService: PiwikService,
              private router: Router,
              private seoService: SEOService,
              private helper: HelperService,
              private layoutService: LayoutService,
              @Inject(PLATFORM_ID) private platform: any,
              private cdr: ChangeDetectorRef, private indexInfoService: IndexInfoService) {
    this.isServer = isPlatformServer(this.platform);
  }
  
  ngOnInit() {
    if(properties.adminToolsPortalType !== "explore") {
      //this.getDivContents();
      this.getPageContents();
    }
    this.pagingLimit = this.properties.pagingLimit;
    this.resultsPerPage = this.properties.resultsPerPage;
    this.csvLimit = this.properties.csvLimit;
    this.updateUrl(this.properties.domain + this.properties.baseLink + this.router.url);
    this.url = this.properties.domain + this.properties.baseLink + this.router.url;
    if (!this.includeOnlyResultsAndFilter) {
      this.subscriptions.push(this._piwikService.trackView(this.properties, this.pageTitle).subscribe());
    }
    this.layoutService.isMobile.subscribe(isMobile => {
      this.isMobile = isMobile;
      this.cdr.detectChanges();
    });
    this.route.queryParams.subscribe(params => {
      if (params['page'] && params['page'] != 1) {
        HelperFunctions.scrollToId("searchForm");
      }
      if (this.basicMetaDescription.length == 0) {
        if (this.entityType == "result") {
          this.basicMetaDescription = [OpenaireEntities.RESULTS, "Discover" + (this.properties.adminToolsCommunity == 'openaire' ? " over 100 million of" : "") + " "+OpenaireEntities.RESULTS+" ", "categorized by research type, year range, funder, languages, "+OpenaireEntities.COMMUNITY+" and "+OpenaireEntities.DATASOURCES+"."];
        } else if (this.entityType == "project") {
          this.basicMetaDescription = ["Research "+OpenaireEntities.PROJECTS, "Discover research "+OpenaireEntities.PROJECTS+" and correlated research categorized by Funder and active year. ", "Statistics data about produced "+OpenaireEntities.RESULTS+" per year available."];
        } else if (this.entityType == "organization") {
          this.basicMetaDescription = ["Research "+OpenaireEntities.ORGANIZATIONS, "Discover worldwide research "+OpenaireEntities.ORGANIZATIONS+" from over 100 countries and correlated research. ", "Funding, "+OpenaireEntities.DATASOURCES+", research "+OpenaireEntities.PUBLICATIONS+" and "+OpenaireEntities.DATASETS+" available."];
        } else {
          this.basicMetaDescription.push(this.pageTitle)
        }
      }
      // console.log("title " + this.pageTitle, this.basicMetaDescription)
      this.updateMeta(this.pageTitle);
    });
    this.searchUtils.baseUrl = "/" + this.searchUtils.baseUrl;
    if(this.breadcrumbs.length === 0) {
      this.breadcrumbs.push({name: 'home', route: '/'});
      if (this.simpleView) {
        this.breadcrumbs.push({name: "Search", route: null});
      } else if (!this.simpleView && this.advancedSearchLink) {
        this.breadcrumbs.push({name: "Advanced Search", route: null});
      }
    }
    if (typeof document !== 'undefined') {
      this.subscriptions.push(this.indexInfoService.lastIndexDate.subscribe(lastIndexUpdate => {
        if (lastIndexUpdate) {
          this.indexUpdateDate = new Date(lastIndexUpdate);
        }
      }));
    }
  }
  
  private getPageContents() {
    this.subscriptions.push(this.helper.getPageHelpContents(this.properties, (this.customFilters && this.customFilters[0] && this.customFilters[0].queryFieldName == "communityId") ? this.customFilters[0].valueId : this.properties.adminToolsCommunity, this.router.url).subscribe(contents => {
      this.pageContents = contents;
    }));
    
  }
  
  private getDivContents() {
    this.subscriptions.push(this.helper.getDivHelpContents(this.properties, (this.customFilters && this.customFilters[0] &&  this.customFilters[0].queryFieldName == "communityId") ? this.customFilters[0].valueId : this.properties.adminToolsCommunity, this.router.url).subscribe(contents => {
      this.divContents = contents;
    }));
  }
  
  ngOnDestroy() {
    this.subscriptions.forEach(subscription => {
      if (subscription instanceof Subscriber) {
        subscription.unsubscribe();
      }
    });
  }
  
  ngOnChanges(changes: SimpleChanges) {
    this.cdr.detectChanges();
  }
  
  
  get disabled() {
    return this.disableForms || this.disableRefineForms;
  }
  
  updateMeta(title: string) {
    let filterArray = [];
    let filtervalues = [];
    let filterURL = "";
    // if (this.resultTypes && this.resultTypes.countSelectedValues > 0) {
    //   filterURL += ((filterURL.length == 0) ? '?' : '&') + this.resultTypes.filterId + "=";
    //   let filterName = this.resultTypes.title + " ";
    //   for (let value of this.resultTypes.values) {
    //     if (value.selected) {
    //       filterArray.push(filterName + '"' + value.name + '"');
    //       filtervalues.push(value.name);
    //       filterURL += ((filterName.length == 0) ? ',' : '') + StringUtils.URIEncode('"' + value.id + '"');
    //       filterName = "";
    //     }
    //   }
    // }
    for (let filter of this.staticFilters) {
      if (filter.countSelectedValues > 0) {
        filterURL += ((filterURL.length == 0) ? '?' : '&') + filter.filterId + "=";
        let filterName = filter.title + " ";
        for (let value of filter.values) {
          if (value.selected) {
            filterArray.push(filterName + '"' + value.name + '"');
            filtervalues.push(value.name);
            filterURL += ((filterName.length == 0) ? ',' : '') + StringUtils.URIEncode('"' + StringUtils.URIEncode(value.id) + '"');
            filterName = "";

          }
        }
      }
    }
    for (let filter of this.filters) {
      if (filter.countSelectedValues > 0) {
        filterURL += ((filterURL.length == 0) ? '?' : '&') + filter.filterId + "=";
        let filterName = filter.title + " ";
        for (let value of filter.values) {
          if (value.selected) {
            filterArray.push(filterName + '"' + value.name + '"');
            filtervalues.push(value.name);
            filterURL += ((filterName.length == 0) ? ',' : '') + StringUtils.URIEncode('"' + StringUtils.URIEncode(value.id) + '"');
            filterName = "";
            
          }
        }
      }
    }
    let nonCanonicalizedPage = filterArray.length > 0;
    this.metaDescription = (nonCanonicalizedPage ? ((this.basicMetaDescription[0] + " filtered by: " + filterArray.join(" and ") + ". ") + (this.basicMetaDescription.length > 1 ? this.basicMetaDescription[1] : ""))
      : ((this.basicMetaDescription.length > 2 ? this.basicMetaDescription[1] + this.basicMetaDescription[2] : this.basicMetaDescription[0])));
    this._meta.updateTag({content: this.metaDescription}, "name='description'");
    this._meta.updateTag({content: this.metaDescription}, "property='og:description'");
    this.updateTitle(title, (nonCanonicalizedPage ? filtervalues.join(" | ") + " | " : ""));
    filterURL = (nonCanonicalizedPage ? filterURL : "");
    this.url = this.properties.domain + this.properties.baseLink + this.router.url.split('?')[0] + filterURL;
    this.seoService.createLinkForCanonicalURL(this.url + (this.searchUtils.page != 1 ? (filterURL.length > 0 ? '&' : '?') + 'page=' + this.searchUtils.page : ''), true);
    this.seoService.createLinkForNextURL(this.url + (filterURL.length > 0 ? '&' : '?') + 'page=' + (this.searchUtils.page + 1), true);
    if (this.searchUtils.page != 1) {
      this.seoService.createLinkForPrevURL(this.url + (this.searchUtils.page != 2 ? (filterURL.length > 0 ? '&' : '?') + 'page=' + (this.searchUtils.page - 1) : ''), true);
    } else {
      this.seoService.removeLinkForPrevURL();
    }
  }
  
  updateTitle(title: string, filters: string) {
    let _title = (this.hasPrefix ? this.prefix : "") + filters + title;
    // _title = ((_title.length > 50) ? _title.substring(0, 50) : _title);
    this.pageTitleWithFilters = _title;
    this._title.setTitle(_title);
    this._meta.updateTag({content: _title}, "property='og:title'");
  }
  
  updateUrl(url: string) {
    this._meta.updateTag({content: url}, "property='og:url'");
  }
  
  
  clearFilters() {
    for (var i = 0; i < this.filters.length; i++) {
      for (var j = 0; j < this.filters[i].countSelectedValues; j++) {
        if (this.filters[i].values[j].selected) {
          this.filters[i].values[j].selected = false;
        }
        this.filters[i].countSelectedValues = 0;
        this.filters[i].radioValue = "";
      }
    }
    this.selectedFilters = 0;
    for (let i = 0; i < this.rangeFilters.length; i++) {
      this.rangeFilters[i].selectedFromValue = null;
      this.rangeFilters[i].selectedToValue = null;
    }
    this.selectedRangeFilters = 0;
    // if (this.quickFilter) {
    //   this.removeValueFromQuickFilter();
    // }
    for (var i = 0; i < this.staticFilters.length; i++) {
      for (var j = 0; j < this.staticFilters[i].countSelectedValues; j++) {
        if (this.staticFilters[i].values[j].selected) {
          this.staticFilters[i].values[j].selected = false;
        }
        this.staticFilters[i].countSelectedValues = 0;
        this.staticFilters[i].radioValue = "";
      }
    }
    this.selectedStaticFilters = 0;
    // if (this.resultTypes) {
    //   this.resultTypes.values = [];
    // }
    this.goTo(1);
    // this.clearKeywords();
  }
  
  goTo(page: number = 1, scroll: boolean = true) {
    if (this.mobileFilters && (typeof document !== 'undefined')) {
      UIkit.offcanvas(this.mobileFilters.nativeElement).hide();
    }
    
    this.searchUtils.page = page;
    this.buildPageURLParameters(this.filters, this.rangeFilters, this.staticFilters, true);
    this.router.navigate([this.searchUtils.baseUrl], {queryParams: this.routerHelper.createQueryParams(this.parameterNames, this.parameterValues)});
    if (scroll) {
      HelperFunctions.scrollToId("searchForm");
    }
    /* Code For Piwik*/
    if (typeof localStorage !== 'undefined') {
      //console.log("In PreviousRouteRecorder : "+this.router.url );
      localStorage.setItem('previousRoute', this.router.url);
    }
    this.subscriptions.push(this._piwikService.trackView(this.properties, this.pageTitle).subscribe());
    /* End Piwik Code */
  }
  
  queryChanged($event) {
    this.cdr.detectChanges();
    if ($event == "filters_update") {
      return;
    }
    this.goTo(1, false);
  }
  
  
  sizeChanged($event) {
    this.searchUtils.size = $event;
    this.goTo(1);
  }
  
  sortByChanged($event) {
    //this.searchUtils.sortBy = $event.value;
    this.sortedByChanged = $event;
    this.goTo(1);
  }
  
  
  getOperatorParameter(parameter: string): string {
    for (let id of this.fieldIds) {
      if (this.fieldIdsMap[id]["param"] == parameter) {
        return this.fieldIdsMap[id]["operator"];
      }
    }
  }
  
  /*
* Get A sub-array of this.refineFields array, which contains the ids of the selected filters
*/
  public getSelectedFilters(): Map<string, string[]> {
    var selected: Map<string, string[]> = new Map<string, string[]>();
    var filters = this.URLCreatedFilters;
    for (var i = 0; i < filters.length; i++) {
      var filter: Filter = filters[i];
      if (filter.countSelectedValues > 0) {
        let selectedValues: string[] = [];
        for(let value of filter.values) {
          if(value.selected) {
            selectedValues.push(value.id);
          }
        }
        selected.set(filter.filterId, selectedValues);
      }
    }
    return selected;
  }
  
  /*
    * Get A sub-array of this.refineFields array, which contains the ids of the selected parameters
    */
  private getSelectedParameters(): Map<string, string[]> {
    var selected: Map<string, string[]> = new Map<string, string[]>();
    for (var i = 0; i < this.refineFields.length; i++) {
      let selectedValues: string[] = [];
      let index = this.parameterNames.indexOf(this.refineFields[i]);
      if (index != -1) {
        for(let values of this.parameterValues[index]) {
          let split = values.split('"');
          for(let value of split) {
            if(value != "" && value != ",") {
              selectedValues.push(value);
            }
          }
        }
        selected.set(this.refineFields[i], selectedValues);
      }
    }
    return selected;
  }

  /*
* Get A sub-array of this.staticFields array, which contains the ids of the selected filters
*/
  public getSelectedStaticFilters(): Map<string, string[]> {
    var selected: Map<string, string[]> = new Map<string, string[]>();
    var filters = this.URLCreatedStaticFilters;
    for (var i = 0; i < filters.length; i++) {
      var filter: Filter = filters[i];
      if (filter.countSelectedValues > 0) {
        let selectedValues: string[] = [];
        for(let value of filter.values) {
          if(value.selected) {
            selectedValues.push(value.id);
          }
        }
        selected.set(filter.filterId, selectedValues);
      }
    }
    return selected;
  }

  /*
    * Get A sub-array of this.staticFields array, which contains the ids of the selected parameters
    */
  private getSelectedStaticParameters(): Map<string, string[]> {
    var selected: Map<string, string[]> = new Map<string, string[]>();
    for (var i = 0; i < this.staticFields.length; i++) {
      let selectedValues: string[] = [];
      let index = this.parameterNames.indexOf(this.staticFields[i]);
      if (index != -1) {
        let split = this.parameterValues[index].split('"');
        for(let value of split) {
          if(value != "" && value != ",") {
            selectedValues.push(value);
          }
        }
        selected.set(this.staticFields[i], selectedValues);
      }
    }
    return selected;
  }

  /*
  * Get A sub-array of this.refineFields array, which hides hidden fields (e.g Funding level 0,1,2,..), and contains those that depend on another fields (e.g  Funding level 0 if Funder is selected )
  */
  public getFields(): string[] {
    var selected_filters: Map<string, string[]> = this.getSelectedFilters();
    if (selected_filters.size == 0) {
      selected_filters = this.getSelectedParameters();
    }

    var selected_static_filters: Map<string, string[]> = this.getSelectedStaticFilters();
    if (selected_static_filters.size == 0) {
      selected_static_filters = this.getSelectedStaticParameters();
    }

    let all_selected_filters = new Map([...selected_filters, ...selected_static_filters]);
    // let all_selected_filters = selected_filters.concat(selected_static_filters);

    var fields: string[] = [];
    for (var i = 0; i < this.refineFields.length; i++) {
      var dependentTo = this.searchFieldsHelper.DEPENDENT_FIELDS[this.refineFields[i]];
      var dependentToValues = this.searchFieldsHelper.DEPENDENT_FIELDS_AND_VALUES[this.refineFields[i]];
      // TODO check again the checks
      //if filter is not marked as hidden OR it is hidden but it is dependent to a field that it IS selected
      if (this.searchFieldsHelper.HIDDEN_FIELDS.indexOf(this.refineFields[i]) == -1
        || (all_selected_filters.has(this.refineFields[i]))
        || (!dependentTo && !dependentToValues)
        || (all_selected_filters.has(dependentTo))
        || (dependentToValues && (all_selected_filters.has(dependentToValues.field) && dependentToValues.values.some(dependentValue=> all_selected_filters.get(dependentToValues.field).includes(dependentValue))))
        || (this.resultTypes && this.resultTypes.filterId == dependentTo && this.resultTypes.countSelectedValues > 0)
        // || (this.resultAccesses && this.resultAccesses.filterId == dependentTo && this.resultAccesses.countSelectedValues > 0)
      ) {
        fields.push(this.refineFields[i]);
      }
    }
    return fields;
  }
  
  /*
  * Get a query  string of all fields, that want to get from search (e.g. &fields=funderid&fields=projectstartyear&...))
  */
  public getRefineFieldsQuery(): string {
    
    var fields: string[] = this.getFields();
    var fieldsStr = ""
    for (var i = 0; i < fields.length; i++) {
      fieldsStr += "&fields=" + fields[i];
    }
    return "&refine=true" + fieldsStr;
  }
  
  
  /*
  * Mark as check the new filters that are selected, when you get them from search
  */
  public checkSelectedFilters(filters: Filter[]) {
    this.filters = filters;
    if (this.customFilters) {
      for (let customFilter of this.customFilters) {
        if (!customFilter.isHiddenFilter) {
          customFilter.selected = null;
        }
      }
    }
    for (var i = 0; i < filters.length; i++) {
      var filter: Filter = filters[i];
      filter.countSelectedValues = 0;
      if (this.parameterNames.indexOf(filter.filterId) != -1) {
        let values = (decodeURIComponent(this.parameterValues[this.parameterNames.indexOf(filter.filterId)])).split(/,(?=(?:[^\"]*\"[^\"]*\")*[^\"]*$)/, -1);
        for (let filterValue of filter.values) {
          if (values.indexOf(StringUtils.quote(filterValue.id)) > -1) {
            filterValue.selected = true;
            filter.countSelectedValues++;
          } else {
            filterValue.selected = false;
            
          }
        }
        if (this.customFilters) {
          for (let customFilter of this.customFilters) {
            customFilter.selected = customFilter.queryFieldName == filter.filterId && values.indexOf(StringUtils.quote(customFilter.valueId)) != -1;
          }
        }
        // } else if (this.quickFilter && this.quickFilter.filterId == filter.filterId && this.quickFilter.selected) {
        //   for (let filterValue of filter.values) {
        //     if (filterValue.id == this.quickFilter.value) {
        //       filterValue.selected = true;
        //       filter.countSelectedValues++;
        //     } else {
        //       filterValue.selected = false;
        //     }
        //   }
      } else {
        for (let filterValue of filter.values) {
          filterValue.selected = false;
        }
      }
      // if (this.quickFilter && filter.filterId == this.quickFilter.filterId) {
      //   this.quickFilter.filter = filter;
      // }
    }
    this.filterFilterValues(this.filters);
    if (!this.includeOnlyResultsAndFilter) {
      this.updateMeta(this.pageTitle);
    }
    return filters;
  }
  
  /*
* Mark as check the new range filters that are selected
*/
  public checkSelectedRangeFilters(filters: RangeFilter[]) {
    //console.log("checkSelectedRangeFilters: parameterNames.length: "+this.parameterNames.length);
    
    this.rangeFilters = filters;
    for (let i = 0; i < filters.length; i++) {
      let filter: RangeFilter = filters[i];
      
      if (this.parameterNames.indexOf(filter.filterId) != -1) {
        //console.log(filter.filterId + " "+this.parameterNames.indexOf(filter.filterId) );
        let values = (decodeURIComponent(this.parameterValues[this.parameterNames.indexOf(filter.filterId)])).split(/,(?=(?:[^\"]*\"[^\"]*\")*[^\"]*$)/, -1);
        let operators: string [] = (StringUtils.URIDecode(this.parameterValues[this.parameterNames.indexOf(filter.filterId)])).split(/,(?=(?:[^\"]*\"[^\"]*\")*[^\"]*$)/, -1);
        if (values.length == operators.length) {
          for (let j = 0; j < values.length; j++) {
            if (this.fieldIdsMap[filter.originalFilterIdFrom + "-range-" + filter.originalFilterIdTo].filterType == "range") {
              let value: string = StringUtils.unquote(values[j]);
              let validDates: boolean = true;
              
              let years: string[] = (value.substring(5)).split(":");
              let yearFrom: string = (Dates.isValidYear(years[0]) ? years[0] : null);
              let yearTo: string = (Dates.isValidYear(years[1]) ? years[1] : null);
              //console.log("checkSelectedRangeFilters: yearFrom: " + yearFrom + " - yearTo: "+yearTo);
              if (yearFrom) {
                filter.selectedFromValue = yearFrom;
              }
              if (yearTo) {
                filter.selectedToValue = yearTo;
              }
              if (yearFrom && yearTo) {
                filter.selectedFromAndToValues = yearFrom + "-" + yearTo;
              } else if (yearFrom) {
                filter.selectedFromAndToValues = "From " + yearFrom;
              } else if (yearTo) {
                filter.selectedFromAndToValues = "Until " + yearTo;
              }
              
              if (!yearFrom && !yearTo) {
                validDates = false;
              }
              
              // if (value.length < 14) {
              //   validDates = false;
              //   console.log("not valid (length<14)");
              // } else {
              //   if (!Dates.isValidYear(value.substring(5, 9)) || !Dates.isValidYear(value.substring(10, 14))) {
              //     validDates = false;
              //     console.log("not valid years");
              //   } else {
              //     filter.selectedFromValue = value.substring(5, 9);
              //     filter.selectedToValue = value.substring(10, 14);
              //     console.log(filter);
              //   }
              // }
            }
          }
        }
      } else {
        filter.selectedFromValue = null;
        filter.selectedToValue = null;
      }
    }
    return this.rangeFilters;
  }

  public checkSelectedStaticFilters(filters: Filter[]) {
    for (var i = 0; i < filters.length; i++) {
      var filter: Filter = filters[i];
      filter.countSelectedValues = 0;
      if (this.parameterNames.indexOf(filter.filterId) != -1) {
        let values = (decodeURIComponent(this.parameterValues[this.parameterNames.indexOf(filter.filterId)])).split(/,(?=(?:[^\"]*\"[^\"]*\")*[^\"]*$)/, -1);
        for (let filterValue of filter.values) {
          if (values.indexOf(StringUtils.quote(filterValue.id)) > -1) {
            filterValue.selected = true;
            filter.countSelectedValues++;
          } else {
            filterValue.selected = false;

          }
        }
      } else {
        for (let filterValue of filter.values) {
          filterValue.selected = false;
        }
      }
    }
    this.filterFilterValues(this.filters);
    if (!this.includeOnlyResultsAndFilter) {
      this.updateMeta(this.pageTitle);
    }
    this.staticFilters = filters;
    return filters;
  }

  get existingFiltersWithValues() {
    if (this.filters.length == 0) {
      return 0;
    }
    return this.filters.some(filter => (filter.values && filter.values.length > 0));
  }
  
  /*
  * For Funder filters - if funder selected
  */
  public filterFilterValues(filters: Filter[]) {
    var funders = [];
    var funder_prefix = [];
    for (var i = 0; i < filters.length; i++) {
      
      var filter: Filter = filters[i];
      //  console.log(filter.filterId);
      if (filter.filterId.indexOf("funder") != -1 && this.parameterNames.indexOf(filter.filterId) != -1) {
        let funders = (decodeURIComponent(this.parameterValues[this.parameterNames.indexOf(filter.filterId)])).split(/,(?=(?:[^\"]*\"[^\"]*\")*[^\"]*$)/, -1);
        for (let funder of funders) {
          funder_prefix.push(StringUtils.unquote(funder).split("____")[0]);
        }
        //  console.log(funder_prefix );
      } else if (filter.filterId.indexOf("funding") != -1) {
        //  console.log(" funding: "+filter.filterId );
        var filteredValues = []
        for (let filterValue of filter.values) {
          var value_prefix = filterValue.id.split("____")[0];
          //  console.log("Value prefix: "+value_prefix );
          if (funder_prefix.indexOf(value_prefix) != -1) {
            //  console.log("here" + value_prefix);
            filteredValues.push(filterValue);
          }
          
        }
        if (filteredValues.length > 0) {
          filter.values = filteredValues;
        }
      }
      
    }
    
    return filters;
  }
  
  public countSelectedFilters(filters: Filter[]): number {
    this.selectedFilters = 0;
    for (let filter of filters) {
      if (filter.countSelectedValues > 0) {
        this.selectedFilters += filter.countSelectedValues;
      }
    }
    return this.selectedFilters;
  }
  
  public countSelectedRangeFilters(rangeFilters: RangeFilter[]): number {
    this.selectedRangeFilters = 0;
    for (let filter of rangeFilters) {
      if (filter.selectedFromValue || filter.selectedToValue) {
        this.selectedRangeFilters++;
      }
    }
    return this.selectedRangeFilters;
  }

  public countSelectedStaticFilters(filters: Filter[]): number {
    this.selectedStaticFilters = 0;
    for (let filter of filters) {
      if (filter.countSelectedValues > 0) {
        this.selectedStaticFilters += filter.countSelectedValues;
      }
    }
    return this.selectedStaticFilters;
  }

  private clearKeywords() {
    if (this.searchUtils.keyword.length > 0) {
      this.searchUtils.keyword = '';
    }
    this.goTo(1);
  }
  
  public removeFilter(value: Value, filter: Filter, forceRemove: boolean = false) {
    this.currentValueToRemove = value;
    this.currentFilterToRemove = filter;
    filter.countSelectedValues--;
    this.selectedFilters--;
    if (value.selected == true) {
      value.selected = false;
    }
    if (filter.filterType == "radio") {
      filter.radioValue = "";
    }
    // if (this.quickFilter && this.quickFilter.filterId == filter.filterId) {
    //   this.removeValueFromQuickFilter();
    // }
    this.goTo(1);
  }

  public removeRangeFilter(filter: RangeFilter) {
    filter.selectedFromValue = null;
    filter.selectedToValue = null;
    this.goTo(1);
  }
  
  getSelectedValues(filter): any {
    var selected = [];
    if (filter.countSelectedValues > 0) {
      for (var i = 0; i < filter.values.length; i++) {
        if (filter.values[i].selected) {
          selected.push(filter.values[i]);
        }
      }
    }
    return selected;
    
  }
  
  filterChanged($event) {
    /*    if (this.quickFilter && this.quickFilter.filter) {
          this.removeValueFromQuickFilter();
        }*/
    this.goTo(1);
    
  }

  filterToggled($event) {
    this.filterRequestAll.emit($event)
  }

  /**
   * if there is a change in the values of the quick filter, this function has to be run, to also update the quickFilter
   */
  
  /*  removeValueFromQuickFilter() {
      if (this.quickFilter.filter.countSelectedValues == 0) {
        this.quickFilter.selected = false;
      } else {
        let isQuickEnabled = false;
        for (let filterValue of this.quickFilter.filter.values) {
          isQuickEnabled = (filterValue.name == this.quickFilter.value)
        }
        this.quickFilter.selected = (isQuickEnabled && this.quickFilter.filter.countSelectedValues == 1);
      }
    }*/
  

  // for loading
  public openLoading() {
    this.loading.open();
  }
  
  public closeLoading() {
    this.loading.close();
  }
  
  /**
   * Build advanced search Filters based on the URL parameters
   * @param params
   */
  createAdvancedSearchSelectedFiltersFromNewURLParameters(params) {
    for (let i = 0; i < Object.keys(params).length; i++) {
      if (params["f" + i] && params["fv" + i]) {
        let fieldId = params["f" + i].split(",")[0];
        let operator = (params["f" + i].split(",").length > 1) ? params["f" + i].split(",")[1] : "and";
        let not: boolean = params["fo" + i] === "not";
        let fieldparam = (this.fieldIdsMap[fieldId]) ? this.fieldIdsMap[fieldId].param : "";
        
        if (!this.fieldIdsMap[fieldId]) {
          console.error("Field: " + fieldId + " not found in fieldIds map");
          continue;
        }
        let value: string = StringUtils.URIDecode(params["fv" + i]);
        if (this.fieldIdsMap[fieldId].type == "date") {
          let validDates: boolean = true;
          let dateField: AdvancedField = new AdvancedField(fieldId, fieldparam, this.fieldIdsMap[fieldId].name, this.fieldIdsMap[fieldId].type, value, operator, !not);
          if (value.indexOf("range") != -1) {
            dateField.dateValue.type = "range";
            if (value.length < 26) {
              validDates = false;
            } else {
              if (!Dates.isValidDate(value.substring(5, 15)) || !Dates.isValidDate(value.substring(16, 26))) {
                validDates = false;
              } else {
                dateField.dateValue.from = Dates.getDateFromString(value.substring(5, 15));
                dateField.dateValue.to = Dates.getDateFromString(value.substring(16, 26));
              }
            }
            //  "rangeYYYY-MM-DD:YYYY-MM-DD"
          } else {
            dateField.dateValue.setDatesByType(value);
          }
          if (validDates) {
            this.selectedFields.push(dateField);
          }
          
        } else {
          this.selectedFields.push(new AdvancedField(fieldId, fieldparam, this.fieldIdsMap[fieldId].name, this.fieldIdsMap[fieldId].type, value, operator, !not));
        }
        
      }
    }
  }
  
  /**
   * Build advanced search Filters based on the URL parameters
   * @param params
   */
  createAdvancedSearchSelectedFiltersFromURLParameters(params) {
    this.createAdvancedSearchSelectedFiltersFromNewURLParameters(params);
    for (var i = 0; i < this.fieldIds.length; i++) {
      var fieldId = this.fieldIds[i];
      var fieldparam = (this.fieldIdsMap[fieldId]) ? this.fieldIdsMap[fieldId].param : "";
      if (!this.fieldIdsMap[fieldId]) {
        console.error("Field: " + fieldId + " not found in fieldIds map");
        continue;
      }
      
      var operatorId = this.getOperatorParameter(fieldparam);
      if (params[fieldparam] != undefined && params[operatorId] != undefined) {
        var values: string [] = StringUtils.URIDecode(params[fieldparam]).split(/,(?=(?:[^\"]*\"[^\"]*\")*[^\"]*$)/, -1);
        var operators: string [] = (StringUtils.URIDecode(params[operatorId])).split(/,(?=(?:[^\"]*\"[^\"]*\")*[^\"]*$)/, -1);
        if (values.length == operators.length) {
          for (var j = 0; j < values.length; j++) {
            if (this.fieldIdsMap[fieldId].type == "date") {
              var value: string = StringUtils.unquote(values[j]);
              var validDates: boolean = true;
              var dateField: AdvancedField = new AdvancedField(fieldId, fieldparam, this.fieldIdsMap[fieldId].name, this.fieldIdsMap[fieldId].type, value, operators[j]);
              if (value.indexOf("range") != -1) {
                dateField.dateValue.type = "range";
                if (value.length < 26) {
                  validDates = false;
                } else {
                  if (!Dates.isValidDate(value.substring(5, 15)) || !Dates.isValidDate(value.substring(16, 26))) {
                    validDates = false;
                  } else {
                    dateField.dateValue.from = Dates.getDateFromString(value.substring(5, 15));
                    dateField.dateValue.to = Dates.getDateFromString(value.substring(16, 26));
                  }
                }
                //  "rangeYYYY-MM-DD:YYYY-MM-DD"
              } else {
                dateField.dateValue.setDatesByType(value);
              }
              if (validDates) {
                this.selectedFields.push(dateField);
              }
              
            } else {
              this.selectedFields.push(new AdvancedField(fieldId, fieldparam, this.fieldIdsMap[fieldId].name, this.fieldIdsMap[fieldId].type, values[j], operators[j]));
            }
          }
        }
      }
    }
    if (params['keyword'] && params['keyword'].length > 0) {
      this.selectedFields.push(new AdvancedField(this.fieldIds[0], this.fieldIdsMap[this.fieldIds[0]].param, this.fieldIdsMap[this.fieldIds[0]].name, this.fieldIdsMap[this.fieldIds[0]].type, params['keyword'], "and"));
    }
    if (this.selectedFields.length == 0) {
      this.selectedFields.push(new AdvancedField(this.fieldIds[0], this.fieldIdsMap[this.fieldIds[0]].param, this.fieldIdsMap[this.fieldIds[0]].name, this.fieldIdsMap[this.fieldIds[0]].type, "", "and"));
    }
  }
  
  /**
   * Create Search API query based on the selected fields of the advanced form
   */
  getSearchAPIQueryForAdvancedSearhFields(URLparams = null) {
    
    var params = "";
    var countParams = 0;
    for (var i = 0; i < this.selectedFields.length; i++) {
      if (this.fieldIdsMap[this.selectedFields[i].id] != undefined && (this.selectedFields[i].value != "" || this.selectedFields[i].type == "date")) {
        //console.log("createQueryParameters::"+this.selectedFields[i].type);
        if (this.selectedFields[i].type == "date") {
          if (this.selectedFields[i].dateValue.type != "any") {
            params += (countParams == 0 ? "" : this.selectedFields[i].operatorId) + " " + this.selectedFields[i].id + this.fieldIdsMap[this.selectedFields[i].id].equalityOperator + '"' + StringUtils.URIEncode(Dates.getDateToString(this.selectedFields[i].dateValue.from)) + " "
              + StringUtils.URIEncode(Dates.getDateToString(this.selectedFields[i].dateValue.to)) + '"' + " ";
          }
        } else {
          if (this.selectedFields[i].id == "q") {
            // console.log(this.selectedFields[i].value)
            /*            var op = "";
                        var doisParams = "";
                        if ((this.entityType == 'publication' || this.entityType == 'dataset' || this.entityType == 'software' || this.entityType == 'other' || this.entityType == "result")) {
                          var DOIs: Identifier[] = Identifier.getIdentifiersFromString(this.selectedFields[i].value);
                          for (let identifier of DOIs) {
                            // console.log(identifier)
                            // pidclassid exact \"doi\" and pid exact \"10.1016/j.nima.2015.11.134\"
                            //and (authorid exact \"0000-0001-7291-3210 \" )"
                            if(identifier.class == "ORCID"){
                              doisParams += (doisParams.length > 0 ? " or " : "") +'(authorid="' + identifier.id + '")';
                            }else{
                              doisParams += (doisParams.length > 0 ? " or " : "") +'(pidclassid exact "' + identifier.class + '" and pid="' +  identifier.id + '")';
                            }
                          }
                        }
                        if (doisParams.length > 0) {
                          params += this.createQuotedKeywordQuery(this.selectedFields[i].value, this.selectedFields[i].id, this.selectedFields[i].operatorId ,countParams,true, true) + " or " + doisParams;
                        } else {
                          params += this.createQuotedKeywordQuery(this.selectedFields[i].value, this.selectedFields[i].id, this.selectedFields[i].operatorId,countParams,true);
                        }*/
            params += NewSearchPageComponent.createKeywordQuery(this.entityType, this.selectedFields[i].value, this.selectedFields[i].id, this.selectedFields[i].operatorId, countParams, this.selectedFields[i].includes);
            //TODO deposit case
            // console.log(this.usedBy)
            // console.log(this.keywordFields)
            if (this.usedBy == "deposit") {
              
              if (this.keywordFields.length > 0) {
                params += " or ("
              }
              for (let j = 0; j < this.keywordFields.length; j++) {
                if (j > 0) {
                  params += " or "
                }
                params += NewSearchPageComponent.createQuotedKeywordQuery(this.selectedFields[i].value, this.keywordFields[j].name, " or ", countParams, false);
                // let field = this.keywordFields[i];
                //keywordQuery += field.name+field.equalityOperator+StringUtils.URIEncode(keyword);
                // params += field.name+field.equalityOperator+StringUtils.quote(StringUtils.URIEncode(keyword));
              }
              if (this.keywordFields.length > 0) {
                params += " ) "
              }
            }
            
          } else if (this.selectedFields[i].type == "identifier") {
            params += NewSearchPageComponent.createKeywordQuery(this.entityType, this.selectedFields[i].value, this.selectedFields[i].id, this.selectedFields[i].operatorId, countParams);
          } else if (countParams == 0 && this.selectedFields[i].operatorId == "not" && this.fieldIdsMap[this.selectedFields[i].id].equalityOperator != "=") {
            params += " " + this.selectedFields[i].id + " <> " + '"' + StringUtils.URIEncode(this.selectedFields[i].value) + '"' + " ";
          } else if (!this.selectedFields[i].includes) {
            params += (i > 0?this.selectedFields[i].operatorId:'') + " (*=* NOT " + this.selectedFields[i].id + this.fieldIdsMap[this.selectedFields[i].id].equalityOperator + '"' + StringUtils.URIEncode(this.selectedFields[i].value) + '"' + ") ";
          } else if (this.fieldIdsMap[this.selectedFields[i].id].equalityOperator == "=") {
            params += NewSearchPageComponent.createQuotedKeywordQuery(this.selectedFields[i].value, this.selectedFields[i].id, this.selectedFields[i].operatorId, countParams, false);
          } else {
            params += (countParams == 0 ? "" : " " + this.selectedFields[i].operatorId + " ") + this.selectedFields[i].id + this.fieldIdsMap[this.selectedFields[i].id].equalityOperator + '"' + encodeURIComponent(this.selectedFields[i].value) + '"' + " ";
          }
        }
        countParams++;
      }
    }

    if (this.entityType == "service" && URLparams) {
      if (URLparams["type"]) {
        let types1 = URLparams["type"];
        types1 = Array.isArray(types1) ? types1.join(',').split(",") : types1.split(",");
        types1.map(function (t) {
          return StringUtils.unquote(StringUtils.URIDecode(t));
        });

        let types = URLparams["type"];
        types = Array.isArray(types) ? types.join(',').split(",") : types.split(",");
        types.map(function (t) {
          return StringUtils.unquote(StringUtils.URIDecode(t));
        });

        if (types.indexOf("datasources") == -1 || types.indexOf("services") == -1) {
          for (let type of types) {
            params += (params ? ' and ' : '') + ("eosctype exact " + (types.indexOf("datasources") != -1 ? "\"Data Source\"" : "\"Service\""));
            // allFqs += "&type=" + StringUtils.unquote(StringUtils.URIDecode(type));
          }
        }
      }
    }
    
    // console.log("ParameterS:")
    // console.log(params)
    return params;
  }
  
  public static createKeywordQuery(entityType: string, value: string, id, operatorId, countParams = 0, includes: boolean = true) {
    let params = "";
    let doisParams = "";
    var DOIs: Identifier[] = Identifier.getIdentifiersFromString(value);
    if ((entityType == 'publication' || entityType == 'dataset' || entityType == 'software' || entityType == 'other' || entityType == "result" || entityType == "dataprovider" || entityType == "service" || entityType == "organization")) {
      for (let identifier of DOIs) {
        // console.log(identifier)
        // pidclassid exact \"doi\" and pid exact \"10.1016/j.nima.2015.11.134\"
        //and (authorid exact \"0000-0001-7291-3210 \" )"
        if (identifier.class == "ORCID") {
          doisParams += (doisParams.length > 0 ? " or " : "") + '(authorid="' + StringUtils.URIEncode(identifier.id) + '")';
          // doisParams += (doisParams.length > 0 ? " or " : "") +'(authorid="' + StringUtils.URIEncode(identifier.id) + '" and (authoridtype exact "orcid"))';
        } else {
          doisParams += (doisParams.length > 0 ? " or " : "") + '(pid="' + StringUtils.URIEncode(identifier.id) + '")';
          // doisParams += (doisParams.length > 0 ? " or " : "") +'(pidclassid exact "' + identifier.class + '" and pid="' +  identifier.id + '")';
        }
      }
    }
    if (doisParams.length > 0) {
      params += this.createQuotedKeywordQuery(value, id, operatorId, countParams, true, true, includes) + " or " + doisParams;
    } else {
      //if it is PIDs but no doisquery produced, forced to use quotes as the query will fail due to special characters
      params += this.createQuotedKeywordQuery(value, id, operatorId, countParams, true,
        (DOIs.length > 0 && doisParams.length == 0), includes);
    }
    return params;
    
  }
  
  private static createQuotedKeywordQuery(fieldValue: string, fieldId, fieldOperator, countParams: number, isSearchAll: boolean, forceQuotted: boolean = false, includes: boolean = true) {
    let params = "";
    let countQuote = (fieldValue.match(/'/g) || []).length;
    let countDoubleQuote = (fieldValue.match(/"/g) || []).length;
    let quotedParts = [];
    if (countQuote % 2 == 0 && countDoubleQuote % 2 == 0) {
      quotedParts = (fieldValue) ? fieldValue.match(/(["'])(.*?)*?\1/g) : [];
    }
    params += (countParams == 0 ? "" : fieldOperator);
    if(!includes) {
      params += "(*=* NOT ";
    } else {
      params += " (";
    }
    if (forceQuotted) {
      /** Remove double quotes **/
      fieldValue = fieldValue.replace(/["]+/g, '');
      return params + this.getQuotedQueryPart(fieldId, '"' + fieldValue + '"', isSearchAll) + ")";
    }
    if (quotedParts && quotedParts.length == 1 && quotedParts[0] == fieldValue) {
      params += this.getQuotedQueryPart(fieldId, fieldValue, isSearchAll);
    } else if (quotedParts && quotedParts.length > 0) {
      for (let i = 0; i < quotedParts.length; i++) {
        params += (i > 0) ? " and " : "";
        params += this.getQuotedQueryPart(fieldId, quotedParts[i], isSearchAll);
      }
      let startPoint = 0;
      let endPoint = 0;
      for (let i = 0; i < quotedParts.length; i++) {
        let index = fieldValue.indexOf(quotedParts[i]);
        endPoint = (i + 1 < quotedParts.length) ? fieldValue.indexOf(quotedParts[i + 1]) : fieldValue.length;
        // console.log(fieldValue.indexOf(quotedParts[i+1]) +" - "+fieldValue.length);
        // console.log(" SP "+ startPoint+" EP: "+endPoint);
        if (index == startPoint) {
          startPoint += quotedParts[i].length;
        } else if (startPoint < index) {
          endPoint = index;
        }
        // console.log(" SP "+ startPoint+" EP: "+endPoint);
        if (decodeURIComponent(fieldValue.substring(startPoint, endPoint)).split(" ").join("").length > 0) {
          params += " and " + this.getNoQuotedQueryPart(fieldId, fieldValue.substring(startPoint, endPoint), isSearchAll);
        }
        // console.log("For "+i+"  " +params+" SP "+ startPoint+" EP: "+endPoint);
        // startPoint = (i+1<quotedParts.length)? fieldValue.indexOf(quotedParts[i+i]):fieldValue.length;//(startPoint<index  )?(index + quotedParts[i].length):fieldValue.length;
        startPoint = ((i + 1 < quotedParts.length) ? (fieldValue.indexOf(quotedParts[i + 1]) + quotedParts[i + 1].length) : (endPoint == index ? (index + quotedParts[i].length) : endPoint));
      }
      if (startPoint != fieldValue.length && decodeURIComponent(fieldValue.substring(startPoint, fieldValue.length)).split(" ").join("").length > 0) {
        params += " and " + this.getNoQuotedQueryPart(fieldId, fieldValue.substring(startPoint, fieldValue.length), isSearchAll);
      }
    } else {
      params += this.getNoQuotedQueryPart(fieldId, fieldValue, isSearchAll);
    }
    params += ")";
    return params;
  }
  
  private static getQuotedQueryPart(fieldId: string, value: string, isSearchAll: boolean) {
    return (isSearchAll ? "__all" : fieldId) + " exact " + StringUtils.URIEncode(value);
  }
  
  private static getNoQuotedQueryPart(fieldId: string, value: string, isSearchAll: boolean) {
    //split the keywords of the vlaue and query seperately for each keyword using quotes to allow characters like .@
    let valueKeywords = value.split(" ");
    let query = "";
    let i = 0;
    for (let keyword of valueKeywords) {
      if (keyword.length > 0) {
        query += (i != 0 ? " and " : "") + (isSearchAll ? "(" : fieldId + "=") + "\"" + StringUtils.URIEncode(this.checkForReservedWords(keyword)) + "\"" + (isSearchAll ? ")" : "");
        i++;
      }
    }
    return query;
  }
  
  private static checkForReservedWords(keyword: string) {
    let reservedWords = ["AND", "OR", "NOT"];
    if (reservedWords.indexOf(keyword) != -1) {
      return keyword.toLowerCase();
    }
    return keyword;
  }
  
  /**
   * Create Search API query based on the filters of refine fields
   * @param URLparams
   * @param firstLoad
   */
  getSearchAPIQueryForRefineFields(URLparams, firstLoad: boolean) {
    
    var allFqs = "";
    // console.log(this.refineFields)
    for (var i = 0; i < this.refineFields.length; i++) {
      var filterId = this.refineFields[i];
      
      if (URLparams[filterId] != undefined) {
        let values = (StringUtils.URIDecode(StringUtils.URIDecode(URLparams[filterId]))).split(/,(?=(?:[^\"]*\"[^\"]*\")*[^\"]*$)/, -1);
        var countvalues = 0;
        var fq = "";
        let filterOp: string = this.searchFieldsHelper.getFieldOperator(filterId);
        // console.info(filterId, filterOp);
        for (let value of values) {
          if (value && value.length > 0) {
            countvalues++;
            var paramId = this.fieldIdsMap[filterId].param;
            // parameters+='&' + paramId+ '='+ value;//+"&" + this.fieldIdsMap[paramId].operator + "="+((countvalues == 1)?"and":"or");
            fq += (fq.length > 0 ? " " + filterOp + " " : "") + filterId + " exact " + (value);
          }
        }
        if (countvalues > 0) {
          fq = "&fq=" + StringUtils.URIEncode(fq);
        }
        allFqs += fq;
      }
    }

    for (var i = 0; i < this.staticFields.length; i++) {
      var filterId = this.staticFields[i];
      if (URLparams[filterId] != undefined && filterId != "type") {
        let values = (StringUtils.URIDecode(StringUtils.URIDecode(URLparams[filterId]))).split(/,(?=(?:[^\"]*\"[^\"]*\")*[^\"]*$)/, -1);
        var countvalues = 0;
        var fq = "";
        let filterOp: string = this.searchFieldsHelper.getFieldOperator(filterId);
        for (let value of values) {
          if (value && value.length > 0) {
            countvalues++;
            fq += (fq.length > 0 ? " " + filterOp + " " : "") + filterId + " exact " + (value);
          }
        }
        if (countvalues > 0) {
          fq = "&fq=" + StringUtils.URIEncode(fq);
        }
        allFqs += fq;
      }
    }

    if (this.customFilters) {
      for (let customFilter of this.customFilters) {
        if (customFilter.isHiddenFilter) {
          if(customFilter.customQuery){
            allFqs += "&fq=" + StringUtils.URIEncode(customFilter.customQuery);
          }else {
            allFqs += "&fq=" + StringUtils.URIEncode(customFilter.queryFieldName + " exact " + StringUtils.quote((customFilter.valueId)));
          }
        }
      }
    }
    
    /*    if (this.quickFilter && this.entityType == "result") {
          if((URLparams[this.quickFilter.filterId] == undefined && URLparams["qf"] == undefined)   || URLparams["qf"] == "true"
            || ((URLparams[this.quickFilter.filterId] != undefined && StringUtils.URIDecode(URLparams[this.quickFilter.filterId]).split(/,(?=(?:[^\"]*\"[^\"]*\")*[^\"]*$)/, -1).indexOf(StringUtils.quote(this.quickFilter.value)) != -1))) {
            this.quickFilter.selected = true;
          } else {
            this.quickFilter.selected = false;
          }
          if( this.quickFilter.selected && URLparams[this.quickFilter.filterId] == undefined){
          // if ((firstLoad && URLparams[this.quickFilter.filterId] == undefined && URLparams["qf"] == undefined)
          // ||( URLparams[this.quickFilter.filterId] == undefined && URLparams["qf"] == "true")) {
            allFqs += "&fq=resultbestaccessright exact " + StringUtils.quote(this.quickFilter.value);
          }
        }*/
    
    if (this.entityType == "result") {
      if (URLparams["type"]) {
        let types = URLparams["type"];
        types = Array.isArray(types) ? types.join(',').split(",") : types.split(",");
        types.map(function (t) {
          return StringUtils.unquote(StringUtils.URIDecode(t));
        });

        if (types.indexOf("publications") != -1 && types.indexOf("datasets") != -1 && types.indexOf("software") != -1 && types.indexOf("other") != -1) {
          allFqs += "&type=results";
        } else {
          for (let type of types) {
            allFqs += "&type=" + StringUtils.unquote(StringUtils.URIDecode(type));
          }
        }
      } else {
        allFqs += "&type=results";
      }
    } else if (this.entityType == "publication") {
      allFqs += "&type=publications";
    } else if (this.entityType == "dataset") {
      allFqs += "&type=datasets";
    } else if (this.entityType == "software") {
      allFqs += "&type=software";
    } else if (this.entityType == "other") {
      allFqs += "&type=other";
    } else if (this.entityType == "project") {
      allFqs += "&type=projects";
    } else if (this.entityType == "organization") {
      allFqs += "&type=organizations";
    } else if (this.entityType == "dataprovider") {
      allFqs += "&type=datasources";
    }  else if (this.entityType == "service") {
      allFqs += "&type=services";
    }
    // console.log("AllFqs (check type): "+allFqs);
    // console.log("type: "+this.entityType);
    // var keyword = URLparams['keyword'];
    // var doiQuery = "";
    // var keywordQuery = "";
    // if((keyword && keyword.length > 0)){
    //   if((this.type == 'publications' ||this.type == 'research data' || this.type == 'software' || this.type == 'other research products')){
    //     var DOIs:string[] = DOI.getDOIsFromString(keyword);
    //     var doisParams = "";
    //
    //     for(var i =0 ;i < DOIs.length; i++){
    //       doisParams+=(doisParams.length > 0?"&":"")+'doi="'+ DOIs[i]+'"';
    //     }
    //     if(doisParams.length > 0){
    //       doiQuery += "&"+doisParams;
    //     }else {
    //       keywordQuery += "&q="+StringUtils.URIEncode(keyword);
    //     }
    //   }else{
    //     if(this.usedBy == "deposit") {
    //       if(this.keywordFields.length > 0) {
    //         keywordQuery = "&fq=";
    //       }
    //
    //       for(let i=0; i< this.keywordFields.length ; i++) {
    //         if(i > 0) {
    //           keywordQuery += " or ";
    //         }
    //         let field = this.keywordFields[i];
    //         //keywordQuery += field.name+field.equalityOperator+StringUtils.URIEncode(keyword);
    //         keywordQuery += field.name+field.equalityOperator+StringUtils.quote(StringUtils.URIEncode(keyword));
    //       }
    //     } else {
    //       keywordQuery += "&q=" + StringUtils.URIEncode(keyword);
    //     }
    //
    //   }
    // }
    //TODO add DOI?
    return allFqs;
    
  }
  
  /**
   * Create Search API query based on the filters of refine fields
   * @param URLparams
   */
  getSearchAPIQueryForRangeFields(URLparams) {
    let allFqs = "";
    for (let i = 0; i < this.rangeFields.length; i++) {
      let filterId = this.rangeFields[i][0] + "-range-" + this.rangeFields[i][1];
      let filterParam = this.searchFieldsHelper.getFieldParam(filterId, this.entityType);
      
      if (URLparams[filterParam] != undefined) {
        let values = (StringUtils.URIDecode(StringUtils.URIDecode(URLparams[filterParam]))).split(/,(?=(?:[^\"]*\"[^\"]*\")*[^\"]*$)/, -1);
        var countvalues = 0;
        var fq = "";
        var fqFrom = "";
        var fqTo = "";
        let filterOp: string = this.searchFieldsHelper.getFieldOperator(filterId);
        
        for (let value of values) {
          if (this.fieldIdsMap[filterId].filterType == "range") {
            
            let selectedFromValue;
            let selectedToValue;
            
            let years: string[] = (value.substring(5)).split(":");
            let yearFrom: string = (Dates.isValidYear(years[0]) ? years[0] : null);
            //(Number.isInteger(parseInt(years[0], 10)) ? years[0] : null);
            let yearTo: string = (Dates.isValidYear(years[1]) ? years[1] : null);
            //console.log("getSearchAPIQueryForRangeFields: yearFrom: " + yearFrom + " - yearTo: "+yearTo);
            if (yearFrom) {
              selectedFromValue = yearFrom;
            }
            if (yearTo) {
              selectedToValue = yearTo;
            }
            if (yearFrom || yearTo) {
              
              // if (value.length <= 14) {
              //   if(Dates.isValidYear(value.substring(5, 9))) {
              //     selectedFromValue = value.substring(5, 9);
              //   }
              //   if(Dates.isValidYear(value.substring(10, 14))) {
              //     selectedToValue = value.substring(10, 14);
              //   }
              
              /*if(this.rangeFields[i][0] == this.rangeFields[i][1]) {
                //console.log(selectedFromValue + " - "+selectedToValue);
                if (selectedFromValue && selectedToValue) {
                  let equalityOp = this.fieldIdsMap[filterId].equalityOperator;
                  fq += (fq.length > 0 ? " " + filterOp + " " : "") + this.rangeFields[i][0] + equalityOp + "\"" + selectedFromValue + " " + selectedToValue + "\"";
                  fq = "&fq=" + StringUtils.URIEncode(fq);
                } else if (selectedFromValue) {
                  let equalityOp = this.fieldIdsMap[this.rangeFields[i][0]].equalityOperator;
                  if(equalityOp == " = ") {
                    equalityOp = " >= ";
                  }
                  fq += (fq.length > 0 ? " " + filterOp + " " : "") + this.rangeFields[i][0] + equalityOp + "\"" + selectedFromValue + "\"";
                  fq = "&fq=" + StringUtils.URIEncode(fq);
                } else if (selectedToValue) {
                  let equalityOp = this.fieldIdsMap[this.rangeFields[i][1]].equalityOperator;
                  if(equalityOp == " = ") {
                    equalityOp = " <= ";
                  }
                  fq += (fq.length > 0 ? " " + filterOp + " " : "") + this.rangeFields[i][0] + equalityOp + "\"" + selectedToValue + "\"";
                  fq = "&fq=" + StringUtils.URIEncode(fq);
                }
              } else {
                let equalityOpFrom = this.fieldIdsMap[this.rangeFields[i][0]].equalityOperator;
                let equalityOpTo = this.fieldIdsMap[this.rangeFields[i][1]].equalityOperator;

                if (selectedFromValue) {
                  fq += (fq.length > 0 ? " " + filterOp + " " : "") + this.rangeFields[i][0] + equalityOpFrom + "\"" + selectedFromValue + "\"";
                  // fq = "&fq=" + StringUtils.URIEncode(fq);
                }
                if (selectedToValue) {
                  fq += (fq.length > 0 ? " " + filterOp + " " : "") + this.rangeFields[i][1] + equalityOpTo + "\"" + selectedToValue + "\"";
                  // fq = "&fq=" + StringUtils.URIEncode(fq);
                }
                if(selectedFromValue || selectedToValue) {
                  fq = "&fq=" + StringUtils.URIEncode(fq);
                }
              }*/
              fq = NewSearchPageComponent.createRangeFilterQuery(this.rangeFields[i], selectedFromValue, selectedToValue, this.fieldIdsMap[filterId].equalityOperator, this.fieldIdsMap[this.rangeFields[i][0]].equalityOperator, this.fieldIdsMap[this.rangeFields[i][1]].equalityOperator, filterOp);
            }
          }
        }
        allFqs += fq + fqFrom + fqTo;
      }
    }
    
    return allFqs;
    
  }
  
  // createRangeFilterQuery(this.rangeFields[i], selectedFromValue, selectedToValue, this.fieldIdsMap[this.rangeFields[i][0]].equalityOperator, this.fieldIdsMap[this.rangeFields[i][1]].equalityOperator; filterOp )
  public static createRangeFilterQuery(rangeField, selectedFromValue, selectedToValue, equalityOp, equalityOpFrom, equalityOpTo, filterOp) {
    let fq = "";
    if (rangeField[0] == rangeField[1]) {
      //console.log(selectedFromValue + " - "+selectedToValue);
      if (selectedFromValue && selectedToValue) {
        fq += (fq.length > 0 ? " " + filterOp + " " : "") + rangeField[0] + equalityOp + "\"" + selectedFromValue + " " + selectedToValue + "\"";
        fq = "&fq=" + StringUtils.URIEncode(fq);
      } else if (selectedFromValue) {
        if (equalityOpFrom == " = ") {
          equalityOpFrom = " >= ";
        }
        fq += (fq.length > 0 ? " " + filterOp + " " : "") + rangeField[0] + equalityOpFrom + "\"" + selectedFromValue + "\"";
        fq = "&fq=" + StringUtils.URIEncode(fq);
      } else if (selectedToValue) {
        if (equalityOpTo == " = ") {
          equalityOpTo = " <= ";
        }
        fq += (fq.length > 0 ? " " + filterOp + " " : "") + rangeField[0] + equalityOpTo + "\"" + selectedToValue + "\"";
        fq = "&fq=" + StringUtils.URIEncode(fq);
      }
    } else {
      
      if (selectedFromValue) {
        fq += (fq.length > 0 ? " " + filterOp + " " : "") + rangeField[0] + equalityOpFrom + "\"" + selectedFromValue + "\"";
        // fq = "&fq=" + StringUtils.URIEncode(fq);
      }
      if (selectedToValue) {
        fq += (fq.length > 0 ? " " + filterOp + " " : "") + rangeField[1] + equalityOpTo + "\"" + selectedToValue + "\"";
        // fq = "&fq=" + StringUtils.URIEncode(fq);
      }
      if (selectedFromValue || selectedToValue) {
        fq = "&fq=" + StringUtils.URIEncode(fq);
      }
      
    }
    return fq;
  }
  
  /**
   * Sets parameterNames and parameterValues arrays
   * used in paging, advanced search link, Goto()
   * @param filters either query filters or filters defined by the URL parameters
   * @param rangeFilters defined by the URL parameters
   * @param staticFilters
   * @param includePage
   */
  buildPageURLParameters(filters: Filter[], rangeFilters: RangeFilter[], staticFilters: Filter[], includePage: boolean) {
    this.parameterNames.splice(0, this.parameterNames.length);
    this.parameterValues.splice(0, this.parameterValues.length);
    for (var i = 0; i < this.selectedFields.length; i++) {
      //default operator is and
      if ((this.selectedFields[i].value && this.selectedFields[i].value.length > 0) || this.selectedFields[i].type == "date") {
        this.parameterNames.push("f" + i);
        this.parameterValues.push(this.selectedFields[i].id + (this.selectedFields[i].operatorId != 'and' ? ("," + this.selectedFields[i].operatorId) : ''));
        if(!this.selectedFields[i].includes) {
          this.parameterNames.push("fo" + i);
          this.parameterValues.push("not");
        }
        this.parameterNames.push("fv" + i);
      }
      if (this.selectedFields[i].type == "date") {
        
        if (this.selectedFields[i].dateValue.type == "range") {
          this.parameterValues.push(StringUtils.URIEncode("range" + Dates.getDateToString(this.selectedFields[i].dateValue.from) + ":" + Dates.getDateToString(this.selectedFields[i].dateValue.to)));
        } else {
          this.parameterValues.push(StringUtils.URIEncode(this.selectedFields[i].dateValue.type));
        }
        
      } else if (this.selectedFields[i].value && this.selectedFields[i].value.length > 0) {
        // console.log(this.selectedFields[i].value +" " + StringUtils.URIEncode(this.selectedFields[i].value))
        this.parameterValues.push(StringUtils.URIEncode(this.selectedFields[i].value));
      }
    }
    if (includePage && this.searchUtils.page != 1) {
      this.parameterNames.push("page");
      this.parameterValues.push("" + this.searchUtils.page);
    }
    
    if (this.searchUtils.size != this.searchUtils.defaultSize) {
      this.parameterNames.push("size");
      this.parameterValues.push("" + this.searchUtils.size);
    }
    
    //if (this.sort && this.searchUtils.sortBy) {
    if (this.sort && this.sortedByChanged && this.sortedByChanged.length > 0) {
      this.parameterNames.push("sortBy");
      //this.parameterValues.push(this.searchUtils.sortBy);
      this.parameterValues.push(this.sortedByChanged);
    }

    for (let filter of staticFilters) {
      var filterLimits = "";
      if (filter.countSelectedValues > 0) {
        for (let value of filter.values) {
          if (value.selected == true) {
            filterLimits += ((filterLimits.length == 0) ? '' : ',') + '"' + StringUtils.URIEncode(value.id) + '"';
          }
        }
        if (filterLimits.length > 0) {
          this.parameterNames.push(filter.filterId);
          this.parameterValues.push(filterLimits);
        }
      }
    }

    // if (this.resultTypes &&
    //   (
    //     (this.entityType == 'publication' || this.entityType == 'dataset' || this.entityType == 'software' || this.entityType == 'other' || this.entityType == "result")
    //     ||
    //     (this.entityType == "service")
    //   )
    // ) {
    //   let values = [];
    //   for (let value of this.resultTypes.values) {
    //     if (value.selected) {
    //       values.push(value.id);
    //     }
    //   }
    //   this.selectedTypesNum = 0;
    //   if (values.length > 0 && values.length != 4) {
    //     this.parameterNames.push("type");
    //     this.parameterValues.push(values.join(","));
    //     this.selectedTypesNum = values.length;
    //   }
    //   //
    //   /*      if(this.quickFilter) {
    //           this.parameterNames.push("qf");
    //           this.parameterValues.push("" + this.quickFilter.selected);
    //         }*/
    // }
    for (let filter of filters) {
      var filterLimits = "";
      if (filter.countSelectedValues > 0) {
        for (let value of filter.values) {
          if (value.selected == true) {
            filterLimits += ((filterLimits.length == 0) ? '' : ',') + '"' + StringUtils.URIEncode(value.id) + '"';
          }
        }
        if (filterLimits.length > 0) {
          this.parameterNames.push(filter.filterId);
          this.parameterValues.push(filterLimits);
        }
      }
    }
    for (let filter of rangeFilters) {
      var filterLimits = "";
      let yearFrom: string = (Dates.isValidYear(filter.selectedFromValue) ? filter.selectedFromValue : null);
      let yearTo: string = (Dates.isValidYear(filter.selectedToValue) ? filter.selectedToValue : null);
      if (yearFrom || yearTo) {
        this.parameterNames.push(filter.filterId);
        this.parameterValues.push("range" + (yearFrom ? yearFrom : "") + ":" + (yearTo ? yearTo : ""));
      }
      // if (filter.countSelectedValues > 0) {
      //   for (let value of filter.values) {
      //     if (value.selected == true) {
      //       filterLimits += ((filterLimits.length == 0) ? '' : ',') + '"' + (value.id) + '"';
      //     }
      //   }
      //   if (filterLimits.length > 0) {
      //     this.parameterNames.push(filter.filterId);
      //     this.parameterValues.push(filterLimits);
      //   }
      // }
    }
    if (this.searchUtils.keyword.length > 0) {
      this.parameterNames.push("keyword");
      this.parameterValues.push(this.searchUtils.keyword);
    }

    // if (this.searchUtils.size != this.resultsPerPage) {
    //   // allLimits += ((allLimits.length == 0) ? '?' : '&') + 'size=' + this.searchUtils.size;
    //   this.parameterNames.push("size");
    //   this.parameterValues.push("" + this.searchUtils.size);
    // }
    // if (this.sort && this.searchUtils.sortBy) {
    //   // allLimits += ((allLimits.length == 0) ? '?' : '&') + 'sortBy=' + this.searchUtils.sortBy;
    //   this.parameterNames.push("sortBy");
    //   this.parameterValues.push(this.searchUtils.sortBy);
    // }
    // console.log(this.parameterNames)
    // console.log(this.parameterValues)
  }
  
  /**
   * create filters based on URL params
   * @param URLparams
   */
  getRefineFiltersFromURL(URLparams) {
    let fields = new SearchFields();
    let filters: Filter[] = [];
    let staticFilters: Filter[] = [];
    for (let i = 0; i < this.refineFields.length; i++) {
      let filterId = this.refineFields[i];
      if (URLparams[filterId] != undefined) {
        let filter = new Filter();
        filter.title = fields.getFieldName(filterId, this.entityType);
        filter.filterId = filterId;
        filter.originalFilterId = filterId;
        filter.values = [];
        let values = StringUtils.URIDecode(URLparams[filterId]).split(/,(?=(?:[^\"]*\"[^\"]*\")*[^\"]*$)/, -1);
        for (let value of values) {
          
          let v: Value = new Value();
          v.name = RefineResultsUtils.keepPartAfterCharacters(StringUtils.unquote(value), "||");
          v.name = (v.name.indexOf("::") != -1) ? v.name.substring(v.name.indexOf("::") + 2).split("::").join("|") : v.name; // for funding streams
          v.id = StringUtils.unquote(value);
          v.selected = true;
          filter.values.push(v);
          // console.log(v)
          filter.countSelectedValues++;
        }
        filters.push(filter)
      }
    }
    
    /*    if (this.quickFilter) {
          if (this.entityType == "result" && (URLparams[this.quickFilter.filterId] == undefined) && (URLparams["qf"] == undefined || URLparams["qf"] == "true")) {
            let filter = new Filter();
            filter.title = fields.getFieldName(this.quickFilter.filterId, this.entityType);
            filter.filterId = this.quickFilter.filterId;
            filter.originalFilterId = this.quickFilter.filterId;
            filter.values = [];
            let v: Value = new Value();
            v.name = this.quickFilter.value;
            v.id = this.quickFilter.value;
            v.selected = true;
            filter.values.push(v);
            filter.countSelectedValues = 1;
            filters.push(filter)
          }
        }*/

    for (let i = 0; i < this.staticFields.length; i++) {
      let filterId = this.staticFields[i];
      if (URLparams[filterId] != undefined) {
        let filter = new Filter();
        filter.title = fields.getFieldName(filterId, this.entityType);
        filter.filterId = filterId;
        filter.originalFilterId = filterId;
        filter.values = [];
        let values = StringUtils.URIDecode(URLparams[filterId]).split(/,(?=(?:[^\"]*\"[^\"]*\")*[^\"]*$)/, -1);
        for (let value of values) {
          let v: Value = new Value();
          v.name = RefineResultsUtils.keepPartAfterCharacters(StringUtils.unquote(value), "||");
          v.name = (v.name.indexOf("::") != -1) ? v.name.substring(v.name.indexOf("::") + 2).split("::").join("|") : v.name; // for funding streams
          v.id = StringUtils.unquote(value);
          v.selected = true;
          filter.values.push(v);
          filter.countSelectedValues++;
        }
        staticFilters.push(filter)
      }
    }

    // let options = null;
    // if ((this.entityType == 'publication' || this.entityType == 'dataset' || this.entityType == 'software' || this.entityType == 'other' || this.entityType == "result")) {
    //   options = this.resultTypeOptions;
    // } else if (this.entityType == "service") {
    //   options = this.serviceTypeOptions;
    // }
    // if (options) {
    //   this.resultTypes = {values:[],filterId:"type", countSelectedValues: 0, filterType: 'checkbox', type:'checkBox', originalFilterId: "", valueIsExact: true, title: "Type",filterOperator:"or"};
    //   for (let typeOption of Object.keys(options)) {
    //     let type = typeOption;
    //     if ( URLparams["type"] &&  URLparams["type"].indexOf(type)==-1 || !URLparams["type"]) {
    //       this.resultTypes.values.push({
    //         name: options[StringUtils.unquote(type)].name,
    //         id: StringUtils.unquote(type),
    //         selected: false,
    //         number: 0
    //       });
    //     }else{
    //       this.resultTypes.values.push({
    //         name: options[StringUtils.unquote(type)].name,
    //         id: StringUtils.unquote(type),
    //         selected: true,
    //         number: 0
    //       });
    //       this.resultTypes.countSelectedValues++;
    //     }
    //   }
    // }

    this.URLCreatedFilters = filters;
    this.URLCreatedStaticFilters = staticFilters;
  }
  
  /**
   * create range filters based on URL params
   * @param URLparams
   */
  getRangeFiltersFromURL(URLparams) {
    let fields = new SearchFields();
    let filters: RangeFilter[] = [];
    for (let i = 0; i < this.rangeFields.length; i++) {
      let filterId = this.rangeFields[i][0] + "-range-" + this.rangeFields[i][1];
      let filterParam = fields.getFieldParam(filterId, this.entityType);
      //console.log("rangeFilter (from url): filterId - filterParam");
      //console.log(filterId + " - "+ filterParam);
      if (URLparams[filterParam] != undefined) {
        let filter = new RangeFilter();
        filter.title = fields.getFieldName(filterId, this.entityType);
        filter.filterId = filterParam;
        filter.originalFilterIdFrom = this.rangeFields[i][0];
        filter.originalFilterIdTo = this.rangeFields[i][1];
        
        
        let values = (decodeURIComponent(URLparams[filterParam])).split(/,(?=(?:[^\"]*\"[^\"]*\")*[^\"]*$)/, -1);
        for (let j = 0; j < values.length; j++) {
          if (this.fieldIdsMap[filterId].filterType == "range") {
            let value: string = StringUtils.unquote(values[j]);
            let validDates: boolean = true;
            // if (value.length < 14) {
            //   validDates = false;
            // } else {
            //   if (!Dates.isValidYear(value.substring(5, 9)) || !Dates.isValidYear(value.substring(10, 14))) {
            //     validDates = false;
            //   } else {
            //     filter.selectedFromValue = value.substring(5, 9);
            //     filter.selectedToValue = value.substring(10, 14);
            //   }
            // }
            let years: string[] = (value.substring(5)).split(":");
            let yearFrom: string = (Dates.isValidYear(years[0]) ? years[0] : null);
            let yearTo: string = (Dates.isValidYear(years[1]) ? years[1] : null);
            //console.log("getRangeFiltersFromURL: yearFrom: " + yearFrom + " - yearTo: "+yearTo);
            if (yearFrom) {
              filter.selectedFromValue = yearFrom;
              //filter.selectedFromAndToValues = yearFrom;
            }
            /*if(yearFrom && yearTo) {
              filter.selectedFromAndToValues += "-";
            }*/
            if (yearTo) {
              filter.selectedToValue = yearTo;
              //filter.selectedFromAndToValues += yearTo;
            }
            //console.log("filter.selectedFromAndToValues: "+filter.selectedFromAndToValues);
            if (!yearFrom && !yearTo) {
              validDates = false;
            }
            
          }
        }
        //console.log(filters);
        filters.push(filter)
      }
    }
    // console.log("Empty Filters");
    // console.log(filters);
    this.URLCreatedRangeFilters = filters;
    // return filters;
    
  }
  
  /**
   * Checks if query has no results, display Filters from URL parameters
   * Mark checked  the selected filters
   * Count the checked
   * @param filters
   */
  public prepareFiltersToShow(filters: Filter[], totalResults): Filter[] {
    if (this.URLCreatedFilters.length > 0 && totalResults == 0) {
      this.showUnknownFilters = true;
      this.filters = this.URLCreatedFilters;
    } else if (totalResults != 0) {
      this.showUnknownFilters = false;
      this.filters = filters;
    } else if ((this.URLCreatedFilters.length == 0 && totalResults == 0)) {
      this.showUnknownFilters = true;
      this.filters = filters;
    }
    
    this.buildPageURLParameters(this.URLCreatedFilters, this.URLCreatedRangeFilters, this.URLCreatedStaticFilters, true);
    //this.checkSelectedRangeFilters(this.rangeFilters);
    
    this.checkSelectedFilters(this.filters);
    this.countSelectedFilters(this.filters);
    this.updateMeta(this.pageTitle);
    this.cdr.detectChanges();
    return this.filters;
  }
  
  /**
   * Mark checked  the selected range filters
   */
  public prepareRangeFiltersToShow() {
    this.rangeFilters = RangeFilter.parse(this.rangeFields, this.entityType); // OK
    
    //this.buildPageURLRangeParameters(this.rangeFilters, true);
    this.checkSelectedRangeFilters(this.rangeFilters);
    this.countSelectedRangeFilters(this.rangeFilters);
    return this.rangeFilters;
  }

  public prepareStaticFiltersToShow() {
    var selected_filters: Map<string, string[]> = this.getSelectedFilters();
    if (selected_filters.size == 0) {
      selected_filters = this.getSelectedParameters();
    }

    var selected_static_filters: Map<string, string[]> = this.getSelectedStaticFilters();
    if (selected_static_filters.size == 0) {
      selected_static_filters = this.getSelectedStaticParameters();
    }

    let all_selected_filters = new Map([...selected_filters, ...selected_static_filters]);
    // let all_selected_filters = selected_filters.concat(selected_static_filters);

    let staticFields: string[] = [];

    for (var i = 0; i < this.staticFields.length; i++) {
      var dependentTo = this.searchFieldsHelper.DEPENDENT_FIELDS[this.staticFields[i]];
      var dependentToValues = this.searchFieldsHelper.DEPENDENT_FIELDS_AND_VALUES[this.staticFields[i]];

      // TODO check again the checks
      //if filter is not marked as hidden OR it is hidden but it is dependent to a field that it IS selected
      if (this.searchFieldsHelper.HIDDEN_FIELDS.indexOf(this.staticFields[i]) == -1
        || (all_selected_filters.has(this.staticFields[i]))
        || (!dependentTo && !dependentToValues)
        || (all_selected_filters.has(dependentTo))
        || (dependentToValues && (all_selected_filters.has(dependentToValues.field) && dependentToValues.values.some(dependentValue=> all_selected_filters.get(dependentToValues.field).includes(dependentValue))))
      ) {
        staticFields.push(this.staticFields[i]);
      }
    }

    this.staticFilters = RefineResultsUtils.parse(this.staticFieldValues, staticFields, this.entityType, "search", true);
    this.checkSelectedStaticFilters(this.staticFilters);
    this.countSelectedStaticFilters(this.staticFilters);
    this.cdr.detectChanges();

    return this.staticFilters;
  }

  /**
   * Used to set the variables and search page, and prepare it before the getResults query
   * @param fieldIds
   * @param selectedFields
   * @param refineFields
   * @param rangeFields
   * @param fieldIdsMap
   * @param customFilter
   * @param params
   * @param entityType
   * @param quickFilter
   */
  prepareSearchPage(fieldIds, selectedFields, refineFields, rangeFields, staticFields, fieldIdsMap, customFilter, params, entityType, quickFilter = null) {
    // console.log(this.refineFields);
    this.entityType = entityType;
    this.fieldIds = fieldIds;
    this.selectedFields = selectedFields;
    this.refineFields = refineFields;
    this.rangeFields = rangeFields;
    this.staticFields = staticFields;
    this.fieldIdsMap = fieldIdsMap;
    this.customFilter = customFilter;
    this.quickFilter = quickFilter;
    this.getRangeFiltersFromURL(params);
    this.getRefineFiltersFromURL(params);
    // this.cdr.detectChanges();
    this.createAdvancedSearchSelectedFiltersFromURLParameters(params);
    this.searchTerm = '';
    if(params && params['fv0'] && params['f0'] && params['f0'] == 'q'){
      let keyword = StringUtils.URIDecode(params['fv0']);
      this.searchTerm = keyword;
    }
    if(params){
      this.advancedSearchTerms = Object.keys(params).filter(key => key.includes('fv')).length;
    }
  }

  removeResultType(type) {
    for (let value of this.resultTypes.values) {
      if (type == value.id && value.selected) {
        value.selected = false;
        this.goTo(1);
        break;
      }
    }
  }
  
  totalPages(totalResults: number): number {
    let totalPages: any = totalResults / (this.searchUtils.size);
    if (!(Number.isInteger(totalPages))) {
      totalPages = (parseInt(totalPages, 10) + 1);
    }
    return totalPages;
  }

  public getFilterById(filterId: string): Filter {
    return this.filters.find(filter => filter.filterId == filterId);
  }

  detectChanges() {
    this.cdr.detectChanges();
  }
 }
