import { Injectable } from "@angular/core";
import { HttpClient } from "@angular/common/http";
import { Observable } from "rxjs";
import { map } from "rxjs/operators";

import {
  StatsByDzResp,
  StatsByAircraftResp,
  StatsByJumpTypeResp,
  StatsByGearResp,
  StatsByYearResp,
  StatsByYearByJumpTypeResp,
  StatsForLastMonthResp,
  StatsForLastYearResp,
  SimpleSummary,
  SimpleSummaryResp,
} from "../models/stats";

import { BaseService } from "./base.service";
import { DropzoneService } from "./dropzone.service";
import { AircraftService } from "./aircraft.service";
import { JumpTypeService } from "./jump-type.service";
import { GearService } from "./gear.service";
import { CacheApiKey } from "../models/cache-api-key.enum";
import { Jump } from "../models/jump";

@Injectable()
export class StatsService extends BaseService {
  constructor(
    private http: HttpClient,
    private dropzoneService: DropzoneService,
    private aircraftService: AircraftService,
    private jumpTypeService: JumpTypeService,
    private gearService: GearService
  ) {
    super();
  }

  public deleteAllCache() {
    this.serviceCacheApi.delete(CacheApiKey.SimpleSummary);
    this.serviceCacheApi.delete(CacheApiKey.StatsByDz);
    this.serviceCacheApi.delete(CacheApiKey.StatsByAircraft);
    this.serviceCacheApi.delete(CacheApiKey.StatsByJumpType);
    this.serviceCacheApi.delete(CacheApiKey.StatsByGear);
    this.serviceCacheApi.delete(CacheApiKey.StatsByYear);
    this.serviceCacheApi.delete(CacheApiKey.StatsOfLastYear);
    this.serviceCacheApi.delete(CacheApiKey.StatsOfLastMonth);
    this.serviceCacheApi.delete(CacheApiKey.StatsByYearByJumpType);
  }

  public resetStats() {
    this.http
      .get(`${this.apiUrl}/Stats/Reset`, { headers: this.headers })
      .subscribe();
  }

  public getSimpleSummary(): Observable<SimpleSummary> {
    let callToApi = this.http
      .get<SimpleSummaryResp>(`${this.apiUrl}/Stats/Simple`, {
        headers: this.headers,
      })
      .pipe(
        map((response) => {
          let tmp = new Jump(response.lastJump);
          this.dropzoneService
            .getById(response.lastJump.dropZoneId)
            .subscribe((d) => (tmp.dropZone = d));
          this.aircraftService
            .getById(response.lastJump.aircraftId)
            .subscribe((d) => (tmp.aircraft = d));
          this.jumpTypeService
            .getById(response.lastJump.jumpTypeId)
            .subscribe((d) => (tmp.jumpType = d));
          this.gearService
            .getById(response.lastJump.gearId)
            .subscribe((d) => (tmp.gear = d));

          let stats = new SimpleSummary(response);
          stats.lastJump = tmp;
          return stats;
        })
      );

    return this.serviceCacheApi.get<SimpleSummary>(
      CacheApiKey.SimpleSummary,
      callToApi
    );
  }

  public getStatsByDz(): Observable<Array<StatsByDzResp>> {
    let callToApi = this.http
      .get<Array<StatsByDzResp>>(`${this.apiUrl}/Stats/ByDz`, {
        headers: this.headers,
      })
      .pipe(
        map((response) => {
          const stats = response.map((data) => new StatsByDzResp(data));
          return stats;
        })
      );

    return this.serviceCacheApi.get<Array<StatsByDzResp>>(
      CacheApiKey.StatsByDz,
      callToApi
    );
  }

  public getStatsByAircraft(): Observable<Array<StatsByAircraftResp>> {
    let callToApi = this.http
      .get<Array<StatsByAircraftResp>>(`${this.apiUrl}/Stats/ByAircraft`, {
        headers: this.headers,
      })
      .pipe(
        map((response) => {
          const stats = response.map((data) => new StatsByAircraftResp(data));
          return stats;
        })
      );

    return this.serviceCacheApi.get<Array<StatsByAircraftResp>>(
      CacheApiKey.StatsByAircraft,
      callToApi
    );
  }

  public getStatsByJumpType(): Observable<Array<StatsByJumpTypeResp>> {
    let callToApi = this.http
      .get<Array<StatsByJumpTypeResp>>(`${this.apiUrl}/Stats/ByJumpType`, {
        headers: this.headers,
      })
      .pipe(
        map((response) => {
          const stats = response.map((data) => new StatsByJumpTypeResp(data));
          return stats;
        })
      );

    return this.serviceCacheApi.get<Array<StatsByJumpTypeResp>>(
      CacheApiKey.StatsByJumpType,
      callToApi
    );
  }

  public getStatsByGear(): Observable<Array<StatsByGearResp>> {
    let callToApi = this.http
      .get<Array<StatsByGearResp>>(`${this.apiUrl}/Stats/ByGear`, {
        headers: this.headers,
      })
      .pipe(
        map((response) => {
          const stats = response.map((data) => new StatsByGearResp(data));
          return stats;
        })
      );

    return this.serviceCacheApi.get<Array<StatsByGearResp>>(
      CacheApiKey.StatsByGear,
      callToApi
    );
  }

  public getStatsByYear(): Observable<Array<StatsByYearResp>> {
    let callToApi = this.http
      .get<Array<StatsByYearResp>>(`${this.apiUrl}/Stats/ByYear`, {
        headers: this.headers,
      })
      .pipe(
        map((response) => {
          const stats = response.map((data) => new StatsByYearResp(data));
          return stats;
        })
      );

    return this.serviceCacheApi.get<Array<StatsByYearResp>>(
      CacheApiKey.StatsByYear,
      callToApi
    );
  }

  public getStatsOfLastYear(): Observable<StatsForLastYearResp> {
    let callToApi = this.http
      .get<StatsForLastYearResp>(`${this.apiUrl}/Stats/ForLastYear`, {
        headers: this.headers,
      })
      .pipe(
        map((response) => {
          const statsByDz = response.byDz.map(
            (data) => new StatsByDzResp(data)
          );
          const statsByJumpType = response.byJumpType.map(
            (data) => new StatsByDzResp(data)
          );

          return new StatsForLastYearResp(statsByDz, statsByJumpType);
        })
      );

    return this.serviceCacheApi.get<StatsForLastYearResp>(
      CacheApiKey.StatsOfLastYear,
      callToApi
    );
  }

  public getStatsOfLastMonth(): Observable<StatsForLastMonthResp> {
    let callToApi = this.http
      .get<StatsForLastYearResp>(`${this.apiUrl}/Stats/ForLastMonth`, {
        headers: this.headers,
      })
      .pipe(
        map((response) => {
          const statsByDz = response.byDz.map(
            (data) => new StatsByDzResp(data)
          );
          const statsByJumpType = response.byJumpType.map(
            (data) => new StatsByDzResp(data)
          );

          return new StatsForLastMonthResp(statsByDz, statsByJumpType);
        })
      );

    return this.serviceCacheApi.get<StatsForLastMonthResp>(
      CacheApiKey.StatsOfLastMonth,
      callToApi
    );
  }

  public getStatsByYearByJumpType(): Observable<
    Array<StatsByYearByJumpTypeResp>
  > {
    let callToApi = this.http
      .get<Array<StatsByYearByJumpTypeResp>>(
        `${this.apiUrl}/Stats/ByYearByJumpType`,
        {
          headers: this.headers,
        }
      )
      .pipe(
        map((response) => {
          const stats = response.map(
            (data) => new StatsByYearByJumpTypeResp(data)
          );
          return stats;
        })
      );

    return this.serviceCacheApi.get<Array<StatsByYearByJumpTypeResp>>(
      CacheApiKey.StatsByYearByJumpType,
      callToApi
    );
  }
}
