import { AfterViewInit, AfterContentInit, Component, ElementRef, Input, OnInit, OnDestroy, NgZone, Renderer2, ViewChild, ViewContainerRef, TemplateRef, EmbeddedViewRef, ViewRef, ChangeDetectorRef, DoCheck, OnChanges, SimpleChange, ViewEncapsulation } from '@angular/core';
import { ActivatedRoute } from '@angular/router';
import { FormGroup, FormControl, FormArray, FormBuilder, Validators } from '@angular/forms';
import { Subscription } from 'rxjs/Subscription';
import { Subscriber } from 'rxjs/Subscriber';
import { Observable } from 'rxjs/Observable';
import { of } from 'rxjs/observable/of';
import { delay, share } from 'rxjs/operators';
import 'rxjs/add/operator/map';
import 'rxjs/add/operator/toPromise';
import { CurrencyService, ExchangeService, FilterService, UserService, LoaderService, TokenService, IKnokOngoingArgs } from '../../../core/shared';
import { IFilter, IKnokFeedArgs, IKnokRaiting, IKnokSort, ICurrency, IExchange, IUser, IUserCredentials, IUserAccounts, User } from '../../../core/shared';
import { ILog, Log, applyMixins, ViewRefWatcherService } from '../../shared/helpers';
import * as MDC from 'material-components-web';
import { head as _head, findIndex as _findIndex, fill as _fill } from 'lodash/array';
import { has as _has } from 'lodash/object';
import { SimpleChanges } from '@angular/core/src/metadata/lifecycle_hooks';

@Component({
  selector: 'knk-search-sort',
  templateUrl: './knk-search-sort.component.pug',
  styleUrls: ['./knk-search-sort.component.scss']
})
export class KnkSearchSortComponent implements AfterViewInit, OnInit, OnDestroy, ILog {
  // @Input('filterType') filterType: string = 'discover';
  filterType: string;
  form: FormGroup = null;
  availableDiscoverSort: IKnokSort[] = [];
  availableTrackSort: IKnokSort[] = [{id: 1, name: 'Time Left'}];
  accounts: IUserAccounts = null;

  price: number[] = [1, 40];

  knoks: number = 0;
  currentProfit: number = 0;
  totalPotentialProfit: number = 0;
  userIsKnokser: boolean = false;

  set sort(value: number) {
    this._sort = Number(value);
  }

  get sort(): number {
    return this._sort;
  }

  /* Mixins */
  public log: (...args: any[]) => void;

  protected _sort: number = 1;
  protected applyTimeout: any = null;
  protected lang: string;

  private loadUserSubscription: Subscription;
  private filterSubscription: Subscription;
  private filterRefreshSubscription: Subscription;
  private userIsKnokserSubscription: Subscription;
  private sortSubscription: Subscription;
  private filterTypeSubscription: Subscription;

  constructor(private element: ElementRef,
              private route: ActivatedRoute,
              private userService: UserService,
              private filterService: FilterService,
              private fb: FormBuilder) {
  }

  ngOnInit(): void {
    const langParamName: string = 'lang';
    this.lang = this.route.snapshot.data[langParamName];

    if (this.userService) {
      const isTestPropertyName: string = 'test';
      this.userService.testParam = this.route.snapshot.data[isTestPropertyName];
    }

    if (this.filterService) {
      // this.filterSubscription = this.filterService.filterSettings.subscribe((filter) => {
      //   this.filter = filter;
      // });
      
      this.filterRefreshSubscription = this.filterService.feedArgsRefreshObservable.subscribe((reset: boolean) => {
        if (reset) {
          // this.reset();
        } else {
          this.apply();
        }
      });

      this.sortSubscription = this.filterService.sortObservable.subscribe((value: number) => {
        this.sort = value;
      });

      this.filterTypeSubscription = this.filterService.filterTypeObservable.subscribe((filterType: string) => {
        this.filterType = filterType;
        this.userIsKnokserSubscription = this.filterService.userIsKnokserObservable.subscribe((value: boolean) => {
          this.userIsKnokser = value;
          if (this.filterType === 'track') {
            this.availableTrackSort = [];
            if (this.userIsKnokser) { // Knokser
              this.availableTrackSort.push({id: 1, name: 'Time Left'});
              this.availableTrackSort.push({id: 2, name: 'Distance from target'});
              this.availableTrackSort.push({id: 5, name: 'Price Pool'});
              this.availableTrackSort.push({id: 6, name: 'Buyer Review'});
            } else { // Trader
              this.availableTrackSort.push({id: 1, name: 'Time Left'});
              this.availableTrackSort.push({id: 2, name: 'Distance from target'});
              this.availableTrackSort.push({id: 3, name: 'Current Profit'});
              this.availableTrackSort.push({id: 4, name: 'Purchases'});
            }
          }
          if (this.filterType === 'ended') {
            this.availableTrackSort = [];
            if (this.userIsKnokser) { // Knokser
              this.availableTrackSort.push({id: 1, name: 'End Time'});
              this.availableTrackSort.push({id: 4, name: 'Distance from target'});
              this.availableTrackSort.push({id: 5, name: 'Price Pool'});
              this.availableTrackSort.push({id: 6, name: 'Buyer Review'});
              this.availableTrackSort.push({id: 3, name: 'Number of Purcahses'});
            } else {
              this.availableTrackSort.push({id: 3, name: 'Purchases'});
              this.availableTrackSort.push({id: 1, name: 'End Time'});
              this.availableTrackSort.push({id: 2, name: 'Profit'});
            }
          }
        });
        if (this.filterType === 'discover') {
          this.availableDiscoverSort = [];
          this.availableDiscoverSort.push({id: 1, name: 'Time Left'});
          this.availableDiscoverSort.push({id: 2, name: 'Price'});
          this.availableDiscoverSort.push({id: 3, name: 'Purchases'});
        }
      });
    }

    this.createForm();
  }

  ngAfterViewInit(): void {
    // todo: create auto init directive and clean it
    MDC.autoInit(this.element.nativeElement);
  }

  ngOnDestroy(): void {
    // this.viewWatcher.unset('sort');

    if (this.loadUserSubscription) {
      this.loadUserSubscription.unsubscribe();
    }

    // if (this.exchangeSubscription) {
    //   this.exchangeSubscription.unsubscribe();
    // }

    // if (this.currencySubscription) {
    //   this.currencySubscription.unsubscribe();
    // }

    if (this.filterSubscription) {
      this.filterSubscription.unsubscribe();
    }

    if (this.filterRefreshSubscription) {
      this.filterRefreshSubscription.unsubscribe();
    }

    if (this.filterTypeSubscription) {
      this.filterTypeSubscription.unsubscribe();
    }
  }

  apply(): void {
    if (this.applyTimeout) {
      clearTimeout(this.applyTimeout);
    }

    this.applyTimeout = setTimeout((): void => {
      this.applyArgs();
      clearTimeout(this.applyTimeout);
    }, 1000);
  }

  onSelectChange(event: CustomEvent, control: string): void {
    const target: HTMLElement | null = event.target as HTMLElement | null;
    const detail: any | null = <CustomEvent>event.detail as any | null;
    let fc: FormControl;
    switch (control) {
      case 'sort':
        fc = this.form.get('sort') as FormControl;
        break;
      default:
        fc = null;
        break;
    }

    if (target && fc) {
      const index: number = detail.index as number | null;
      const option: HTMLElement | null = detail.item as HTMLElement | null;
      const value: string = option.dataset.value as string | null;
      fc.setValue(value);
    }
  }

  menuToggleHandler(nodeToggle: any, nodeMenu: any, closed?: false): void {
    let toggle: any = nodeToggle.MDCIconToggle || null;
    let menu: any = nodeMenu.MDCMenu || null;

    if (toggle && menu) {
      if (!closed) {
        menu.open = !menu.open;
        toggle.on = !!menu.open;
      } else {
        toggle.on = !!menu.open;
        menu.open = toggle.on;
      }
    }
  }

  trackByFn(index: any, item: any): any {
    return index;
  }

  setSettingMenu(event: CustomEvent): void {
    const target: HTMLElement | null = event.target as HTMLElement | null;
    const menu: any = event.detail.component;
    menu.setAnchorCorner(MDC.menu.MDCMenuFoundation.Corner.BOTTOM_START);
    menu.rememberSelection = false;
    menu.quickOpen = false;
  }

  booleanConverter(some: any): boolean {
    try {
      return !!some;
    } catch (e) {
      return false;
    }
  }

  selectedSort(i: number): boolean {
    return (this.availableTrackSort && i <= this.availableTrackSort.length - 1 && this.availableTrackSort[i].id === this.sort);
  }

  private createForm(): void {
    this.form = this.fb.group({
      sort: this.fb.control(this.sort)
    });

    this.form.valueChanges.distinctUntilChanged().debounceTime(500).subscribe((value: any): void => {
      if (this.form.valid && this.form.enabled) {
        this.apply();
      }
    });
  }

  private applyArgs(): void {
    const fields: any = (this.form && this.form.value) || null;
    let sortField: number = 1;
    if (this.filterType === 'discover') {
        sortField = (_has(fields, 'sort')) ? fields.sort : _head(this.availableDiscoverSort).id;
    } else if (this.filterType === 'track') {
        sortField = (_has(fields, 'sort')) ? fields.sort : _head(this.availableTrackSort).id;
    } else if (this.filterType === 'ended') {
      sortField = (_has(fields, 'sort')) ? fields.sort : _head(this.availableTrackSort).id;
    }
    this.filterService.sort = sortField;
  }
}

applyMixins(KnkSearchSortComponent, [Log]);
