import {Component, OnInit, ViewChild} from '@angular/core';
import {BaseChartDirective, NgChartsModule} from 'ng2-charts';
import { HttpClient } from "@angular/common/http";
import {environment} from "../../environments/environment";
import {DecimalPipe, JsonPipe, NgForOf, NgIf, NgOptimizedImage} from "@angular/common";
import {ActivatedRoute, RouterLink} from "@angular/router";
import {catchError, throwError} from "rxjs";
import {ReplayData} from "../replays";
import {calculateAccuracy} from "../format";
import {Title} from "@angular/platform-browser";
import {OsuGradeComponent} from "../../corelib/components/osu-grade/osu-grade.component";
import {ChartComponent} from "../../corelib/components/chart/chart.component";
import {
  ChartHitDistributionComponent
} from "../../corelib/components/chart-hit-distribution/chart-hit-distribution.component";
import {CuteProgressbarComponent} from "../../corelib/components/cute-progressbar/cute-progressbar.component";

@Component({
  selector: 'app-view-score',
  standalone: true,
  imports: [
    NgChartsModule,
    JsonPipe,
    NgIf,
    DecimalPipe,
    NgForOf,
    NgOptimizedImage,
    RouterLink,
    OsuGradeComponent,
    ChartComponent,
    ChartHitDistributionComponent,
    CuteProgressbarComponent
  ],
  templateUrl: './view-score.component.html',
  styleUrl: './view-score.component.css'
})
export class ViewScoreComponent implements OnInit {

  @ViewChild(BaseChartDirective)
  public chart!: BaseChartDirective;

  isLoading = false;
  error: string | null = null;
  replayData: ReplayData | null = null;

  isUserScore: boolean = false;
  userReplayId: string | null = null;
  replayId: number | null = null;

  constructor(private http: HttpClient,
              private activatedRoute: ActivatedRoute,
              private title: Title
  ) {}

  hasErrorDistribution(): boolean {
    return !!this.replayData?.error_distribution && Object.keys(this.replayData.error_distribution).length > 0;
  }

  hasReplay(): boolean {
    if(this.isUserScore) {
      return false;
    }
    return this.hasErrorDistribution();
  }

  isWebScore(): boolean {
    return !!this.replayData && this.replayData.replay_id !== 0;
  }

  ngOnInit(): void {
    this.activatedRoute.params.subscribe(params => {
      this.replayId = params['replayId'];
      this.userReplayId = params['userReplayId'];
      if (this.replayId) {
        this.loadScoreData(`${environment.apiUrl}/score/${this.replayId}`);
      }
      if(this.userReplayId) {
        this.loadScoreData(`${environment.apiUrl}/user-score/${this.userReplayId}`);
        this.isUserScore = true;
      }
    });
  }

  /**
   * Prints the total_length (a positive integer) into a timer-like string (e.g. 3:45)
   * @param total_length
   */
  printTotalLength(total_length: number): string {
    let minutes = Math.floor(total_length / 60);
    let seconds = total_length % 60;
    return `${minutes}:${seconds.toString().padStart(2, '0')}`;
  }

  buildCircleguardUrl(): string {
    if(!this.replayData) {
      return "";
    }

    let url = "circleguard://m=" + this.replayData.beatmap_id + "&u=" + this.replayData.user_id;

    if (this.replayData.mods.length > 0) {
      url += "&m1=" + this.replayData.mods.join('');
    }

    return url;
  }

  private loadScoreData(url: string): void {
    this.isLoading = true;
    this.http.get<ReplayData>(url).pipe(
      catchError(error => {
        this.isLoading = false;
        return throwError(() => new Error('An error occurred with the request: ' + error.message));
      })
    ).subscribe({
      next: (response) => {
        this.isLoading = false;
        this.replayData = response;

        this.title.setTitle(
          `${this.replayData.username} on ${this.replayData.beatmap_title} (${this.replayData.beatmap_version})`
        )
      },
      error: (error) => {
        this.error = error;
      }
    });
  }


  protected readonly Object = Object;
  protected readonly calculateAccuracy = calculateAccuracy;

}
