import { Component, OnInit,
    ChangeDetectorRef, ChangeDetectionStrategy, ViewChild } from '@angular/core'
import { ActivatedRoute } from '@angular/router'
import { UntypedFormGroup, UntypedFormControl } from '@angular/forms'

import { MatTableDataSource } from '@angular/material/table'
import { MatSnackBar } from '@angular/material/snack-bar'
import { MatSort } from '@angular/material/sort'
import { MatPaginator } from '@angular/material/paginator'
import { MatDialog } from '@angular/material/dialog'

import { GisafAdminCategoryDialogComponent } from './dialog.component'
import { AdminManageDataService } from '../data.service'
import { AuthenticationService } from '../../../_services/authentication.service'
import { CategoryField, categoryFields } from './fields'
import { CategoryRead } from '../../../openapi'

@Component({
    selector: 'gisaf-admin-category',
    templateUrl: './category.component.html',
    styleUrls: ['./category.component.css'],
    changeDetection: ChangeDetectionStrategy.OnPush,
})
export class CategoryComponent implements OnInit {
    edit_roles = ['category manager']
    categories: CategoryRead[] = []
    fields: string[] = categoryFields.map(f=>f.name)
    actions: string[] = [
        'edit',
        'delete'
    ]
    columns: string[]
    dataSource: MatTableDataSource<object>
    @ViewChild(MatSort, {static: true}) sort: MatSort
    @ViewChild(MatPaginator, {static: true}) paginator: MatPaginator
    unlockDeleteFormGroup: UntypedFormGroup = new UntypedFormGroup({})
    filterText: string

    constructor(
        private cdr: ChangeDetectorRef,
        private route: ActivatedRoute,
        private snackBar: MatSnackBar,
        private adminManageDataService: AdminManageDataService,
        public authenticationService: AuthenticationService,
        public dialog: MatDialog,
    ) {}

    ngOnInit() {
        this.route.data.subscribe(
            data => {
                this.categories = data['categories']
                this.dataSource = new MatTableDataSource(this.categories)
                this.dataSource.sort = this.sort
                this.dataSource.paginator = this.paginator
                this.cdr.markForCheck()
            }
        )
        this.unlockDeleteFormGroup = new UntypedFormGroup({
            'canDelete': new UntypedFormControl(),
        })
        this.columns = categoryFields.filter(f=>f.inTable).map(f=>f.name)
        this.authenticationService.isAuthorized(this.edit_roles).subscribe(
            isAuthorized => {
                if (isAuthorized) {
                    this.columns = this.columns.concat(this.actions)
                }
            }
        )
    }

    applyFilter() {
        this.dataSource.filter = this.filterText.trim().toLowerCase();
    }

    editItem(data?: CategoryRead) {
        const dialogRef = this.dialog.open(GisafAdminCategoryDialogComponent, {
            width: '75%',
            data: {
                'category': data
            }
        })
        dialogRef.afterClosed().subscribe(
            (category: CategoryRead) => category &&
                this.adminManageDataService.saveCategory(
                    category
                ).subscribe({
                    next: (result: object) => {
                        let _mode: string = result['_mode']
                        if (_mode == 'updated') {
                            let row = this.dataSource.data.findIndex(c=>c['name'] == category.name)
                            this.dataSource.data[row] = category
                        }
                        else {
                            this.dataSource.data.push(category as CategoryRead)
                        }
                        let msg = 'Category ' + category.name + ' ' + result['_mode']
                        if (result['message']) {
                            msg += result['message']
                        }
                        this.snackBar.open(msg, 'Close')
                        this.dataSource.data = this.dataSource.data
                        this.cdr.markForCheck()
                    },
                    error: err => {
                        // Popup the dialog again, the error is catched by Apollo
                        console.error(err)
                        this.editItem(category)
                    }
                })
        )
    }

    deleteItem(category: CategoryRead) {
        this.adminManageDataService.deleteCategory(category).subscribe({
            next: (message: string) => {
                this.snackBar.open(message, 'Close')
                // Remove from table
                let dsi = this.dataSource.data.findIndex(fi => fi['name'] == category.name)
                this.dataSource.data.splice(dsi, 1)
                // Force Angular change detection (??)
                this.dataSource.data = this.dataSource.data
                this.cdr.markForCheck()
            },
            error: err => {
                this.snackBar.open(err, 'Close')
            }
        })
    }

    updateRegistry() {
        this.adminManageDataService.updateRegistry().subscribe(
            resp => {
                this.snackBar.open(
                    'Success: tables created, registry updated, other Gisaf processes notified',
                    'Close',
                    {duration: 3000}
                )
            }
        )
    }
}
