import {Component, OnInit} from '@angular/core';
import {Identifier, StringUtils} from "../../openaireLibrary/utils/string-utils.class";
import {EnvProperties} from "../../openaireLibrary/utils/properties/env-properties";
import {ErrorCodes} from "../../openaireLibrary/utils/properties/errorCodes";
import {SearchOrcidService} from "../../openaireLibrary/claims/claim-utils/service/searchOrcid.service";
import {SearchResearchResultsService} from "../../openaireLibrary/services/searchResearchResults.service";
import {forkJoin, Subscriber} from "rxjs";
import {properties} from "../../../environments/environment";
import {BaseComponent} from "../../openaireLibrary/sharedComponents/base/base.component";
import {ActivatedRoute, Router} from "@angular/router";
import {SEOService} from "../../openaireLibrary/sharedComponents/SEO/SEO.service";
import {PiwikService} from "../../openaireLibrary/utils/piwik/piwik.service";
import {Meta, Title} from "@angular/platform-browser";
import {map} from "rxjs/operators";
import {OpenaireEntities} from "../../openaireLibrary/utils/properties/searchFields";

@Component({
  selector: 'search-researcher',
  templateUrl: './search-researcher.component.html',
})
export class SearchResearcherComponent  extends BaseComponent implements OnInit  {
  openaireEntities = OpenaireEntities;
  page: number = 1;
  size: number = 10;
  public keyword: string = "";//"paolo manghi";//'0000-0001-7291-3210';
  properties: EnvProperties = properties;
  public errorCodes: ErrorCodes = new ErrorCodes();
  public warningMessage = "";
  public infoMessage = "";
  orcidStatus: number = null;
  authors = [];
  authorsToShow = [];
  authorsRendered = 0;
  subscriptions = [];
  constructor(private _searchOrcidService: SearchOrcidService,
              private _searchResearchResultsService: SearchResearchResultsService,
  protected _router: Router,
  protected _route: ActivatedRoute,

  protected seoService: SEOService,
  protected _piwikService: PiwikService,
  protected _title: Title,
  protected _meta: Meta) {
  super();
}
  ngOnInit() {
    this.title = 'Researcher Monitors';
    this.description = 'Researcher Monitors';
    this.setMetadata();
    this.subscriptions.push(this._route.queryParams.subscribe(params => {
        this.keyword = params['keyword']? decodeURIComponent( params['keyword']):"";
        this.search();
    }));
  }

  ngOnDestroy() {
    this.subscriptions.forEach(subscription => {
      if (subscription instanceof Subscriber) {
        subscription.unsubscribe();
      }
    });
  }

  checkForReset() {
    if(this.keyword == ""){
      this.searchByKeyword()
    }
  }
  searchByKeyword(){
    this._router.navigate(['/researcher'], {queryParams: {keyword:encodeURIComponent(this.keyword)}});
  }
  search() {
    //uncomment to disable search with no keyword
    this.warningMessage = "";
    this.infoMessage = "";
    this.authors = [];
    this.authorsToShow = [];
    this.page = 1;
    this.authorsRendered = 0;
    if (this.keyword.length == 0) {
      this.orcidStatus = null;
      return;
    }
    this.orcidStatus = this.errorCodes.LOADING;
    if(!Identifier.isValidORCID(this.keyword) && Identifier.isValidORCID(this.keyword.replace("x","X"))){
      this.keyword = this.keyword.replace("x","X")
    }
    if(Identifier.isValidORCID(this.keyword)){
      this.getOrcidAuthor(this.keyword.indexOf(properties.orcidURL)!=-1?this.keyword.split(properties.orcidURL)[1]:this.keyword, true, -1);
    }else{
      this.getOrcidAuthors(this.keyword)
    }


  }


  private getOrcidAuthor(term: string, addId, count = -1) {
    //passing structures in order to fill them in service
    this.subscriptions.push(this._searchOrcidService.searchOrcidSingleAuthor(StringUtils.URIEncode(term.replace(/\s/g, "")), this.properties, addId).subscribe(
      data => {
        if (data != null) {
          this.orcidStatus = this.errorCodes.LOADING;
          this.authors.push(data);
          if(count ==-1) {
            this.getOpenaireResultsFor(0,1);
          }else{
            data.resultsCount = count;
            this.authorsToShow.push(data);
          }
        }else{
          this.orcidStatus = this.errorCodes.NONE;
        }

      },
      err => this.errorHandler(err, term)
    ));
  }

  private errorHandler(err: any, term: string) {
    if (err.status == 404) {
      this.getOrcidAuthors(term);
    } else {
      this.orcidStatus = this.errorCodes.ERROR;
      //console.log(err.status);
    }
  }

  private getOrcidAuthors(term: string) {
    this.orcidStatus = this.errorCodes.LOADING;
    this.subscriptions.push(this._searchOrcidService.searchOrcidAuthorsNew(StringUtils.URIEncode(term), this.properties, 100).subscribe(
      data => {
        this.authors = data;
        if (data != null) {
          this.getOpenaireResultsFor(0,this.size);
          this.authorsRendered = this.size;
          if (this.authors.length == 0) {
            this.orcidStatus = this.errorCodes.NONE;
          }
        } else {
          this.orcidStatus = this.errorCodes.ERROR;
        }

      },
      err => {
        this.orcidStatus = this.errorCodes.ERROR;
        //console.log(err.status);
      }
    ));
  }

private getOpenaireResultsFor(start, end){
    let obs = [];
    for (let i = start; i < (this.authors.length>end?end:this.authors.length); i++) {
      obs.push(this.getOpenaireResultsObs(this.authors[i]));
    }
    if(obs.length > 0) {
      this.subscriptions.push(forkJoin(obs).subscribe(data => {
        for (let author of data) {
          if (author["resultsCount"] > 0) {
            this.authorsToShow.push(author);
          }
        }
        this.authorsRendered = (this.authors.length > end ? end : this.authors.length)

        if (this.authorsToShow.length < this.page * this.size) {
          this.getOpenaireResultsFor(end, end + (this.size));
        }else{
          this.orcidStatus = this.errorCodes.DONE;
        }
      }));
    }else{
      this.orcidStatus = this.errorCodes.DONE;
      if(this.authorsToShow.length == 0){
        this.orcidStatus = this.errorCodes.NONE;
      }

    }
}
  private getOpenaireResultsObs(author){
    let param =  '(authorid="' + StringUtils.URIEncode(author.id) + '")'
    +' and (country exact "IE")';
    return this._searchResearchResultsService.numOfResearchOutcomes(param, properties, null).pipe(map(res => {
      author.resultsCount = res;
      return author;
    }));

  }

  loadMore(){
    this.orcidStatus = this.errorCodes.LOADING;
    let page = this.page + 1;
    if(page*this.size>this.authorsToShow.length) {
      if (this.authorsRendered < this.authors.length) {
          this.getOpenaireResultsFor(this.authorsRendered, this.authorsRendered + this.size*2);
      }
    }
    this.page = page;
  }

}
