import { Http, RequestOptions, Response } from '@angular/http';

import { Injectable } from '@angular/core';
import { Observable } from 'rxjs/Observable';
import { Subject } from 'rxjs/Subject';
import { ReplaySubject } from 'rxjs/ReplaySubject';

import 'rxjs/add/observable/of';
import 'rxjs/add/observable/throw';

import 'rxjs/add/operator/catch';
import 'rxjs/add/operator/map';
import 'rxjs/add/operator/mergeMap';

import { IFilter, FilterParams, ILoseKnokItems, IRankItems } from './filter.model';
import { IKnokFeedArgs, IKnokOngoingArgs } from '../knok';

import { TokenService } from '../token/token.service';
import { IApiError, IApiResponseError, IApiResponseSuccess, isApiResponseError } from '../token/apiresponse.model';

@Injectable()
export class FilterService {
  private subjectKnKFeedArgs = new Subject<IKnokFeedArgs | IKnokOngoingArgs>();
  private subjectKnKFeedArgsRefresh = new Subject<boolean>();
  private currentFilterType = new ReplaySubject<string>(1);
  private ongoingTotal = new Subject<{currentProfit: number, potentialProfit: number, knoksCount: number}>();
  private userIsKnokserProp = new ReplaySubject<boolean>(1);
  private sortProp = new Subject<number>();

  constructor(private http: Http, private tokenService: TokenService) {
  }

  get feedArgsObservable(): Observable<IKnokFeedArgs | IKnokOngoingArgs> {
    return this.subjectKnKFeedArgs.asObservable();
  }

  set feedArgs(dict: IKnokFeedArgs | IKnokOngoingArgs | null) {
    if (dict) {
      this.subjectKnKFeedArgs.next(dict);
    } else {
      this.subjectKnKFeedArgs.next();
    }
  }

  set totals(totals: {currentProfit: number, potentialProfit: number, knoksCount: number} | null) {
    if (totals) {
      this.ongoingTotal.next(totals);
    } else {
      this.ongoingTotal.next();
    }
  }

  set userIsKnokser(value: boolean) {
    this.userIsKnokserProp.next(Boolean(value));
  }

  set sort(value: number) {
    if (value !== null) {
      this.sortProp.next(value);
    } else {
      this.sortProp.next();
    }
  }

  set filterType(filterType: string | null) {
    if (filterType) {
      this.currentFilterType.next(filterType);
    } else {
      this.currentFilterType.next('');
    }
  }

  get feedArgsRefreshObservable(): Observable<boolean> {
    return this.subjectKnKFeedArgsRefresh.asObservable();
  }

  get ongoingTotalObservable(): Observable<{currentProfit: number, potentialProfit: number, knoksCount: number}> {
    return this.ongoingTotal.asObservable();
  }

  get userIsKnokserObservable(): Observable<boolean> {
    return this.userIsKnokserProp.asObservable();
  }

  get sortObservable(): Observable<number> {
    return this.sortProp.asObservable();
  }

  get filterTypeObservable(): Observable<string> {
    return this.currentFilterType.asObservable();
  }

  set feedArgsRefresh(reset: boolean) {
    this.subjectKnKFeedArgsRefresh.next(Boolean(reset));
  }

  get filterSettings(): Observable<IFilter> {
    return this.http
      .get(`${SETTINGS.API_URL}/general/userrankcount`,
        new RequestOptions({headers: this.tokenService.authorizationHeaders}))
      .map((response: Response) => {
        const data: IApiResponseError | IApiResponseSuccess<IRankItems> = response.json();
        if (isApiResponseError(data)) {
          return Observable.throw(data.error);
        }
        let res: FilterParams = new FilterParams();
        data.result.items.forEach((item) => {
          res.knoksTotal += item.count;
          switch (item.rank) {
            case 0:
              res.knokserPadawan = item.count;
              break;
            case 1:
              res.knokserRanger = item.count;
              break;
            case 2:
              res.knokserAdept = item.count;
              break;
            case 3:
              res.knokserMaster = item.count;
              break;
            case 4:
              res.knokserJedi = item.count;
              break;
            default:
              break;
          }
        });

        return res;
      })
      .map((config: IFilter) => {
        return config;
      }).catch(this.handleError);
  }

  get filterEndedKnoksSettings(): Observable<IFilter> {
    return this.http
      .get(`${SETTINGS.API_URL}/general/knokslosscount`,
        new RequestOptions({headers: this.tokenService.authorizationHeaders}))
      .map((response: Response) => {
        const data: IApiResponseError | IApiResponseSuccess<ILoseKnokItems> = response.json();
        if (isApiResponseError(data)) {
          return Observable.throw(data.error);
        }
        let res: FilterParams = new FilterParams();
        data.result.items.forEach((item) => {
          res.knoksTotal += item.count;
          switch (item.id) {
            case 1:
              res.exitPriceMissed = item.count;
              break;
            case 2:
              res.stopLossReached = item.count;
              break;
            case 3:
              res.closedByKnokser = item.count;
              break;
            default:
              break;
          }
        });

        return res;
      })
      .map((config: IFilter) => {
        return config;
      }).catch(this.handleError);
  }

  private handleError(error: IApiError): Observable<IFilter> {
    return Observable.throw(error.msg || error);
  }
}
