import {Component} from '@angular/core';
import {EnvProperties} from '../openaireLibrary/utils/properties/env-properties';
import {ActivatedRoute, Router} from "@angular/router";
import {CommunityService} from "../openaireLibrary/connect/community/community.service";
import {HelperService} from "../openaireLibrary/utils/helper/helper.service";
import {Meta, Title} from "@angular/platform-browser";
import {SEOService} from "../openaireLibrary/sharedComponents/SEO/SEO.service";
import {PiwikService} from "../openaireLibrary/utils/piwik/piwik.service";
import {StringUtils} from "../openaireLibrary/utils/string-utils.class";
import {Breadcrumb} from "../openaireLibrary/utils/breadcrumbs/breadcrumbs.component";
import {properties} from "../../environments/environment";
import {Subscriber, Subscription} from "rxjs";

@Component({
  selector: 'subjects',
  template: `
    <schema2jsonld *ngIf="url" [URL]="url" [name]="pageTitle" type="other"></schema2jsonld>
    <div style="min-height: 650px;">
      <div class="uk-container uk-container-large uk-section uk-section-small uk-padding-remove-bottom">
        <div class="uk-padding-small uk-padding-remove-horizontal">
          <breadcrumbs [breadcrumbs]="breadcrumbs"></breadcrumbs>
        </div>
      </div>
      <div class="uk-container uk-container-large uk-section uk-section-small">
        <div *ngIf="showLoading" class="uk-margin-large">
          <div class="uk-animation-fade uk-margin-top uk-width-1-1" role="alert">
            <span class="loading-gif uk-align-center"></span>
          </div>
        </div>
        <div *ngIf="!showLoading">
          <h1 class="uk-margin-top">
            Subjects
          </h1>
          <div *ngIf="pageContents && pageContents['top'] && pageContents['top'].length > 0">
            <helper *ngIf="pageContents && pageContents['top'] && pageContents['top'].length > 0"
              [texts]="pageContents['top']">
            </helper>
          </div>
          <div class="uk-margin-large-top" *ngIf="displayedSubjects?.length == 0 && displayedSdg?.length == 0 && displayedFos?.length == 0"
            class="uk-card uk-card-default uk-padding-large uk-text-center uk-margin-bottom uk-text-bold">
            <div>No subjects</div>
          </div>
          <div class="uk-margin-large-top" *ngIf="displayedSubjects?.length > 0 || displayedSdg?.length > 0 || displayedFos?.length > 0">
            <ul uk-tab class="uk-tab uk-margin-bottom uk-flex uk-flex-center uk-flex-left@m">
              <li class="uk-active" *ngIf="displayedAllSubjects?.length" (click)="groupSubjects(displayedAllSubjects, 'all')">
                <a>All ({{displayedAllSubjects.length}})</a>
              </li>
              <li *ngIf="displayedSubjects?.length" (click)="groupSubjects(displayedSubjects, 'freeText')">
                <a>Free Text ({{displayedSubjects.length}})</a>
              </li>
              <li *ngIf="displayedSdg?.length" (click)="groupSubjects(displayedSdg, 'sdg')">
                <a>SDGs ({{displayedSdg.length}})</a>
              </li>
              <li *ngIf="displayedFos?.length" (click)="groupSubjects(displayedFos, 'fos')">
                <a>Fields of Science ({{displayedFos.length}})</a>
              </li>
            </ul>
            <ul class="uk-switcher">
              <li *ngIf="displayedAllSubjects?.length">
                <ng-container *ngIf="groupedAllSubjects?.length">
                  <div>
                    <ul class="uk-nav uk-nav-default uk-flex uk-flex-wrap">
                      <li *ngFor="let item of groupedAllSubjects; let i = index;" class="uk-margin-right" [class.uk-margin-left]="i != 0"
                        [class]="indexAll == i ? 'uk-active':''" (click)="changeDisplayedSubjects(i, item)">
                        <a class="uk-padding-remove">{{item.group}}</a>
                      </li>
                    </ul>
                  </div>
                  <!-- View for 'All' -->
                  <div *ngIf="indexAll == 0 && groupedAllSubjects.length > 1" class="uk-margin-large-top uk-grid uk-child-width-1-4@m" uk-grid>
                    <div *ngFor="let item of groupedAllSubjects.slice(1); let i = index;">
                      <div>
                        <h6>{{item.group}}</h6>
                        <div *ngFor="let subItem of item.data.slice(0, subjectsLimit)" class="uk-margin-small-bottom">
                          <a [queryParams]="{f0:subItem.type,fv0:createParams(subItem.value)}" class="uk-link-text"
                            routerLinkActive="router-link-active" [routerLink]="properties.searchLinkToAdvancedResults"
                            [attr.uk-tooltip]="subItem.value.length > maxCharacters ? subItem.value :''">
                            <span>{{subItem.value.length > maxCharacters ? subItem.value.substring(0,maxCharacters)+'...' : subItem.value}}</span>
                          </a>
                        </div>
                        <div *ngIf="item.data.length > subjectsLimit">
                          <a (click)="changeDisplayedSubjects(i+1, item)" class="view-more-less-link">
                            View all
                          </a>
                        </div>
                      </div>
                    </div>
                  </div>
                  <!-- View for a single group -->
                  <div *ngIf="indexAll != 0 || groupedAllSubjects.length == 1" class="uk-margin-large-top">
                    <div>
                      <div>
                        <h6>{{groupedAllSubjects[indexAll].group}}</h6>
                        <ng-container *ngIf="subjectsColumns?.length == 0; else elseBlock">
                          <div *ngFor="let subItem of groupedAllSubjects[indexAll].data" class="uk-margin-small-bottom">
                            <a [queryParams]="{f0:subItem.type,fv0:createParams(subItem.value)}" class="uk-link-text"
                              routerLinkActive="router-link-active" [routerLink]="properties.searchLinkToAdvancedResults"
                              [attr.uk-tooltip]="subItem.value.length > maxCharacters ? subItem.value :''">
                              <span>{{subItem.value.length > maxCharacters ? subItem.value.substring(0,maxCharacters)+'...' : subItem.value}}</span>
                            </a>
                          </div>
                        </ng-container>
                        <ng-template #elseBlock>
                          <div class="uk-grid uk-child-width-1-4@m" uk-grid>
                            <div *ngFor="let group of subjectsColumns">
                              <div *ngFor="let subItem of group" class="uk-margin-small-bottom">
                                <a [queryParams]="{f0:subItem.type,fv0:createParams(subItem.value)}" class="uk-link-text"
                                  routerLinkActive="router-link-active" [routerLink]="properties.searchLinkToAdvancedResults"
                                  [attr.uk-tooltip]="subItem.value.length > maxCharacters ? subItem.value :''">
                                  <span>{{subItem.value.length > maxCharacters ? subItem.value.substring(0,maxCharacters)+'...' : subItem.value}}</span>
                                </a>
                              </div>
                            </div>
                          </div>
                        </ng-template>
                      </div>
                    </div>
                  </div>
                </ng-container>
              </li>
              <li *ngIf="displayedSubjects?.length">
                <ng-container *ngIf="groupedSubjects?.length">
                  <div>
                    <ul class="uk-nav uk-nav-default uk-flex uk-flex-wrap">
                      <li *ngFor="let item of groupedSubjects; let i = index;" class="uk-margin-right" [class.uk-margin-left]="i != 0"
                        [class]="indexSubjects == i ? 'uk-active':''" (click)="changeDisplayedSubjects(i, item)">
                        <a class="uk-padding-remove">{{item.group}}</a>
                      </li>
                    </ul>
                  </div>
                  <!-- View for 'All' -->
                  <div *ngIf="indexSubjects == 0 && groupedSubjects.length > 1" class="uk-margin-large-top uk-grid uk-child-width-1-4@m" uk-grid>
                    <div *ngFor="let item of groupedSubjects.slice(1); let i = index;">
                      <div>
                        <h6>{{item.group}}</h6>
                        <div *ngFor="let subItem of item.data.slice(0, subjectsLimit)" class="uk-margin-small-bottom">
                          <a [queryParams]="{f0:'resultsubject',fv0:createParams(subItem)}" class="uk-link-text"
                            routerLinkActive="router-link-active" [routerLink]="properties.searchLinkToAdvancedResults"
                            [attr.uk-tooltip]="subItem.length > maxCharacters ? subItem :''">
                            <span>{{subItem.length > maxCharacters ? subItem.substring(0,maxCharacters)+'...' : subItem}}</span>
                          </a>
                        </div>
                        <div *ngIf="item.data.length > subjectsLimit">
                          <a (click)="changeDisplayedSubjects(i+1, item)" class="view-more-less-link">
                            View all
                          </a>
                        </div>
                      </div>
                    </div>
                  </div>
                  <!-- View for a single group -->
                  <div *ngIf="indexSubjects != 0 || groupedSubjects.length == 1" class="uk-margin-large-top">
                    <div>
                      <div>
                        <h6>{{groupedSubjects[indexSubjects]?.group}}</h6>
                        <ng-container *ngIf="subjectsColumns?.length == 0; else elseBlock">
                          <div *ngFor="let subItem of groupedSubjects[indexSubjects]?.data" class="uk-margin-small-bottom">
                            <a [queryParams]="{f0:'resultsubject',fv0:createParams(subItem)}" class="uk-link-text"
                              routerLinkActive="router-link-active" [routerLink]="properties.searchLinkToAdvancedResults"
                              [attr.uk-tooltip]="subItem.length > maxCharacters ? subItem :''">
                              <span>{{subItem.length > maxCharacters ? subItem.substring(0,maxCharacters)+'...' : subItem}}</span>
                            </a>
                          </div>
                        </ng-container>
                        <ng-template #elseBlock>
                          <div class="uk-grid uk-child-width-1-4@m" uk-grid>
                            <div *ngFor="let group of subjectsColumns">
                              <div *ngFor="let subItem of group" class="uk-margin-small-bottom">
                                <a [queryParams]="{f0:'resultsubject',fv0:createParams(subItem)}" class="uk-link-text"
                                  routerLinkActive="router-link-active" [routerLink]="properties.searchLinkToAdvancedResults"
                                  [attr.uk-tooltip]="subItem.length > maxCharacters ? subItem :''">
                                  <span>{{subItem.length > maxCharacters ? subItem.substring(0,maxCharacters)+'...' : subItem}}</span>
                                </a>
                              </div>
                            </div>
                          </div>
                        </ng-template>
                      </div>
                    </div>
                  </div>
                </ng-container>
              </li>
              <li *ngIf="displayedSdg?.length">
                <ng-container *ngIf="groupedSdg?.length">
                  <div>
                    <ul class="uk-nav uk-nav-default uk-flex uk-flex-wrap">
                      <li *ngFor="let item of groupedSdg; let i = index;" class="uk-margin-right" [class.uk-margin-left]="i != 0"
                        [class]="indexSdg == i ? 'uk-active':''" (click)="changeDisplayedSubjects(i, item)">
                        <a class="uk-padding-remove">{{item.group}}</a>
                      </li>
                    </ul>
                  </div>
                  <!-- View for 'All' -->
                  <div *ngIf="indexSdg == 0 && groupedSdg.length > 1" class="uk-margin-large-top uk-grid uk-child-width-1-4@m" uk-grid>
                    <div *ngFor="let item of groupedSdg.slice(1); let i = index;">
                      <div>
                        <h6>{{item.group}}</h6>
                        <div *ngFor="let subItem of item.data.slice(0, subjectsLimit)" class="uk-margin-small-bottom">
                          <a [queryParams]="{f0:'sdg',fv0:createParams(subItem)}" class="uk-link-text"
                            routerLinkActive="router-link-active" [routerLink]="properties.searchLinkToAdvancedResults"
                            [attr.uk-tooltip]="subItem.length > maxCharacters ? subItem :''">
                            <span>{{subItem.length > maxCharacters ? subItem.substring(0,maxCharacters)+'...' : subItem}}</span>
                          </a>
                        </div>
                        <div *ngIf="item.data.length > subjectsLimit">
                          <a (click)="changeDisplayedSubjects(i+1, item)" class="view-more-less-link">
                            View all
                          </a>
                        </div>
                      </div>
                    </div>
                  </div>
                  <!-- View for a single group -->
                  <div *ngIf="indexSdg != 0 || groupedSdg.length == 1" class="uk-margin-large-top">
                    <div>
                      <div>
                        <h6>{{groupedSdg[indexSdg].group}}</h6>
                        <ng-container *ngIf="subjectsColumns?.length == 0; else elseBlock">
                          <div *ngFor="let subItem of groupedSdg[indexSdg].data" class="uk-margin-small-bottom">
                            <a [queryParams]="{f0:'sdg',fv0:createParams(subItem)}" class="uk-link-text"
                              routerLinkActive="router-link-active" [routerLink]="properties.searchLinkToAdvancedResults"
                              [attr.uk-tooltip]="subItem.length > maxCharacters ? subItem :''">
                              <span>{{subItem.length > maxCharacters ? subItem.substring(0,maxCharacters)+'...' : subItem}}</span>
                            </a>
                          </div>
                        </ng-container>
                        <ng-template #elseBlock>
                          <div class="uk-grid uk-child-width-1-4@m" uk-grid>
                            <div *ngFor="let group of subjectsColumns">
                              <div *ngFor="let subItem of group" class="uk-margin-small-bottom">
                                <a [queryParams]="{f0:'sdg',fv0:createParams(subItem)}" class="uk-link-text"
                                  routerLinkActive="router-link-active" [routerLink]="properties.searchLinkToAdvancedResults"
                                  [attr.uk-tooltip]="subItem.length > maxCharacters ? subItem :''">
                                  <span>{{subItem.length > maxCharacters ? subItem.substring(0,maxCharacters)+'...' : subItem}}</span>
                                </a>
                              </div>
                            </div>
                          </div>
                        </ng-template>
                      </div>
                    </div>
                  </div>
                </ng-container>
              </li>
              <li *ngIf="displayedFos?.length">
                <ng-container *ngIf="groupedFos?.length">
                  <div>
                    <ul class="uk-nav uk-nav-default uk-flex uk-flex-wrap">
                      <li *ngFor="let item of groupedFos; let i = index;" class="uk-margin-right" [class.uk-margin-left]="i != 0"
                        [class]="indexFos == i ? 'uk-active':''" (click)="changeDisplayedSubjects(i, item)">
                        <a class="uk-padding-remove">{{item.group}}</a>
                      </li>
                    </ul>
                  </div>
                  <!-- View for 'All' -->
                  <div *ngIf="indexFos == 0 && groupedFos.length > 1" class="uk-margin-large-top uk-grid uk-child-width-1-4@m" uk-grid>
                    <div *ngFor="let item of groupedFos.slice(1); let i = index;">
                      <div>
                        <h6>{{item.group}}</h6>
                        <div *ngFor="let subItem of item.data.slice(0, subjectsLimit)" class="uk-margin-small-bottom">
                          <a [queryParams]="{f0:'fos',fv0:createParams(subItem)}" class="uk-link-text"
                            routerLinkActive="router-link-active" [routerLink]="properties.searchLinkToAdvancedResults"
                            [attr.uk-tooltip]="subItem.length > maxCharacters ? subItem :''">
                            <span>{{subItem.length > maxCharacters ? subItem.substring(0,maxCharacters)+'...' : subItem}}</span>
                          </a>
                        </div>
                        <div *ngIf="item.data.length > subjectsLimit">
                          <a (click)="changeDisplayedSubjects(i+1, item)" class="view-more-less-link">
                            View all
                          </a>
                        </div>
                      </div>
                    </div>
                  </div>
                  <!-- View for a single group -->
                  <div *ngIf="indexFos != 0 || groupedFos.length == 1" class="uk-margin-large-top">
                    <div>
                      <div>
                        <h6>{{groupedFos[indexFos].group}}</h6>
                        <ng-container *ngIf="subjectsColumns?.length == 0; else elseBlock">
                          <div *ngFor="let subItem of groupedFos[indexFos].data" class="uk-margin-small-bottom">
                            <a [queryParams]="{f0:'fos',fv0:createParams(subItem)}" class="uk-link-text"
                              routerLinkActive="router-link-active" [routerLink]="properties.searchLinkToAdvancedResults"
                              [attr.uk-tooltip]="subItem.length > maxCharacters ? subItem :''">
                              <span>{{subItem.length > maxCharacters ? subItem.substring(0,maxCharacters)+'...' : subItem}}</span>
                            </a>
                          </div>
                        </ng-container>
                        <ng-template #elseBlock>
                          <div class="uk-grid uk-child-width-1-4@m" uk-grid>
                            <div *ngFor="let group of subjectsColumns">
                              <div *ngFor="let subItem of group" class="uk-margin-small-bottom">
                                <a [queryParams]="{f0:'fos',fv0:createParams(subItem)}" class="uk-link-text"
                                  routerLinkActive="router-link-active" [routerLink]="properties.searchLinkToAdvancedResults"
                                  [attr.uk-tooltip]="subItem.length > maxCharacters ? subItem :''">
                                  <span>{{subItem.length > maxCharacters ? subItem.substring(0,maxCharacters)+'...' : subItem}}</span>
                                </a>
                              </div>
                            </div>
                          </div>
                        </ng-template>
                      </div>
                    </div>
                  </div>
                </ng-container>
              </li>
            </ul>
          </div>
        </div>
      </div>
    </div>
  `
})
export class SubjectsComponent {
  properties: EnvProperties = properties;
  breadcrumbs: Breadcrumb[] = [{name: 'Home', route: '/'}, {name: 'About - Subjects'}];
  pageContents = null;
  divContents = null;
  url: string = null;
  pageTitle: string = "Subjects";
  communityId = null;
  showLoading = true;
  subs: Subscription[] = [];

  displayedAllSubjects = [];
  displayedSubjects = [];
  displayedSdg = [];
  displayedFos = [];
  groupedAllSubjects = [];
  groupedSubjects = [];
  groupedSdg = [];
  groupedFos = [];
  subjectsColumns = [];
  subjectsLimit: number = 6;
  maxCharacters: number = 25;
  activeTab: 'all' | 'freeText' | 'sdg' | 'fos' = 'all';
  indexAll: number = 0;
  indexSubjects: number = 0;
  indexSdg: number = 0;
  indexFos: number = 0;

  viewAll: boolean = false;

  constructor(private route: ActivatedRoute,
              private communityService: CommunityService,
              private _router: Router,
              private helper: HelperService,
              private _meta: Meta,
              private _title: Title,
              private seoService: SEOService,
              private _piwikService: PiwikService) {
  }
  
  ngOnInit() {
    this.showLoading = true;
    this.url = this.properties.domain + this._router.url;
    this.seoService.createLinkForCanonicalURL(this.url);
    this.updateUrl(this.url);
    this.updateTitle(this.pageTitle);
    this.updateDescription("OpenAIRE - Connect, Community Gateway, research community");
    this.subs.push(this.communityService.getCommunityAsObservable().subscribe(community => {
      if (community) {
        this.communityId = community.communityId;
        this.subs.push(this._piwikService.trackView(this.properties, this.pageTitle).subscribe());
        this.getPageContents();
        this.displayedSubjects = community.subjects;
        this.displayedSdg = community.sdg;
        this.displayedFos = community.fos;
        this.displayedSubjects.forEach(element => {
          this.displayedAllSubjects.push({value: element, type: 'resultsubject'});
        });
        this.displayedSdg.forEach(element => {
          this.displayedAllSubjects.push({value: element, type: 'sdg'});
        });
        this.displayedFos.forEach(element => {
          this.displayedAllSubjects.push({value: element, type: 'fos'});
        });
        this.groupSubjects(this.displayedAllSubjects, 'all');
        this.showLoading = false;
      }
    }));
  }
  
  createParams(param) {
    return StringUtils.quote(StringUtils.URIEncode(param));
  }
  
  ngOnDestroy() {
    for (let sub of this.subs) {
      if (sub instanceof Subscriber) {
        sub.unsubscribe();
      }
    }
  }
  
  private getPageContents() {
    this.subs.push(this.helper.getPageHelpContents(this.properties, this.communityId, this._router.url).subscribe(contents => {
      this.pageContents = contents;
    }));
  }
  
  public groupSubjects(subjects: string[], type: string) {
    if(subjects.length === 0) {
      return [];
    }
    if(type === 'all') {
      subjects.sort((a, b) => a['value'].localeCompare(b['value']));
      this.indexAll = 0;
      this.activeTab = 'all';
      this.groupedAllSubjects = Object.values(
        subjects.reduce((acc, subject) => {
          let firstLetter = subject['value'][0].toLocaleUpperCase();
          if(!acc[firstLetter]) {
            acc[firstLetter] = {group: firstLetter, data: [subject]};
          } else {
            acc[firstLetter].data.push(subject);
          }
          return acc;
        },{})
      )
      if(subjects.length > 1) {
        this.groupedAllSubjects.unshift({group: 'All', data: subjects});
      }
    }
    if(type === 'freeText') {
      subjects.sort((a, b) => a.localeCompare(b));
      this.indexSubjects = 0;
      this.activeTab = 'freeText';
      this.groupedSubjects = Object.values(
        subjects.reduce((acc, subject) => {
          let firstLetter = subject[0].toLocaleUpperCase();
          if(!acc[firstLetter]) {
            acc[firstLetter] = {group: firstLetter, data: [subject]};
          } else {
            acc[firstLetter].data.push(subject);
          }
          return acc;
        },{})
      )
      if(subjects.length > 1) {
        this.groupedSubjects.unshift({group: 'All', data: subjects});
      }
    }
    if(type === 'sdg') {
      subjects.sort((a, b) => a.localeCompare(b));
      this.indexSdg = 0;
      this.activeTab = 'sdg';
      this.groupedSdg = Object.values(
        subjects.reduce((acc, subject) => {
          let firstLetter = subject[0].toLocaleUpperCase();
          if(!acc[firstLetter]) {
            acc[firstLetter] = {group: firstLetter, data: [subject]};
          } else {
            acc[firstLetter].data.push(subject);
          }
          return acc;
        },{})
      )
      if(subjects.length > 1) {
        this.groupedSdg.unshift({group: 'All', data: subjects});
      }
    }
    if(type === 'fos') {
      subjects.sort((a, b) => a.localeCompare(b));
      this.indexFos = 0;
      this.activeTab = 'fos';
      this.groupedFos = Object.values(
        subjects.reduce((acc, subject) => {
          let key = subject.substring(0,2).toLocaleUpperCase();
          if(!acc[key]) {
            acc[key] = {group: key, data: [subject]};
          } else {
            acc[key].data.push(subject);
          }
          return acc;
        },{})
      )
      if(subjects.length > 1) {
        this.groupedFos.unshift({group: 'All', data: subjects});
      }
    }
  }

  public changeDisplayedSubjects(i, group) {
    this.subjectsColumns = [];
    if(this.activeTab === 'all') {
      this.indexAll = i;
    } else if(this.activeTab === 'freeText') {
      this.indexSubjects = i;
    } else if(this.activeTab === 'sdg') {
      this.indexSdg = i;
    } else if(this.activeTab === 'fos') {
      this.indexFos = i;
    }
    if(group.data.length > this.subjectsLimit && group.group != 'All') {
      this.divideSubjects(group);
    }
  }

  public divideSubjects(group) {
    let columns = [];
    for(let i = 0; i < (group.data.length / this.subjectsLimit); i++) {
      columns.push(group.data.slice(i * this.subjectsLimit, ((i + 1) * this.subjectsLimit)));
    }
    this.subjectsColumns = columns;
  }
  
  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'");
  }
}
