import { FormGroup, FormControl } from '@angular/forms';
import { AttacksService } from './../attacks.service';
import { LayoutService } from './../../core/layout.service';
import { AttacksState, Sort } from './../store/attacks.redurecs';
import { Store } from '@ngrx/store';
import { Component, OnInit, OnDestroy } from '@angular/core';
import { AttacksFeatureState } from '../store/attacks.redurecs';
import { RequestAttacksListAction, UpdateSortAction, UpdateSearchAction } from '../store/attacks.actions';
import { Attack } from '../model/attack.model';
import { Observable, Subscription } from 'rxjs';
import * as moment from 'moment';
import { SoftTargetType } from 'src/app/core/model/soft-target-type';

@Component({
  selector: 'app-attacks-list',
  templateUrl: './attacks-list.component.html',
  styleUrls: ['./attacks-list.component.scss']
})
export class AttacksListComponent implements OnInit, OnDestroy {

  public attacks: Attack[];
  
  private controlForm: FormGroup = this.initControlForm();

  private isWebView: Observable<Boolean> = this.layoutService.isWebView;
  
  private storeSubscription: Subscription;

  constructor(private store: Store<AttacksFeatureState>, private attacksService: AttacksService, private layoutService: LayoutService) {
    this.storeSubscription = this.store.select('attacks').subscribe(
      (state: AttacksState) => {
        if (state.attacks !== null){
          this.controlForm = this.initControlForm(state.search, state.sort);
          let attacks: Attack[] = state.attacks;
          
          let searchBy = <string>state.search;
          if (searchBy)
            attacks = this.search(attacks, searchBy);

          let sortBy = <string>state.sort.by;
          if (sortBy)
            attacks = this.sort(attacks, sortBy);
          
            if (state.sort.reverse){
            attacks = attacks.reverse();
          }

          this.attacks = attacks;
        }
      }
    );
    this.store.dispatch(new RequestAttacksListAction());
  }

  ngOnInit() {
  }

  ngOnDestroy() {
    this.storeSubscription.unsubscribe();
  }

  private onSort(sortBy: String){
    let reverse = this.controlForm.get('reverse');
    this.store.dispatch(new UpdateSortAction(sortBy, reverse.value));

  }

  private onSearch(searchBy: String){
    this.store.dispatch(new UpdateSearchAction(searchBy));
  }

  private sort(attacks: Attack[], sortBy: string){
    return attacks.sort((attack1: Attack, attack2: Attack) => {
      switch(sortBy){
        case "date":
          let d1 = moment(<string>attack1.date, 'D.M.YYYY');
          let d2 = moment(<string>attack2.date, 'D.M.YYYY');
          return d1.isAfter(d2) ? 1 : d1.isBefore(d2) ? -1 : 0;
        case "time":
          let t1 = moment(<string>attack1.time, 'HH:mm');
          let t2 = moment(<string>attack2.time, 'HH:mm');
          return t1.isAfter(t2) ? 1 : t1.isBefore(t2) ? -1 : 0;
        case "modusOperandi":
        case "epicenter":
          let l1 = attack1[sortBy] ? attack1[sortBy].label : null;
          let l2 = attack2[sortBy] ? attack2[sortBy].label : null;
          return l1 > l2 ? 1 :l1 < l2 ? -1 : 0;
        case "numberOfAttackers":
          return attack1.attackers.length > attack2.attackers.length ? 1 : attack1.attackers.length < attack2.attackers.length ? -1 : 0;
        default:
          return attack1[sortBy] > attack2[sortBy] ? 1 : attack1[sortBy] < attack2[sortBy] ? -1 : 0;
      }
    });
  }

  private reverseSort(){
    let reverseControl = this.controlForm.get('reverse');
    let sortBy = this.controlForm.get('sortBy');
    this.store.dispatch(new UpdateSortAction(sortBy.value, !reverseControl.value));
  }

  private search(attacks: Attack[], searchBy: string){
      let inputValues: String[] = searchBy.split(",");
      inputValues = inputValues.map(inputValue => inputValue.trim().toLocaleLowerCase());
      return attacks.filter((attack: Attack) => {
        return inputValues.every((inputValue: string) => { 
          return (
          attack.city.toLocaleLowerCase().includes(inputValue) ||
          attack.country.toLocaleLowerCase().includes(inputValue) ||
          attack.date.toLocaleLowerCase().includes(inputValue) ||
          (attack.time ? attack.time.toLocaleLowerCase().includes(inputValue) : false) ||
          (attack.softTargetTypes && attack.softTargetTypes.length > 0 ? (attack.softTargetTypes.findIndex((softTargetType: SoftTargetType) => softTargetType.softTargetType.label.toLocaleLowerCase().includes(inputValue)) > -1 ? true : false ): false) ||
          (attack.terroristOrganization ? attack.terroristOrganization.toLocaleLowerCase().includes(inputValue) : false) ||
          (attack.modusOperandi ? attack.modusOperandi.label.toLocaleLowerCase().includes(inputValue) : false)
          )
        })
      });
  }

  private onClearSearch(){
    let searchControl = this.controlForm.get('searchBy');
    searchControl.setValue(null);
    this.store.dispatch(new UpdateSearchAction(null));
  }

  private onDeleteAttack(attackId: number){
    this.attacksService.deleteAttackRecord(attackId);
  }

  private attackLabelById(attackId: number){
    let attack: Attack = this.attacks.find((attack: Attack) => { return attack.id === attackId });
    return attack ? attack.city + ", " + attack.country + ", " + attack.date : '#'+attackId;
  }

  private onExportClick(){
    this.attacksService.exportAttacks(this.attacks.map((attack: Attack) => attack.id));
  }

  private initControlForm(searchBy?: String, sort?: Sort){
    let controls = {
      'sortBy': new FormControl(sort ? sort.by : null),
      'reverse': new FormControl(sort ? sort.reverse : null),
      'searchBy': new FormControl(searchBy ? searchBy : null)
    }
    return new FormGroup(controls);
  }
}