import {Component, ElementRef, EventEmitter, Input, Output} from '@angular/core';
import {SearchProjectsService} from '../../services/searchProjects.service';
import {ProjectService} from '../../landingPages/project/project.service';
import {ClaimEntity, ClaimProject} from './claimHelper.class';
import {EnvProperties} from '../../utils/properties/env-properties';
import {ErrorCodes} from '../../utils/properties/errorCodes';
import {StringUtils} from "../../utils/string-utils.class";
import {Filter, Value} from "../../searchPages/searchUtils/searchHelperClasses.class";
import {RangeFilter} from "../../utils/rangeFilter/rangeFilterHelperClasses.class";
import {OpenaireEntities, SearchFields} from "../../utils/properties/searchFields";
import {NewSearchPageComponent} from "../../searchPages/searchUtils/newSearchPage.component";
import {Subscriber} from "rxjs";

declare var UIkit:any;

@Component({
    selector: 'claim-projects-search-form',

    templateUrl:'claimProjectSearchForm.component.html',

})
export class ClaimProjectsSearchFormComponent {
  public query = '';
  @Input() public centerAlign: boolean = false;
  @Input() public selectedProjects:ClaimEntity[]=[] ;
  public elementRef;

  @Output() projectSelected = new EventEmitter();
  @Input() public properties:EnvProperties;
  @Input() public inlineClaim:boolean=false;
  @Input()  localStoragePrefix:string = "";
  @Input() basketLimit;
  @Input() showOptions;

  public errorCodes:ErrorCodes = new ErrorCodes();
  public projects:string[];
  public warningMessage = "";
  openaireResults:ClaimEntity[] = [];
  openaireResultsNum: number ;
  openaireResultsPage : number = 1;
  openaireResultsStatus:number = this.errorCodes.NONE;
  page : number = 1;
  size:number = 5;
  keyword:string = '';
  showResults = false;

  public refineFields: string[] = ["funder"];
  public refineFieldsQuery: string = "&refine=true&fields=funder";
  filters = [];
  prevFilters = [];
  public rangeFilters: RangeFilter[] = [];
  public searchFields: SearchFields = new SearchFields();
  public rangeFields:string[][] = this.searchFields.PROJECT_RANGE_FIELDS;
  openaireEntities = OpenaireEntities;
  sub;
  constructor(private _service: ProjectService, private _projectService: SearchProjectsService, myElement: ElementRef) {
      this.elementRef = myElement;
    this.rangeFilters = RangeFilter.parse(this.rangeFields,"project");

  }
  ngOnDestroy() {
    if (this.sub  instanceof Subscriber) {
      this.sub.unsubscribe();
    }
  }

  search(page,size) {
    if(this.keyword.length == 0){
      this.showResults =false;
      return;
    }
    this.showResults =true;
    this.openaireResults = [];
    this.openaireResultsStatus = this.errorCodes.LOADING;
    this.prevFilters = this.filters;

    //searchProjects (params: string, refineParams:string, page: number, size: number, refineFields:string[] , properties:EnvProperties ):any {
    this.sub = this._projectService.searchProjects(this.createOpenaireQueryParams(),(page==1)? this.refineFieldsQuery:null, page, size, (page==1)?this.refineFields:[], this.properties).subscribe(
      data => {
          if(data != null) {
              this.openaireResultsPage=page;
              this.openaireResultsNum = data[0];
              this.openaireResults =ClaimProjectsSearchFormComponent.openaire2ClaimEntity(data[1], this.properties);
              if(data[2] && data[2].length > 0){
                this.filters =  this.checkSelectedFilters( data[2], this.prevFilters);
              }

              this.openaireResultsStatus = this.errorCodes.DONE;
              if(this.openaireResultsNum == 0){
                this.openaireResultsStatus = this.errorCodes.NONE;
                this.filters =  this.checkSelectedFilters( [], this.prevFilters);
              }
          }else {
            this.openaireResultsStatus = this.errorCodes.ERROR;
          }
       },
      err => {
        this.openaireResultsStatus = this.errorCodes.ERROR;
        //console.log(err.status);
        ClaimProjectsSearchFormComponent.handleError("Error getting projects by keyword: "+this.keyword, err);
      }
    );
  }
// select(entity){
//   if(this.selectedProjects.length > 50){
//     UIkit.notification({
//         message : 'Your basket exceeds the number of allowed projects (50)',
//         status  : 'warning',
//         timeout : 1500,
//         pos     : 'top-center'
//     });
//     return;
//   }
//     this.query = "";
//     // this.searchTermStream.next(this.query); //clear
//     entity = entity.value;
//     // var project: ClaimProject = new ClaimProject();
//     // project.funderId = entity.funderId;
//     // project.funderName = entity.funderName;
//     // project.id = entity.id;
//     // project.projectName = entity.projectName;
//     // project.projectAcronym = entity.projectAcronym;
//     // project.startDate = entity.startDate;
//     // project.endDate = entity.endDate;
//     // project.code = entity.code;
//     // project.jurisdiction = entity.jurisdiction;
//     // project.fundingLevel0 = entity.fundingLevel0;
//
//
//     var index:number =this.selectedProjects.indexOf(entity);
//     var found:boolean = false;
//     this.warningMessage = "";
//
//     for (var _i = 0; _i < this.selectedProjects.length; _i++) {
//         let project = this.selectedProjects[_i];
//         if(entity.id == project.id){
//               found=true;
//               this.warningMessage = "Project already in your basket";
//         }
//      }
//
//     if (!found) {
//       this.selectedProjects.push(entity);
//       if(this.selectedProjects != null){
//         localStorage.setItem(this.localStoragePrefix + "projects", JSON.stringify(this.selectedProjects));
//       }
//       this.projectSelected.emit({
//         value: true
//       });
//
//     }
// }
/*  static showItem(item):string{
    return ((item.field[1]['@value'])?item.field[1]['@value']+" - ":"" ) + item.field[3]['@value'];
  }*/
  remove(item){
    let index:number =this.selectedProjects.indexOf(item);
     if (index > -1) {
        this.selectedProjects.splice(index, 1);
    }

  }
/*  handleClick(event){
   var clickedComponent = event.target;
   var inside = false;
   do {
       if (clickedComponent === this.elementRef.nativeElement) {
           inside = true;
       }
      clickedComponent = clickedComponent.parentNode;
   } while (clickedComponent);

  }*/
  static openaire2ClaimEntity(items, properties:EnvProperties){
    const projects: ClaimEntity[] = [];
    for(const item of items){
      const entity: ClaimEntity = new ClaimEntity();
      entity.project = new ClaimProject();
      entity.project.funderId = item.funderId;
      entity.project.funderName = item.funderShortname;
      entity.id = item.id;
      entity.project.url = properties.searchLinkToProject + entity.id;
      entity.title = item.title.name;
      entity.project.acronym = item.acronym;
      entity.project.startDate = item.startYear;
      entity.project.endDate = item.endYear;
      entity.project.code = item.code;
      entity.project.jurisdiction = item.jurisdiction;
      entity.project.fundingLevel0 = item.fundingLevel0;
      entity.type="project";
      projects.push(entity);
    }
    return projects;
  }
  private openaireResultsPageChange($event) {
     this.openaireResultsPage=$event.value;
     this.openaireResults = [];
     this.search(this.openaireResultsPage,this.size);
  }
  private static handleError(message: string, error) {
      console.error("Claim project search form (component): "+message, error);
  }


  createOpenaireQueryParams():string {
    let query = "";
    if(this.keyword.length > 0){
      query += "q=" + StringUtils.quote(StringUtils.URIEncode(this.keyword));
    }

    /*if(this.startYear.length > 0 ){
      query+='&fq=projectstartyear exact \"'+this.startYear+'\"'
    }
    if(this.endYear.length > 0 ){
      query+='&fq=projectendyear exact \"'+this.endYear+'\"'
    }*/
    let allFqs = "";
    for (let filter of this.filters){
      if(filter.countSelectedValues > 0){
        let count_selected=0;
        let fq = "";
        for (let value of filter.values){
          if(value.selected == true){
            count_selected++;
            fq+=(fq.length > 0 ? " " + filter.filterOperator + " ":"" ) + filter.filterId + " exact " + (StringUtils.quote(value.id));
          }
        }
        if(count_selected > 0){
          fq="&fq="+StringUtils.URIEncode(fq);
          allFqs += fq;
        }
      }
    }
    for (let i=0; i<this.rangeFilters.length; i++){
      let filter = this.rangeFilters[i];
      //selectedFromValue, selectedToValue, equalityOp, equalityOpFrom, equalityOpTo, filterOp ){
      allFqs+= NewSearchPageComponent.createRangeFilterQuery(this.rangeFields[i],filter.selectedFromValue, filter.selectedToValue, " within ", ">=" ,"<=", "and" )
    }
    return query+allFqs;

  }
  public yearChanged() {
    this.search(this.page, this.size);

  }

  filterChanged($event) {
    this.search(this.page, this.size);

  }
  public checkSelectedFilters(filters:Filter[], prevFilters:Filter[]){
    for(let i=0; i< filters.length ; i++){
      let filter:Filter = filters[i];
      filter.countSelectedValues = 0;
      let prevFilterSelectedValues:string[] = [];
      for(let j=0; j< prevFilters.length ; j++){
        if(filters[i].filterId == prevFilters[j].filterId){
          if(prevFilters[j].countSelectedValues >0){
            for(let filterValue of prevFilters[j].values) {
              if(filterValue.selected){
                prevFilterSelectedValues.push(filterValue.id);
              }
            }

          }
          break;
        }
      }
      for(let filterValue of filter.values) {
        if(prevFilterSelectedValues.indexOf(filterValue.id) > -1) {
          filterValue.selected = true;
          filter.countSelectedValues++;
        }

      }

    }
    if(filters.length == 0 ){
      for(let j=0; j< prevFilters.length ; j++){
            let filter  = Object.assign({}, prevFilters[j]);
            filter.values = [];
            for(let filterValue of prevFilters[j].values) {
              if(filterValue.selected){
                filterValue.number  = 0;
                filter.values.push(filterValue);
              }
            }
            filters.push(filter)
          }
    }
    return filters;
  }
  totalPages(totalResults: number): number {
    let totalPages:any = totalResults/(this.size);
    if(!(Number.isInteger(totalPages))) {
      totalPages = (parseInt(totalPages, 10) + 1);
    }
    return totalPages;
  }

  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;

  }
  dateFilterChanged(filter:RangeFilter) {
    if (filter.selectedFromValue && filter.selectedToValue) {
      filter.selectedFromAndToValues = filter.selectedFromValue + "-" + filter.selectedToValue;
    } else if (filter.selectedFromValue) {
      filter.selectedFromAndToValues = "From " + filter.selectedFromValue;
    } else if (filter.selectedToValue) {
      filter.selectedFromAndToValues = "Until " + filter.selectedToValue;
    }
    this.filterChanged(null);
  }

  private removeFilter(value: Value, filter: Filter) {
    filter.countSelectedValues--;
    if (value.selected == true) {
      value.selected = false;
    }
    // this.search(false);
    this.filterChanged(null);
  }

  public countFilters(): number {
    let filters = 0;
    for (let filter of this.filters) {
      if (filter.countSelectedValues > 0) {
        filters += filter.countSelectedValues;
      }
    }
    for (let filter of this.rangeFilters) {
      if (filter.selectedFromValue || filter.selectedToValue) {
        filters += 1;
      }
    }
    return filters;
  }

  private clearFilters() {
    for (let i = 0; i < this.filters.length; i++) {
      for (let 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;
      }
    }
    for(let filter of this.rangeFilters){
      this.removeRangeFilter(filter);
    }
    this.filterChanged(null);
  }
  public removeRangeFilter(filter: RangeFilter) {
    filter.selectedFromValue = null;
    filter.selectedToValue = null;
    filter.selectedFromAndToValues = null;
    this.filterChanged(null);
  }
}
