import { Component, OnInit } from '@angular/core';
import { AccountService } from 'src/app/shared/server-services/account.service';
import { UserRole } from 'src/app/shared/server-services/query-records/account-records';
import { aggregateStats, nanoMetricsQuery } from 'src/app/shared/server-services/querys';
import { ServerRestApiService } from 'src/app/shared/services/server-rest-api.service';
import { sideMenuActiveObserver } from 'src/app/shared/shared-observers';

export type AggregateStatsRecord = {
  accounts: number;
  accountsUpdated: number;
  nanoMetricsUpdated: number;
  nanoMetrics: {
    year: number;
    month: number;
    requestBytes: number;
    responseBytes: number;
    cacheBytes: number;
    requestColumnHeight: number;
    responseColumnHeight: number;
    cacheColumnHeight: number;
    sumColumnHeight: number;
  }[];
};

export type StatsRecord = {
  year: number;
  month: number;
  /**
   * Msg to the nano
   * nano download
   * client upload
   */
  requestBytes: number;
  /**
   * Nano response
   * nano upload
   * client download
   */
  responseBytes: number;
  /**
   * Server response instead of nano (file)
   * nano do nothing
   * client download
   */
  cacheBytes: number;
  requestColumnHeight: number;
  responseColumnHeight: number;
  cacheColumnHeight: number;
  sumColumnHeight: number;
};

// export type AggregateStats = {
//   accounts: number;
//   accountsUpdated: number;
//   nanoMetricsUpdated: number;
//   nanoMetrics: {
//     year: number;
//     month: number;
//     requestBytes: number;
//     responseBytes: number;
//     cacheBytes: number;
//   }[];
// }

@Component({
  selector: 'app-aggregate-stats',
  templateUrl: './aggregate-stats.component.html',
  styleUrls: ['./aggregate-stats.component.scss'],
})
export class AggregateStatsComponent implements OnInit {
  public adminStats: AggregateStatsRecord;
  public stats: StatsRecord[];

  public isAdmin: boolean = false;
  public loadingData: boolean = true;
  public showAggregateStats: boolean = false;

  constructor(
    private serverRestApiService: ServerRestApiService,
    private accountService: AccountService
  ) {
    Promise.all([this.accountService.getMe(), this.getMetrics()]).then(([me, metrics]) => {
      this.isAdmin = this.accountService.isCurrentUserInRole(UserRole.ADMIN, me);

      this.stats = metrics;
      this.processMetrics(metrics);

      this.loadingData = false;
    });
  }

  ngOnInit(): void {
    sideMenuActiveObserver.next(false);
  }

  public displayAggregateStats(show: boolean): void {
    if (show && !this.adminStats) {
      this.loadingData = true;
      this.serverRestApiService
        .query({
          query: aggregateStats,
        })
        .then((response: AggregateStatsRecord) => {
          this.adminStats = response;

          this.processMetrics(this.adminStats.nanoMetrics);
          this.showAggregateStats = true;
          this.loadingData = false;
        });
    } else {
      this.showAggregateStats = show;
    }
  }

  private processMetrics(metrics: StatsRecord[]): void {
    metrics.sort((a, b) => {
      if (a.year == b.year) return b.month - a.month;
      else return b.year - a.year;
    });

    var maxUpload = Math.max(
      ...metrics.map((m) => m.responseBytes + m.cacheBytes),
      ...metrics.map((m) => m.requestBytes)
    );

    for (let stat of metrics) {
      var maxOnePercent = maxUpload / 100;
      stat.requestColumnHeight = Math.max(Math.round(stat.requestBytes / maxOnePercent), 0.5);
      stat.responseColumnHeight = Math.max(Math.round(stat.responseBytes / maxOnePercent), 0.5);
      stat.cacheColumnHeight = Math.max(
        Math.round(stat.cacheBytes / ((stat.responseBytes + stat.cacheBytes) / 100)),
        0.5
      );
      stat.sumColumnHeight = Math.max(
        Math.round((stat.responseBytes + stat.cacheBytes) / maxOnePercent),
        0.5
      );
    }
  }

  private getMetrics(): Promise<StatsRecord[]> {
    return this.serverRestApiService.query({ query: nanoMetricsQuery });
  }
}
