import {Component, inject, OnDestroy, ChangeDetectionStrategy} from '@angular/core';
import {ActivatedRoute, Params, Router} from '@angular/router';
import {Store} from '@ngrx/store';
import {Throbber} from 'org_xprof/frontend/app/common/classes/throbber';
import {ChartDataInfo} from 'org_xprof/frontend/app/common/interfaces/chart';
import {SimpleDataTable} from 'org_xprof/frontend/app/common/interfaces/data_table';
import {Diagnostics} from 'org_xprof/frontend/app/common/interfaces/diagnostics';
import {HostMetadata} from 'org_xprof/frontend/app/common/interfaces/hosts';
import {parseDiagnosticsDataTable, setLoadingState} from 'org_xprof/frontend/app/common/utils/utils';
import {TABLE_OPTIONS} from 'org_xprof/frontend/app/components/chart/chart_options';
import {Dashboard} from 'org_xprof/frontend/app/components/chart/dashboard/dashboard';
import {DefaultDataProvider} from 'org_xprof/frontend/app/components/chart/default_data_provider';
import {DATA_SERVICE_INTERFACE_TOKEN, DataServiceV2Interface} from 'org_xprof/frontend/app/services/data_service_v2/data_service_v2_interface';
import {setCurrentToolStateAction, } from 'org_xprof/frontend/app/store/actions';
import {getHostsState} from 'org_xprof/frontend/app/store/selectors';
import {combineLatest, ReplaySubject} from 'rxjs';
import {takeUntil} from 'rxjs/operators';

const MEGASCALE_STATS_INDEX = 0;
const DIAGNOSTICS_INDEX = 1;

/** A Megascale Stats page component. */
@Component({
  changeDetection: ChangeDetectionStrategy.Default,standalone: false,
  selector: 'megascale-stats',
  templateUrl: './megascale_stats.ng.html',
  styleUrls: ['./megascale_stats.scss']
})
export class MegascaleStats extends Dashboard implements OnDestroy {
  tool = 'megascale_stats';
  /** Handles on-destroy Subject, used to unsubscribe. */
  private readonly destroyed = new ReplaySubject<void>(1);
  private readonly throbber = new Throbber(this.tool);
  private readonly dataService: DataServiceV2Interface =
      inject(DATA_SERVICE_INTERFACE_TOKEN);

  sessionId = '';
  host = '';
  hostList: string[] = [];

  diagnostics: Diagnostics = {info: [], warnings: [], errors: []};

  isExpanded = false;

  dataInfo: ChartDataInfo = {
    data: null,
    dataProvider: new DefaultDataProvider(),
    filters: [],
    options: {
      ...TABLE_OPTIONS,
      showRowNumber: false,
    },
  };

  constructor(
      route: ActivatedRoute,
      private readonly store: Store<{}>,
      private readonly router: Router,
  ) {
    super();
    combineLatest([route.params, route.queryParams])
        .pipe(takeUntil(this.destroyed))
        .subscribe(([params, queryParams]) => {
          this.sessionId = params['sessionId'] || this.sessionId;
          this.processQueryParams(queryParams);
          this.update();
        });
    this.store.dispatch(setCurrentToolStateAction({currentTool: this.tool}));
    this.store
      .select(getHostsState)
      .pipe(takeUntil(this.destroyed))
      .subscribe((hostsmetadata: HostMetadata[]) => {
        if (!hostsmetadata || hostsmetadata.length === 0) return;
        this.hostList = hostsmetadata.map((host) => host.hostname);

        if (!this.host && this.hostList.length > 0) {
          this.host =
            hostsmetadata.find(
              (hostMetadata) => hostMetadata.hasDeviceTrace,
            )?.hostname || this.hostList[0];
          this.update();
        }
      });
  }

  processQueryParams(params: Params) {
    this.sessionId = params['run'] || params['sessionId'] || this.sessionId;
    this.tool = params['tag'] || this.tool;
    this.host = params['host'] || this.host;
  }

  update() {
    if (!this.isExpanded) {
      return;
    }

    setLoadingState(true, this.store, 'Loading Megascale Stats data');

    this.throbber.start();

    this.dataService.getData(this.sessionId, this.tool, this.host)
        .pipe(takeUntil(this.destroyed))
        .subscribe((data) => {
          this.throbber.stop();
          setLoadingState(false, this.store);

          if (data) {
            const d = data as SimpleDataTable[] | null;
            if (d) {
              if (d.hasOwnProperty(DIAGNOSTICS_INDEX)) {
                this.diagnostics = parseDiagnosticsDataTable(
                    d[DIAGNOSTICS_INDEX],
                );
              }
              if (d.hasOwnProperty(MEGASCALE_STATS_INDEX)) {
                this.parseData(d[MEGASCALE_STATS_INDEX]);
                this.dataInfo = {
                  ...this.dataInfo,
                  data: d[MEGASCALE_STATS_INDEX],
                };
              }
            }
          }
        });
  }

  override updateView() {
    this.dataInfo = {
      ...this.dataInfo,
      filters: this.getFilters(),
    };
  }

  onPanelOpened() {
    this.isExpanded = true;
    this.update();
  }

  onPanelClosed() {
    this.isExpanded = false;
  }

  openPerfetto() {
    const searchParams = this.dataService.getSearchParams();
    const queryParams: Params = {};
    searchParams.forEach((value, key) => {
      queryParams[key] = value;
    });

    if (this.host) {
      queryParams['host'] = this.host;
    }

    this.router.navigate(['/megascale_perfetto', this.sessionId], {queryParams});
  }

  ngOnDestroy() {
    // Unsubscribes all pending subscriptions.
    this.destroyed.next();
    this.destroyed.complete();
  }
}
