import {ChangeDetectorRef, Component, OnInit} from '@angular/core';
import {Router} from '@angular/router';
import {Subscriber, Subscription, zip} from "rxjs";
import {Meta, Title} from "@angular/platform-browser";

import {EnvProperties} from "../openaireLibrary/utils/properties/env-properties";
import {PiwikService} from "../openaireLibrary/utils/piwik/piwik.service";
import {SEOService} from "../openaireLibrary/sharedComponents/SEO/SEO.service";
import {Breadcrumb} from "../openaireLibrary/utils/breadcrumbs/breadcrumbs.component";
import {properties} from "../../environments/environment";
import {RefineFieldResultsService} from '../openaireLibrary/services/refineFieldResults.service';
import {StakeholderService} from '../openaireLibrary/monitor/services/stakeholder.service';
import {Option} from '../openaireLibrary/sharedComponents/input/input.component';
import {StringUtils} from '../openaireLibrary/utils/string-utils.class';
import {HelperFunctions} from '../openaireLibrary/utils/HelperFunctions.class';
import {NumberUtils} from '../openaireLibrary/utils/number-utils.class';
import {LayoutService} from '../openaireLibrary/dashboard/sharedComponents/sidebar/layout.service';
import {FormBuilder, FormControl} from '@angular/forms';
import {debounceTime, distinctUntilChanged} from 'rxjs/operators';
import {GroupedRequestsService} from "../openaireLibrary/services/groupedRequests.service";

@Component({
	selector: 'funders',
	templateUrl: './funders.component.html',
  styleUrls: ['funders.component.less']
})

export class FundersComponent implements OnInit {
	private subscriptions: Subscription[] = [];
	url: string = null;
	pageTitle: string = "OpenAIRE - Explore | Funders";
	pageDescription: string = "Funders | Be an integral part of the open R&I ecosystem";
	properties: EnvProperties = properties;
  breadcrumbs: Breadcrumb[] = [{name: 'home', route: '/'}, {name: 'funders'}];
  showLoading: boolean = true;
  isMobile: boolean = false;
  funders: any[] = [];
  displayedFunders: any[] = [];
  showOptions: Option[];
  sortOptions: Option[];
  pageOptions: number[] = [10, 20, 30, 40];
  show: string = 'all';
  sortBy: string = 'alphAsc';
  gridView: boolean = true;
  currentPage: number = 1;
  pageSize: number = 10;
  keywordControl: FormControl;
  keyword: string;
  fundersNumber: number = 0;
  researchProductsNumber: number = 0;
  projectsNumber: number = 0;
  fundersMap = new Map<string, {
                              "id": string,
                              "name": string,
                              "alias": string, 
                              "researchProducts": number, 
                              "openAccessResearchProducts": number, 
                              "openAccessPercentage": number,
                              "projects": number, 
                              "monitorDashboard": string, 
                              "monitorDashboardStatus": string, 
                              "logoUrl": string
                            }>();
  staticLogos: Set<string> = new Set<string>([
    "arc_________::ARC||Australian Research Council (ARC)||ARC",
    "asap________::ASAP||Aligning Science Across Parkinson's||ASAP",
    "cihr________::CIHR||Canadian Institutes of Health Research||CIHR",
    "euenvagency_::EEA||European Environment Agency||EEA",
    "inca________::INCA||Institut National du Cancer||INCa",
    "nhmrc_______::NHMRC||National Health and Medical Research Council (NHMRC)||NHMRC",
    "nih_________::NIH||National Institutes of Health||NIH",
    "nserc_______::NSERC||Natural Sciences and Engineering Research Council of Canada||NSERC",
    "nsf_________::NSF||National Science Foundation||NSF",
    "sshrc_______::SSHRC||Social Sciences and Humanities Research Council||SSHRC",
    "taraexp_____::tara||Tara Expeditions Foundation||TARA",
    "ukri________::UKRI||UK Research and Innovation||UKRI",
    "wt__________::WT||Wellcome Trust||WT"
  ]);

	constructor(private router: Router,
							private meta: Meta,
							private title: Title,
							private seoService: SEOService,
							private piwikService: PiwikService,
              private refineFieldResultsService: RefineFieldResultsService,
              private stakeholderService: StakeholderService,
              private layoutService: LayoutService,
              private cdr: ChangeDetectorRef,
              private fb: FormBuilder,
              private groupedRequestsService: GroupedRequestsService) {
	}

	ngOnInit() {
    this.layoutService.setRootClass('funders');
		this.title.setTitle('OpenAIRE - Explore | Funders');
		this.properties = properties;
    this.subscriptions.push( this.piwikService.trackView(this.properties, this.pageTitle).subscribe());
		this.url = this.properties.domain + this.router.url;
		this.seoService.createLinkForCanonicalURL(this.url);
		this.updateUrl(this.url);
		this.updateTitle(this.pageTitle);
		this.updateDescription(this.pageDescription);
    this.subscriptions.push(this.layoutService.isMobile.subscribe(isMobile => {
      this.isMobile = isMobile;
      this.cdr.detectChanges();
    }));
    this.showOptions = [
      {value: 'all', label: 'All funders'},
      {value: 'dashboard', label: 'Funders with dashboard'}
    ];
    this.sortOptions = [
      {value: 'alphAsc', label: 'Alphabetically Asc. (A-Z)'},
      {value: 'alphDsc', label: 'Alphabetically Dsc. (Z-A)'},
      {value: 'oaDsc', label: '"Open Access %" Dsc.'}
    ];
    this.getFunders();
    this.keywordControl = this.fb.control('');
    this.subscriptions.push(this.keywordControl.valueChanges.pipe(debounceTime(500), distinctUntilChanged()).subscribe(value => {
      this.keyword = value;
      this.filtering();
    }));
	}

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

	private updateDescription(description: string) {
		this.meta.updateTag({content: description}, "name='description'");
		this.meta.updateTag({content: description}, "property='og:description'");
	}

	private updateTitle(title: string) {
		var title = ((title.length > 50) ? title.substring(0, 50) : title);
		this.title.setTitle(title);
		this.meta.updateTag({content: title}, "property='og:title'");
	}

	private updateUrl(url: string) {
		this.meta.updateTag({content: url}, "property='og:url'");
	}

  private getFunders() {
    this.subscriptions.push(this.groupedRequestsService.funders().subscribe(data => {
      let funders = data["funders"];
      funders.forEach(queriedFunder => {
        let id = queriedFunder.id;
        let funder = {
          "id": id,
          "name": this.removePartAfterCharacters(queriedFunder.name, "||"),
          "alias": '',
          "researchProducts": +queriedFunder.results,
          "openAccessResearchProducts": +queriedFunder.openResults,
          "openAccessPercentage": 0,
          "projects": +queriedFunder.projects,
          "monitorDashboard": '',
          "monitorDashboardStatus": '',
          "logoUrl": ''
        };

        if((!funder.researchProducts || funder.researchProducts == 0) && (!funder.projects || funder.projects == 0)) {
          return;
        }

        if(queriedFunder.stakeholder) {
          let stakeholder = queriedFunder.stakeholder;
          funder.alias = stakeholder.alias;
          funder.monitorDashboard = stakeholder.alias;
          funder.monitorDashboardStatus = stakeholder.visibility;
          funder.logoUrl = (stakeholder.isUpload ? properties.utilsService + "/download/" : "")+ (stakeholder.logoUrl);
        }

        if(funder.openAccessResearchProducts && funder.researchProducts) {
          funder.openAccessPercentage = Math.round((funder.openAccessResearchProducts / funder.researchProducts) * 100);
        }

        if(!funder.logoUrl && this.staticLogos.has(funder.id)) {
          let split = funder.id.split("||");
          let shortname = (split && split.length==3) ? funder.id.split("||")[2] : funder.id;
          funder.logoUrl = "assets/explore-assets/funders/logos/"+shortname+".webp";
        }

        this.fundersMap.set(queriedFunder.id, funder);
      });
      // convert funders map into an array
      this.funders = Array.from(this.fundersMap.values());
      // calculate total numbers for intro content
      this.fundersNumber = data.count;
      this.researchProductsNumber = data.results;
      this.projectsNumber = data.projects;
      // sort funders
      this.funders.sort((a, b) => a['name'].localeCompare(b['name']));
      // initialize displayedFunders
      this.displayedFunders = this.funders;
      this.showLoading = false;
    }))

    // let refineParams = '&fq=resultbestaccessright%20exact%20%22Open%20Access%22';
    // this.subscriptions.push(
    //   zip(
    //     this.refineFieldResultsService.getAllRefineFieldResultsByFieldName('relfunder', 'result', this.properties),
    //     this.refineFieldResultsService.getAllRefineFieldResultsByFieldName('relfunder', 'result', this.properties, refineParams),
    //     this.refineFieldResultsService.getAllRefineFieldResultsByFieldName('funder', 'project', this.properties),
    //     this.stakeholderService.getStakeholders(this.properties.monitorServiceAPIURL, 'funder')
    //   ).subscribe((data: any[]) => {
    //     // storing all needed data to a map
    //     // 1st call
    //     let queriedFunders1 = data[0][1][0].values;
    //     queriedFunders1.forEach(queriedFunder => {
    //       this.fundersMap.set(queriedFunder.id, {
    //         "id": queriedFunder.id,
    //         "name": queriedFunder.name,
    //         "alias": '',
    //         "researchProducts": +queriedFunder.number,
    //         "openAccessResearchProducts": 0,
    //         "openAccessPercentage": 0,
    //         "projects": 0,
    //         "monitorDashboard": '',
    //         "monitorDashboardStatus": '',
    //         "logoUrl": ''
    //       });
    //     });
    //
    //     // 2nd call
    //     let queriedFunders2 = data[1][1][0].values;
    //     queriedFunders2.forEach(queriedFunder => {
    //       if(this.fundersMap.has(queriedFunder.id)) {
    //         this.fundersMap.get(queriedFunder.id).openAccessResearchProducts = +queriedFunder.number;
    //       }
    //     });
    //
    //     // 3rd call
    //     let queriedFunders3 = data[2][1][0].values;
    //     queriedFunders3.forEach(queriedFunder => {
    //       if(+queriedFunder.number > 1) {
    //         if (this.fundersMap.has(queriedFunder.id)) {
    //           this.fundersMap.get(queriedFunder.id).projects = +queriedFunder.number;
    //         } else {
    //           this.fundersMap.set(queriedFunder.id, {
    //             "id": queriedFunder.id,
    //             "name": queriedFunder.name,
    //             "alias": '',
    //             "researchProducts": 0,
    //             "openAccessResearchProducts": 0,
    //             "openAccessPercentage": 0,
    //             "projects": +queriedFunder.number,
    //             "monitorDashboard": '',
    //             "monitorDashboardStatus": '',
    //             "logoUrl": ''
    //           });
    //         }
    //       }
    //     });
    //
    //     // 4th call
    //     let queriedFunders4 = data[3];
    //     queriedFunders4.forEach(queriedFunder => {
    //       let id = queriedFunder.index_id + '||' + queriedFunder.index_name + '||' + queriedFunder.index_shortName;
    //       if(this.fundersMap.has(id) && (
    //         !this.fundersMap.get(id).monitorDashboardStatus
    //         ||
    //         (this.fundersMap.get(id).monitorDashboardStatus == "RESTRICTED" && queriedFunder.visibility == "PUBLIC")
    //         ||
    //         (this.fundersMap.get(id).monitorDashboardStatus == "PRIVATE" && (queriedFunder.visibility == "RESTRICTED" || queriedFunder.visibility == "PUBLIC")))) {
    //         this.fundersMap.get(id).alias = queriedFunder.alias;
    //         this.fundersMap.get(id).monitorDashboard = queriedFunder.alias;
    //         this.fundersMap.get(id).monitorDashboardStatus = queriedFunder.visibility;
    //         this.fundersMap.get(id).logoUrl = (queriedFunder.isUpload ? properties.utilsService + "/download/" : "")+ (queriedFunder.logoUrl);
    //       }
    //     });
    //     this.fundersMap.forEach((value) => {
    //       if(value.openAccessResearchProducts > 0) {
    //         value.openAccessPercentage = Math.round((value.openAccessResearchProducts / value.researchProducts) * 100);
    //       }
    //       if(!value.logoUrl && this.staticLogos.has(value.id)) {
    //         let split = value.id.split("||");
    //         let shortname = (split && split.length==3) ? value.id.split("||")[2] : value.id;
    //         value.logoUrl = "assets/explore-assets/funders/logos/"+shortname+".png";
    //       }
    //     });
    //     // convert funders map into an array
    //     this.funders = Array.from(this.fundersMap.values());
    //     // calculate total numbers for intro content
    //     this.calculateNumbers();
    //     // sort funders
    //     this.funders.sort((a, b) => a['name'].localeCompare(b['name']));
    //     // initialize displayedFunders
    //     this.displayedFunders = this.funders;
    //     console.log(this.funders);
    //     this.showLoading = false;
    //   })
    // );
  }

  private calculateSum(array, property) {
    let sum = 0;
    array.forEach(element => {
      sum += element[property];
    });
    return sum;
  }

  private calculateNumbers() {
    this.fundersNumber = this.funders.length;
    this.researchProductsNumber = this.calculateSum(this.funders, 'researchProducts');
    this.projectsNumber = this.calculateSum(this.funders, 'projects');
  }

  get showContentWithNumbers() {
    return this.fundersNumber && this.researchProductsNumber && this.projectsNumber;
  }

  formatNumber(num: number | string) {
    let formatted = NumberUtils.roundNumber(+num);
    return formatted.number + formatted.size;
  }

  urlEncodeAndQuote(str: string): string {
    return StringUtils.quote(StringUtils.URIEncode(str));
  }

  sortByChanged() {
    switch(this.sortBy) {
      case 'alphAsc':
        this.funders = this.funders.sort((a, b) => a['name'].localeCompare(b['name']));
        break;
      case 'alphDsc':
        this.funders = this.funders.sort((a, b) => b['name'].localeCompare(a['name']));
        break;
      case 'oaDsc':
        this.funders = this.funders.sort((a, b) => b['openAccessPercentage'] - a['openAccessPercentage']);
        break;
    }
    this.filtering();
  }

  sizeChanged($event) {
    this.pageSize = $event;
    this.currentPage = 1;
  }

  filtering() {
    let displayedFunders = this.funders;
    if(!this.keyword){
      this.keyword = '';
    }
		if(this.funders.length) {
			displayedFunders = displayedFunders.filter(item => (item['name'] && item['name'].toLowerCase().includes(this.keyword.toLowerCase())) || (item['alias'] && item['alias'].toLowerCase().includes(this.keyword.toLowerCase())));
		}
    if(this.show == 'dashboard') {
      displayedFunders = displayedFunders.filter(funder => funder.monitorDashboard && funder.monitorDashboard?.length > 0 && funder.monitorDashboardStatus != 'PRIVATE');
    }
    
    this.displayedFunders = displayedFunders;
    this.currentPage = 1;
  }

  public updateCurrentPage($event) {
    this.currentPage = $event.value;
    HelperFunctions.scrollToId('target');
  }

  private removePartAfterCharacters(field, characters):string {
    if(field && field.indexOf(characters) !=-1){
      return field.split(characters)[0];

    }
    return field;
  }
}
