import { AfterViewInit, Component, ElementRef, OnInit, ViewChild } from '@angular/core';
import { Package } from '../../api/models/package';
import { PkgdashService } from '../../api/services/pkgdash.service';
import { debounceTime, distinctUntilChanged, fromEvent, merge, Observable, of, tap } from 'rxjs';
import { MatPaginator } from '@angular/material/paginator';
import { PackagesService } from '../../services/packages/packages.service';
import { PackagesDataSource } from '../../datasources/packages';
import { MatSort, Sort, SortDirection } from '@angular/material/sort';
import { Router } from '@angular/router';
import { ConfirmService } from 'src/app/services/confirm/confirm.service';
import { AppConstants } from 'src/app/app.constants';
import { MessageService } from 'src/app/services/message/message.service';
import { ErrorRsp, PackageCreateRsp, PackageDeleteRsp, PackageUpdateRsp } from 'src/app/api/models';


@Component({
  selector: 'app-packages',
  templateUrl: './package-list.component.html',
  styleUrls: ['./package-list.component.scss'],
  providers: [PkgdashService, MessageService]
})

export class PackageListComponent implements OnInit, AfterViewInit {
  @ViewChild(MatPaginator) paginator!: MatPaginator;
  @ViewChild(MatSort) sort!: MatSort;
  @ViewChild('input') input!: ElementRef;

  selectedPackage?: Package;

  dataSource: PackagesDataSource;
  selectedRowIndex: any;

  packages$!: Observable<any>;

  public itemsCount = 20;
  sortField = 'name';
  sortOrder: SortDirection = 'asc';

  displayedColumns: string[] = ['name', 'modules', 'issues', 'comments', 'coverage', 'handlers', 'actions'];

  constructor(
    private router: Router,
    private packageDialog: PackagesService,
    private pkgdashService: PkgdashService,
    private confirmDialog: ConfirmService,
    private messageService: MessageService,
  ) {
    this.dataSource = new PackagesDataSource(this.pkgdashService);
  }

  createPackageDialog(): void {
    this.packageDialog.open({
      height: '400px',
      width: '600px',
      autoFocus: true,
      disableClose: false,
      backdropClass: "package-dialog",
      data: {
        title: 'Create package'
      }
    });

    this.packageDialog.confirmed().subscribe((data: any) => {
      if (data) {
        this.pkgdashService.packageCreate(data)
          .subscribe({
            next: (rsp: PackageCreateRsp) => {
              this.loadPackages();
              this.reloadComponent();
              this.messageService.showMessage("package " + rsp.package!.name + " created")
            },
            error: (err: ErrorRsp) => {
              this.messageService.showMessage("package " + data.name + " not created, error " + err.details)
            }
          });
      }
    });
  }

  updatePackageDialog(pkg: Package): void {
    this.packageDialog.open({
      height: '400px',
      width: '600px',
      autoFocus: true,
      disableClose: false,
      backdropClass: "package-dialog",
      data: {
        pkg: pkg,
        title: 'Update package ' + pkg.name,
      }
    });

    this.packageDialog.confirmed().subscribe((data: any) => {
      if (data) {
        this.pkgdashService.packageUpdate({
          id: pkg.id!,
          body: data,
        }).subscribe({
          next: (rsp: PackageUpdateRsp) => {
            this.loadPackages();
            this.reloadComponent();
            this.messageService.showMessage("package " + data.name + " updated")
          },
          error: (err: ErrorRsp) => {
            this.messageService.showMessage("package " + data.name + " not updated, error " + err.details)
          }
        })
      }
    });
  }

  deletePackageDialog(pkg: Package): void {
    this.confirmDialog.open({
      height: '200px',
      width: '300px',
      autoFocus: true,
      disableClose: false,
      backdropClass: "package-dialog",
      data: {
        title: 'Delete package ' + pkg.name,
        message: 'Are you sure?',
      }
    });

    this.confirmDialog.confirmed().subscribe((data: any) => {
      if (data) {
        this.pkgdashService.packageDelete({
          id: pkg.id!,
        }).subscribe({
          next: (rsp: PackageDeleteRsp) => {
            this.loadPackages();
            this.reloadComponent();
            this.messageService.showMessage("package " + data.name + " deleted")
          },
          error: (err: ErrorRsp) => {
            this.messageService.showMessage("package " + data.name + " not deleted, error " + err.details)
          }
        })
      }
    })
  }

  selectPackage(pkg: Package): void {
    this.selectedPackage = pkg;
  }

  ngAfterViewInit() {

    fromEvent(this.input.nativeElement, 'keyup')
      .pipe(
        debounceTime(AppConstants.SEARCH_DEBOUNCE),
        distinctUntilChanged(),
        tap(() => {
          this.paginator.pageIndex = 0;
          this.loadPackages();
        })
      )
      .subscribe();

    this.sort.sortChange.subscribe(() => this.paginator.pageIndex = 0);

    merge(this.sort.sortChange, this.paginator.page)
      .pipe(
        tap(() => this.loadPackages())
      )
      .subscribe();
  }

  public sortPackages(event: Sort): void {
    this.loadPackages()
    this.reloadComponent()
  }

  private reloadComponent(): void {
    let currentUrl = this.router.url;
    this.router.routeReuseStrategy.shouldReuseRoute = () => false;
    this.router.onSameUrlNavigation = 'reload';
    this.router.navigate([currentUrl]);
  }

  private loadPackages(): void {
    this.dataSource.list(
      this.input.nativeElement.value,
      this.sort.active,
      this.sort.direction,
      this.paginator.pageIndex,
      this.paginator.pageSize);
  }

  ngOnInit(): void {
    this.dataSource.list('', this.sortField, this.sortOrder, 0, this.itemsCount);
    this.packages$ = this.dataSource.connect();
  }
}
