import {
  Component,
  Input,
  Output,
  EventEmitter,
  OnInit,
  OnChanges,
  SimpleChanges,
  ChangeDetectorRef
} from '@angular/core';
import {Filter, Value} from './searchHelperClasses.class';
import {ActivatedRoute, Router} from "@angular/router";
import {SearchFields} from "../../utils/properties/searchFields";
import {HelperFunctions} from "../../utils/HelperFunctions.class";
import {Option} from "../../sharedComponents/input/input.component";
@Component({
  selector: 'search-filter',
  templateUrl: 'searchFilter.component.html'
})

export class SearchFilterComponent implements OnInit, OnChanges {
  
  @Input() filter: Filter;
  @Input() showResultCount: boolean = true;
  @Input() isDisabled: boolean = false;
  @Input() addShowMore: boolean = true;
  @Input() showMoreInline: boolean = true;
  @Input() filterValuesNum: number = 6;
  public hasMoreValues: boolean = false;
  public showAll: boolean = false;
  public _maxCharacters: number = 28;
  
  @Output() toggleModal = new EventEmitter();
  
  @Output() modalChange = new EventEmitter();
  @Output() onFilterChange = new EventEmitter();
  @Output() onFilterToggle = new EventEmitter();
  keyword = "";
  sortBy: "name" | "num" = "name";
  sortByOptions: Option[] = [{label: 'Results number', value: 'num'}, {label: 'Name', value: 'name'}];
  queryParams = {};
  paramPosition = 0;
  @Input() actionRoute: boolean = false;
  @Input() quickFilter: { filter: Filter, selected: boolean, filterId: string, value: string };
  sub;
  // @Input() isViewAllOpen: boolean = false;
  sortedValues;
  hasMatch: boolean = false;
  @Input() grouped: boolean = false;

  constructor(private _router: Router,
              private route: ActivatedRoute,
              private cdr: ChangeDetectorRef) {
  }
  
  ngOnDestroy() {
    if (this.sub) {
      this.sub.unsubscribe();
    }
  }
  
  ngOnInit() {
    if(this.filterValuesNum == 0){
      this.filter.isViewAllOpen = true;
      this.sortBy = "num";
    }
    // else{
    //   this.filter.isViewAllOpen = false;
    // }
    this.sub = this.route.queryParams.subscribe(params => {
      this.queryParams = Object.assign({}, params);
      this.paramPosition = SearchFields.getParameterOrder(this.filter.filterId, this.getEntries(params));
    });
    // this.filter.values = this.filter.values.filter(value => !value.name.toLowerCase().includes('unknown') && !value.name.toLowerCase().includes('not available'));
    // this.sort();
    // if (this.filter.filterType == "radio") {
    //   this.filter.radioValue = "";
    //   this.filter.values.forEach(value => {
    //     if (value.selected) {
    //       this.filter.radioValue = value.id
    //     }
    //   });
    // }
  }
  
  ngOnChanges(changes: SimpleChanges) {
    if (changes.filter) {
      this.hasMoreValues = (this.filter.countUnfilteredValues > 0 ? this.filter.countUnfilteredValues : this.filter.values.length) > this.filterValuesNum;
      // this.filter.values = this.filter.values.filter(value => !value.name.toLowerCase().includes('unknown') && !value.name.toLowerCase().includes('not available'));
      // this.filter.values = this.filter.values.filter(value => value  && value.name != "unidentified" && value.name != "Undetermined" && !value.name.toLowerCase().includes('unknown') && !value.name.toLowerCase().includes('not available')
      //   && value.name.toLowerCase() != "null"
      // );

      if (this.filter.filterType == "radio" || this.filter.filterType == "triplet") {
        this.filter.radioValue = "";
        this.filter.values.forEach(value => {
          if (value.selected) {
            this.filter.radioValue = value.id
          }
        });
      }
      this.sort();
    }
  }
  
  public _formatTitle(title, length) {
    // return (((title + " (" + length + ")").length > this._maxCharacters) ? (title.substring(0, (this._maxCharacters - (" (" + length + ")").length - ('...').length)) + "...") : title) + " (" + (length > 95 ? "100" : length) + ")";
    return (((title).length > this._maxCharacters) ? (title.substring(0, (this._maxCharacters - ('...').length)) + "...") : title);
  }
  
  public _formatName(value) {
    //let maxLineLength = 24;
    let maxLineLength = 35;
    
    //1 space after checkbox
    //3 space before number + parenthesis
    if (!this.showResultCount && value.name.length + 1 > maxLineLength) {
      return value.name.substr(0, maxLineLength - 3 - 1) + '...';
    }
    if (value.name.length + value.number.toLocaleString().length + 1 + 3 > maxLineLength) {
      return value.name.substr(0, (maxLineLength - 3 - 4 - value.number.toLocaleString().length)) + '...';
    }
    
    return value.name;
  }
  
  filterKeywords(value) {
    if (this.keyword.length > 0) {
      if (value.toLowerCase().indexOf(this.keyword.toLowerCase()) == -1) {
        return false;
      }
    }
    if(!this.hasMatch) {
      this.hasMatch = true;
      this.cdr.detectChanges();
    }
    return true;
  }
  
  filterChange(selected: boolean) {
    if (selected) {
      this.filter.countSelectedValues++;
    } else {
      this.filter.countSelectedValues--;
    }
    this.onFilterChange.emit({
      value: this.filter
    });
  }
  
  uniqueFilterChange(value: Value) {
    let tmp = value.selected;
    value.selected = !tmp;
    
    if (value.selected) {
      this.filter.countSelectedValues = 1;
    } else {
      this.filter.countSelectedValues = 0;
    }
    
    this.filter.values.forEach(value => {
      value.selected = (value.id == this.filter.radioValue);
    });
    this.onFilterChange.emit({
      value: this.filter
    });
  }

  tripletFilterChange() {
    if(this.filter.radioValue == "") {
      this.clearFilter();
    } else {
      this.filter.countSelectedValues = 1;
      this.filter.values.forEach(value => {
        value.selected = (value.id == this.filter.radioValue);
      });
      this.onFilterChange.emit({
        value: this.filter
      });
    }
  }
  
  clearFilter() {
    for (var i = 0; i < this.filter.values.length; i++) {
      this.filter.values[i].selected = false;
    }
    this.filter.countSelectedValues = 0;
    this.onFilterChange.emit({
      value: this.filter
    });
    this.filter.radioValue = "";
  }
  
  getSelectedAndTopValues(filter, topNum: number = 6): any {
    var values = [];
    
    for (let i = 0; i < topNum; i++) {
      if (filter.values.length <= i) {
        break;
      }
      values.push(filter.values[i]);
    }
    
    if (filter.countSelectedValues > 0) {
      for (let i = topNum; i < filter.values.length; i++) {
        if (filter.values[i].selected) {
          values.push(filter.values[i]);
        }
      }
    }
    
    return values;
  }
  
  getSelectedValues(filter, sortBy: string = "num"): 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]);
        }
      }
    }
    if (sortBy == "name") {
      
      selected.sort((n1, n2) => {
        if (n1.name > n2.name) {
          return 1;
        }
        
        if (n1.name < n2.name) {
          return -1;
        }
        
        return 0;
      });
    }
    return selected;
    
  }
  
  getNotSelectedValues(filter, sortBy: string = "num"): any {
    var notSselected = [];
    for (var i = 0; i < filter.values.length; i++) {
      if (!filter.values[i].selected) {
        notSselected.push(filter.values[i]);
      }
    }
    
    if (sortBy == "name") {
      
      notSselected.sort((n1, n2) => {
        if (n1.name > n2.name) {
          return 1;
        }
        if (n1.name < n2.name) {
          return -1;
        }
        
        return 0;
      });
    }
    return notSselected;
  }
  
  sort() {
    let sorted: Value[] = this.filter.values.slice();
    if (this.sortBy == "name") {
      sorted.sort((n1, n2) => {
        if (this.filter.filterId === "sdg") {
          return HelperFunctions.sortSDGs(n1.name.toLowerCase(), n2.name.toLowerCase());
        } else {
          if (n1.name.toLowerCase() > n2.name.toLowerCase()) {
            return 1;
          }
          if (n1.name < n2.name) {
            return -1;
          }
          return 0;
        }
      });
    } 
    this.sortedValues = Object.assign(sorted);
  }

  initMatching() {
    this.hasMatch = false;
    this.cdr.detectChanges();
  }
  
  toggle(event) {
    this.filter.isViewAllOpen = !this.filter.isViewAllOpen;
    event.stopPropagation();
    this.toggleWithoutUpdate();
  }

  toggleWithoutUpdate() {
    if(this.filter.countAllValues == 0) {
      this.filter.countAllValues = -1;  // if request failed, try again automatically if toggled again
    }
    if(this.filter.isViewAllOpen && this.filter.countAllValues < 0) {
      this.onFilterToggle.emit(this.filter);
    }
  }
  
  disabled(value) {
    return this.isDisabled || (this.showResultCount && value === 0);
  }
  
  getFilterName(value) {
    let name = value.name + " (" + value.number.format() + ")";
    return name;
  }
  
  getRoute() {
    return this._router.url.split("?")[0];
  }
  
  getParams(filter: Filter, value: Value) {
    let params = Object.assign({}, this.queryParams);
    /*      let qf=false;
          if(this.quickFilter && this.quickFilter.filterId == filter.filterId && this.quickFilter.selected && value.id == this.quickFilter.value){
            params['qf']="false";
            qf=true;
          }*/
    if (params[filter.filterId] && this.checkIfValueIndexOf(params[filter.filterId].split(','), value.id) == -1 /*&& !qf*/) {
      //has other values of this filter --> add this value
      params[filter.filterId] = params[filter.filterId] + ',' + '"' + encodeURIComponent(value.id) + '"';
    } else if (params[filter.filterId] && this.checkIfValueIndexOf(params[filter.filterId].split(','), value.id) != -1) {
      // has this filter and the value -- > remove it
      
      let values = params[filter.filterId].split(',');
      values.splice(this.checkIfValueIndexOf(values, value.id), 1);
      params[filter.filterId] = values.join(',');
      if (values.length == 0) {
        delete params[filter.filterId];
      }
    } else /*if(!qf)*/{
      //has no filter, no value --> add the value
      //check the order
      let keyValues = this.getEntries(params);
      keyValues.splice(this.paramPosition, 0, [filter.filterId, '"' + encodeURIComponent(value.id) + '"']); // insert key value at paramPosition.
      params = keyValues.reduce((o, key) => Object.assign(o, {[key[0]]: key[1]}), {});
      // params[filter.filterId] = '"' + encodeURIComponent(value.id) + '"' ;
    }
    delete params['page'];
    return params;
  }
  
  checkIfValueIndexOf(array, value) {
    let encodedValue = encodeURIComponent(value);
    if (array.indexOf(encodedValue) != -1) {
      return array.indexOf(encodedValue);
    }
    if (array.indexOf('"' + encodedValue + '"') != -1) {
      return array.indexOf('"' + encodedValue + '"');
    }
    return -1;
  }
  
  getEntries(obj) {
    if (!Object.entries) {
      
      var ownProps = Object.keys(obj),
        i = ownProps.length,
        resArray = new Array(i); // preallocate the Array
      while (i--)
        resArray[i] = [ownProps[i], obj[ownProps[i]]];
      return resArray;
    } else {
      return Object.entries(obj);
    }
  }
}