import { E, I } from '@angular/cdk/keycodes';
import { Location } from '@angular/common';
import { Component, OnInit, ChangeDetectionStrategy, ChangeDetectorRef } from '@angular/core';
import { FormArray, FormBuilder, Validators } from '@angular/forms';
import { MatDialog, MatDialogRef } from '@angular/material/dialog';
import { ActivatedRoute, Router } from '@angular/router';
import { of, Subject, throwError } from 'rxjs';
import { tap } from 'rxjs/internal/operators/tap';
import { catchError, concatMap, debounceTime, filter } from 'rxjs/operators';
import { BaseForm } from 'src/app/core/base/base-form';
import { SubjectsService } from 'src/app/core/service/settings/subjects.service';
import { SweetalertService } from 'src/app/core/service/sweetalert/sweetalert';
import { GradingService } from 'src/app/core/service/testing-information/grading.service';
import { TestingInformationService } from 'src/app/core/service/testing-information/testing-information.service';
import { GradeDialogComponent } from '../../grade-dialog/grade-dialog.component';

@Component({
  selector: 'app-grade-summary',
  templateUrl: './grade-summary.component.html',
  styleUrls: ['./grade-summary.component.scss'],
  changeDetection: ChangeDetectionStrategy.OnPush
})
export class GradeSummaryComponent extends BaseForm implements OnInit {
  subject;
  oldData;
  testingInformationUid;
  testingInformationData;
  subjectUid;
  constructor(
    public router: Router,
    public fb: FormBuilder,
    public activeRoute: ActivatedRoute,
    public location: Location,
    private subjectSV: SubjectsService,
    private cdr: ChangeDetectorRef,
    private gradingSV: GradingService,
    private swSV: SweetalertService,
    private dialog: MatDialog,
    private testingInformationSV: TestingInformationService
  ) {
    super(router,activeRoute,fb,location)
   }

  ngOnInit(): void {
    this.subjectSV.get(this.id).pipe(
      tap(x => this.subject = x),
      tap(x => this.form.get('subject_uid').setValue(this.subject.subject_uid)),
      tap(x => this.cdr.detectChanges())
    ).subscribe()
    this.activeRoute.params.pipe(
      tap(x => this.form.get('testing_information_uid').setValue(x.uid)),
      tap(x => this.testingInformationUid = x.uid),
      tap(x => this.subjectUid = x.id),
      concatMap((x:any) => {
        return this.testingInformationSV.get(this.testingInformationUid).pipe(
          tap(x => this.testingInformationData = x)
        )
      }),
      concatMap((x:any) => this.gradingSV.search('?subject_uid='+this.subjectUid+'&testing_information_uid='+this.testingInformationUid+'&is_use=true')),
      concatMap((x:any) => {
        if(x.length > 0) return this.gradingSV.get(x[0].grading_uid)
        if(x.length == 0) return of()
      }),
      tap(x => this.oldData = x),
    ).subscribe()

  }

  gradingTypeChange(event){
    const form = this.form.get('grading_details') as FormArray
    if(event.value == 1){
      form.clear()
      this.addGradeTemplate()
    } else {
      form.clear()
    }
  }

  gradingCharacteristicChange(event){
    const form = this.form.get('grading_details') as FormArray
    form.clear()
    this.addGradeTemplate()
  }

  announcementChange(event){
    if(event.value == 1) {
      this.form.get('announcement_date').clearValidators()
      this.form.get('announcement_date').updateValueAndValidity()
      return this.form.get('announcement_date').setValue(null)
    }
    this.form.get('announcement_date').setValidators(Validators.required)
    this.form.get('announcement_date').updateValueAndValidity()
  }

  checkValidate(value,form,index){
    const isPercent = this.form.get('grading_characteristic').value == 2
    const gradingDetailsForm = this.form.get('grading_details') as FormArray
    const gradingDetailsRawValue = (this.form.get('grading_details') as FormArray).getRawValue()
    const gradeEndBefore = gradingDetailsRawValue[index !== 0 ? index-1 : index].grade_end
    const gradeEndAfter = gradingDetailsRawValue[index !== gradingDetailsRawValue.length-1 ? index+1 : index].grade_end
    const valueGreaterEqualThan = (grade_end:number) => +value >= grade_end
    const valueLessEqualThan = (grade_end:number) => +value <= grade_end
    // grade A
    if(index === 0){
      if(valueLessEqualThan(gradeEndAfter)){
        gradingDetailsForm.at(index+1).get('grade_end').setValue(null)
      }else{
        if(isPercent){
          if(+value > 100){
            return form.get('grade_end').setValue(100)
          }
        }
        form.get('grade_end').setValue(+value)
      }
    }

    // grade F
    if(index === gradingDetailsRawValue.length-1){
      // if(valueGreaterEqualThan(gradeEndBefore) && (typeof gradeEndBefore === 'number')){
      //   gradingDetailsForm.at(index).get('grade_end').setValue(null)
      // }

      gradingDetailsForm.at(index).get('grade_end').setValue(0)
    }

    // grade B,C,D
    if(index !== 0 && index !== gradingDetailsRawValue.length-1){
      if((typeof gradeEndBefore === 'number') && valueGreaterEqualThan(gradeEndBefore)){
        form.get('grade_end').setValue(null)
      }
      if(valueLessEqualThan(gradeEndAfter)){
        gradingDetailsForm.at(index+1).get('grade_end').setValue(null)
      }
    }

  }

  createForm(){
    return this.fb.group({
      status_id: null,
      created_by: null,
      created_datetime: null,
      updated_by: null,
      updated_datetime: null,
      deleted_by: null,
      deleted_datetime: null,
      grading_uid: null,
      testing_information_uid: null,
      subject_uid: null,
      grading_characteristic: [null,Validators.required],
      grading_type: [1,Validators.required],
      announcement_type : [null,Validators.required],
      announcement_date: null,
      grading_details: this.fb.array([])
    })
  }

  addGradeTemplate(){
    const form = this.form.get('grading_details') as FormArray
    form.push(this.createDetail('A'))
    form.push(this.createDetail('B+'))
    form.push(this.createDetail('B'))
    form.push(this.createDetail('C+'))
    form.push(this.createDetail('C'))
    form.push(this.createDetail('D+'))
    form.push(this.createDetail('D'))
    form.push(this.createDetail('F'))
  }

  add(){
    const form = this.form.get('grading_details') as FormArray
    form.push(this.createDetail())
  }

  remove(i){
    const form = this.form.get('grading_details') as FormArray
    form.removeAt(i)
    form.at(form.length-1 >= 0? form.length-1 : 0).get('grade_end').setValue(0)
  }

  createDetail(x?){
    return this.fb.group({
      status_id: null,
      created_by: null,
      created_datetime: null,
      updated_by: null,
      updated_datetime: null,
      deleted_by: null,
      deleted_datetime: null,
      grading_detail_uid: null,
      grading_uid: null,
      grading_name: [x,Validators.required],
      grade_start: [null],
      grade_end: [null,Validators.required],
    })
  }

  save(){
    const form = this.form.getRawValue()
    if(this.oldData){
      form.grading_uid = this.oldData.grading_uid
      this.gradingSV.update2(form).pipe(
        tap(x => this.swSV.saveSuccess()),
        tap(x => this.location.back()),
        catchError(err => {
          this.swSV.err()
          return throwError(err)
        })
      ).subscribe()
    }else{
      this.gradingSV.add(form).pipe(
        tap(x => this.swSV.saveSuccess()),
        tap(x => this.location.back()),
        catchError(err => {
          this.swSV.err()
          return throwError(err)
        })
      ).subscribe()
    }
  }

  cancel(){
    this.location.back()
  }

  selectGrade(){
    const dialogRef = this.dialog.open(GradeDialogComponent, {
      width: '700px',
      data: this.subject.subject_uid,
    });

    dialogRef.afterClosed().pipe(
      filter(x => x),
      tap(x => this.setupGrade(x.grade_data))
    ).subscribe()
  }

  setupGrade(x){
    // announcement_date
    // announcement_type
    // this.form.patchValue(x)grading_type
    this.form.get('grading_type').setValue(x.grading_type)
    this.form.get('announcement_type').setValue(x.announcement_type)
    this.form.get('announcement_date').setValue(x.announcement_date)
    this.form.get('grading_characteristic').setValue(x.grading_characteristic)
    this.form.setControl('grading_details',this.fb.array(x?.grading_details.map(z => this.createSelectGradeDetail(z))))
  }

  createSelectGradeDetail(x){
    return this.fb.group({
      status_id: null,
      created_by: null,
      created_datetime: null,
      updated_by: null,
      updated_datetime: null,
      deleted_by: null,
      deleted_datetime: null,
      grading_detail_uid: null,
      grading_uid: null,
      grading_name: x.grading_name,
      grade_start: x.grade_start,
      grade_end: x.grade_end,
    })
  }

}
