import { Utils } from '../Utils';

interface FilterObject {
  title: string;
  value: string;
}

interface SwifttypeRecord {
  body: string;
  id: string;
  image: string;
  sort: null;
  title: string;
  type: string;
  url: string;
}

const MINIMUM_QUERY_LENGTH = 2;
const INITIAL_PAGE_COUNTER = 1;
const TAB_LABEL_IDENTIFIER_PREFIX = 'search.component.tab.label.'

export class SearchController {

  public query: string;
  public searchActive: boolean = false;
  public records: Array<any> = [];
  public searching: boolean = false;
  public numPages: number = 0;
  public currentPageCounter: number = 0;
  public attributes: Array<any> = [];
  public selectedAttribute: FilterObject = {
    title: 'all',
    value: ''
  };
  public filterObject: any = {
    type: this.selectedAttribute.value
  }

  private inputElement: HTMLElement;
  private data: Array<any> = [];

  constructor(
    private SearchService,
    private $element,
    private $timeout
  ) {
    this.subscribeObservables();
  }

  $onInit(): void {
    this.inputElement = this.$element.find('#search')[0];
    this.inputElement.addEventListener('keyup', (e) => {
      if (e.keyCode === 13) {
        this.inputElement.blur();
      } else if (e.keyCode === 27) {
        this.closeActiveState();
      }
    });
  }

  private subscribeObservables(): void {
    this.SearchService.get().subscribe((data) => {
      if (data) {
        this.data = data;
        if (this.data['info'].page.current_page === 1) {
          this.resetRecords();
          if (this.data['info'].page.num_pages > 1) {
            this.viewObserver();
          }
        }
        if (this.query.length > MINIMUM_QUERY_LENGTH) {
          this.records = this.records.concat(this.data['records'].page);
          this.attributes = this.getAttributes(this.records);
          this.numPages = this.data['info'].page.num_pages;
          this.currentPageCounter = this.data['info'].page.current_page;
          this.searching = false;
        }
      }
    });
  }

  private resetRecords(): void {
    this.records = [];
    this.currentPageCounter = INITIAL_PAGE_COUNTER;
  }

  public queryChangeHandler(): void {
    if (this.query.length > MINIMUM_QUERY_LENGTH) {
      this.searching = true;
      this.SearchService.updateQuery(this.query);
    } else {
      this.resetRecords();
    }
  }

  public getAttributes(list: Array<SwifttypeRecord>): Array<FilterObject> {
    let attributes = this.attributes.map(item => { return item.value });
    for (let item of list) {
      if (attributes.indexOf(item.type) === -1) {
        attributes.push(item.type);
      }
    }
    let filterObjects = attributes.map(item => {
      let title = (item === '') ? 'all' : item;
      return {
        title: TAB_LABEL_IDENTIFIER_PREFIX + title,
        value: item
      }
    });
    return filterObjects;
  }

  public setSelectedAttribute(attribute: FilterObject): void {
    this.selectedAttribute = attribute;
    this.filterObject.type = this.selectedAttribute.value;
  }

  public toggleActiveState(): void {
    this.inputElement.focus();
    this.searchActive = !this.searchActive;
    Utils.toggleNoScrollBodyState();
  }

  public closeActiveState(): void {
    this.inputElement.blur();
    this.$timeout(() => {
      this.searchActive = false;
    });
    Utils.toggleNoScrollBodyState();
  }

  public viewObserver(): void {
    let updateView = document.querySelector('search-component .backdrop');
    let updateViewTrigger = document.querySelector('search-component .js-update-view-trigger');
    let io;
    let onChange = changes => {
      changes.forEach(change => {
        if (change.isIntersecting) {
          this.updateViewHandler();
          if (this.currentPageCounter === this.numPages) {
            io.unobserve(change.target);
          }
        }
      }, this);
    }
    let observerOptions = {
      root: updateView,
      rootMargin: '0px 0px 250px 0px',
      threshold: [0.0]
    }
    io = new IntersectionObserver(onChange, observerOptions);
    io.observe(updateViewTrigger);
  }

  public updateViewHandler(): void {
    if (this.currentPageCounter !== this.numPages) {
      this.currentPageCounter++;
    }
    if (this.currentPageCounter < this.numPages) {
      this.SearchService.getData(this.query, this.currentPageCounter);
    } else {
      this.currentPageCounter = this.numPages;
    }
  }
}
