/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */

import { Component, OnInit, ViewChild, Output, EventEmitter, ViewEncapsulation, ChangeDetectorRef, Inject } from '@angular/core';
import { FormGroup, FormBuilder, Validators } from '@angular/forms';
import { MatDialogRef, MAT_DIALOG_DATA } from '@angular/material/dialog';
import { ToastrService } from 'ngx-toastr';

import * as _moment from 'moment';
import 'moment-timezone';


import { SchedulerService } from '../../core/services';
import { SchedulerModel, WeekdaysModel } from './scheduler.model';
import { SchedulerCalculations } from './scheduler.calculations';
import { HTTP_STATUS_CODES, CheckUtils } from '../../core/util';
import { ScheduleSchema } from './scheduler.model';
import { map } from 'rxjs/operators';

@Component({
  selector: 'dlab-scheduler',
  templateUrl: './scheduler.component.html',
  styleUrls: ['./scheduler.component.scss'],
  encapsulation: ViewEncapsulation.None
})
export class SchedulerComponent implements OnInit {

  readonly CheckUtils = CheckUtils;

  public model: SchedulerModel;
  public selectedStartWeekDays: WeekdaysModel = WeekdaysModel.setDefault();
  public selectedStopWeekDays: WeekdaysModel = WeekdaysModel.setDefault();
  public notebook: any;
  public infoMessage: boolean = false;
  public timeReqiered: boolean = false;
  public terminateDataReqiered: boolean = false;
  public inherit: boolean = false;
  public allowInheritView: boolean = false;
  public parentInherit: boolean = false;
  public enableSchedule: boolean = false;
  public enableIdleTime: boolean = false;
  public enableIdleTimeView: boolean = false;
  public considerInactivity: boolean = false;
  public date_format: string = 'YYYY-MM-DD';
  public timeFormat: string = 'HH:mm';
  public weekdays: string[] = ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'];
  public schedulerForm: FormGroup;
  public destination: any;
  public zones: {};
  public tzOffset: string = _moment().format('Z');
  public startTime = { hour: 9, minute: 0, meridiem: 'AM' };
  public endTime = { hour: 8, minute: 0, meridiem: 'PM' };
  public terminateTime = null;

  public inactivityLimits = { min: 120, max: 10080 };
  public integerRegex: string = '^[0-9]*$';

  @ViewChild('resourceSelect', { static: false }) resource_select;

  constructor(
    @Inject(MAT_DIALOG_DATA) public data: any,
    public toastr: ToastrService,
    public dialogRef: MatDialogRef<SchedulerComponent>,
    private formBuilder: FormBuilder,
    private schedulerService: SchedulerService,
    private changeDetector: ChangeDetectorRef
  ) { }

  ngOnInit() {
    this.open(this.data.notebook, this.data.type, this.data.resource);
  }

  public open(notebook, type, resource?): void {
    this.notebook = notebook;
    this.zones = _moment.tz.names()
      .map(item => [_moment.tz(item).format('Z'), item])
      .sort()
      .reduce((memo, item) => {
        memo[item[0]] ? memo[item[0]] += `, ${item[1]}` : memo[item[0]] = item[1];
        return memo;
      }, {});

    this.model = new SchedulerModel(
      response => {
        if (response.status === HTTP_STATUS_CODES.OK) {
          this.toastr.success('Schedule data were successfully saved', 'Success!');
          this.dialogRef.close();
        }
      },
      error => this.toastr.error(error.message || 'Scheduler configuration failed!', 'Oops!'),
      () => {
        this.formInit();
        this.changeDetector.detectChanges();
        this.destination = (type === 'EXPLORATORY') ? this.notebook : resource;
        this.destination.type = type;
        this.selectedStartWeekDays.reset();
        this.selectedStopWeekDays.reset();
        this.allowInheritView = false;

        if (this.destination.type === 'СOMPUTATIONAL') {
          this.allowInheritView = true;
          this.getExploratorySchedule(this.notebook.project, this.notebook.name, this.destination.computational_name);
          this.checkParentInherit();
        } else if (this.destination.type === 'EXPLORATORY') {
          this.allowInheritView = this.checkIsActiveSpark();
          this.getExploratorySchedule(this.notebook.project, this.notebook.name);
        }
      },
      this.schedulerService
    );
  }

  public onDaySelect($event, day, action) {
    if (action === 'start') {
      this.selectedStartWeekDays[day.toLowerCase()] = $event.source.checked;
    } else if (action === 'stop') {
      this.selectedStopWeekDays[day.toLowerCase()] = $event.source.checked;
    }
  }

  public toggleInherit($event) {
    this.inherit = $event.checked;

    if (this.destination.type === 'СOMPUTATIONAL' && this.inherit) {
      this.getExploratorySchedule(this.notebook.project, this.notebook.name);
      this.schedulerForm.get('startDate').disable();
    } else {
      this.schedulerForm.get('startDate').enable();
    }
  }

  public toggleSchedule($event) {
    this.enableSchedule = $event.checked;
    this.timeReqiered = false;
    this.allowInheritView = this.destination.type === 'СOMPUTATIONAL' || this.checkIsActiveSpark();

    this.enableSchedule && this.enableIdleTime && this.toggleIdleTimes({ checked: false });
    (this.enableSchedule && !(this.destination.type === 'СOMPUTATIONAL' && this.inherit))
      ? this.schedulerForm.get('startDate').enable()
      : this.schedulerForm.get('startDate').disable();

    this.enableSchedule ? this.schedulerForm.get('finishDate').enable() : this.schedulerForm.get('finishDate').disable();
    this.enableSchedule ? this.schedulerForm.get('terminateDate').enable() : this.schedulerForm.get('terminateDate').disable();

    if (this.enableSchedule && $event.source) this.enableIdleTimeView = false;
  }

  public toggleIdleTimes($event) {
    const control = this.schedulerForm.controls.inactivityTime;

    this.enableIdleTime = $event.checked;
    this.enableIdleTime && this.enableSchedule && this.toggleSchedule({ checked: false });
    this.allowInheritView = false;

    if (!this.enableIdleTime) {
      this.allowInheritView = this.destination.type === 'СOMPUTATIONAL' || this.checkIsActiveSpark();
      control.setValue('');
    } else {
      !control.value && control.setValue(this.inactivityLimits.min);
      this.enableIdleTimeView = true;
    }
  }

  public setInactivity(...params) {
    this.model.setInactivityTime(params).subscribe((response: any) => {
      if (response.status === HTTP_STATUS_CODES.OK) {
        this.toastr.success('Schedule data were successfully saved', 'Success!');
        this.dialogRef.close();
      }
    },
      error => this.toastr.error(error.message || 'Scheduler configuration failed!', 'Oops!'));
  }

  public inactivityCounter($event, action: string): void {
    $event.preventDefault();
    const value = this.schedulerForm.controls.inactivityTime.value;
    const newValue = (action === 'increment' ? Number(value) + 10 : Number(value) - 10);
    this.schedulerForm.controls.inactivityTime.setValue(newValue);
  }

  public scheduleInstance_btnClick() {
    if (this.enableIdleTimeView) {
      this.enableIdleTime ? this.setScheduleByInactivity() : this.resetScheduler();
    } else {
      this.enableSchedule ? this.setScheduleByTime() : this.resetScheduler();
    }
  }

  private resetScheduler() {
    const resource = this.destination.type === 'СOMPUTATIONAL' ? this.destination.computational_name : null;
    this.model.resetSchedule(this.notebook.name, resource)
      .subscribe(() => {
        this.resetDialog();
        this.toastr.success('Schedule data were successfully deleted', 'Success!');
        this.dialogRef.close();
      });
  }

  private setScheduleByTime() {
    const data = {
      startDate: this.schedulerForm.controls.startDate.value,
      finishDate: this.schedulerForm.controls.finishDate.value,
      terminateDate: this.schedulerForm.controls.terminateDate.value
    };
    const terminateDateTime = (data.terminateDate && this.terminateTime)
      ? `${_moment(data.terminateDate).format(this.date_format)} ${SchedulerCalculations.convertTimeFormat(this.terminateTime)}`
      : null;

    if (!this.startTime && !this.endTime && !this.terminateTime && this.enableSchedule) {
      this.timeReqiered = true;
      return false;
    }

    if ((data.terminateDate && !this.terminateTime) || (!data.terminateDate && this.terminateTime)) {
      this.terminateDataReqiered = true;
      return false;
    }

    const selectedDays = Object.keys(this.selectedStartWeekDays);
    const parameters: ScheduleSchema = {
      begin_date: data.startDate ? _moment(data.startDate).format(this.date_format) : null,
      finish_date: data.finishDate ? _moment(data.finishDate).format(this.date_format) : null,
      start_time: this.startTime ? SchedulerCalculations.convertTimeFormat(this.startTime) : null,
      end_time: this.endTime ? SchedulerCalculations.convertTimeFormat(this.endTime) : null,
      start_days_repeat: selectedDays.filter(el => Boolean(this.selectedStartWeekDays[el])).map(day => day.toUpperCase()),
      stop_days_repeat: selectedDays.filter(el => Boolean(this.selectedStopWeekDays[el])).map(day => day.toUpperCase()),
      timezone_offset: this.tzOffset,
      sync_start_required: this.inherit,
      check_inactivity_required: this.enableIdleTime,
      terminate_datetime: terminateDateTime
    };

    if (this.destination.type === 'СOMPUTATIONAL') {
      this.model.confirmAction(this.notebook.project, this.notebook.name, parameters, this.destination.computational_name);
    } else {
      parameters['consider_inactivity'] = this.considerInactivity;
      this.model.confirmAction(this.notebook.project, this.notebook.name, parameters);
    }
  }

  private setScheduleByInactivity() {
    const data = {
      sync_start_required: this.parentInherit,
      check_inactivity_required: this.enableIdleTime,
      max_inactivity: this.schedulerForm.controls.inactivityTime.value
    };
    (this.destination.type === 'СOMPUTATIONAL')
      ? this.setInactivity(this.notebook.project, this.notebook.name, data, this.destination.computational_name)
      : this.setInactivity(this.notebook.project, this.notebook.name, { ...data, consider_inactivity: this.considerInactivity });
  }

  private formInit(start?: string, end?: string, terminate?: string) {
    this.schedulerForm = this.formBuilder.group({
      startDate: { disabled: this.inherit, value: start ? _moment(start).format() : null },
      finishDate: { disabled: false, value: end ? _moment(end).format() : null },
      terminateDate: { disabled: false, value: terminate ? _moment(terminate).format() : null },
      inactivityTime: [this.inactivityLimits.min,
      [Validators.compose([Validators.pattern(this.integerRegex), this.validInactivityRange.bind(this)])]]
    });
  }

  private getExploratorySchedule(project, resource, resource2?) {
    this.schedulerService.getExploratorySchedule(project, resource, resource2).subscribe(
      (params: ScheduleSchema) => {
        if (params) {
          params.start_days_repeat.filter(key => (this.selectedStartWeekDays[key.toLowerCase()] = true));
          params.stop_days_repeat.filter(key => (this.selectedStopWeekDays[key.toLowerCase()] = true));
          this.inherit = params.sync_start_required;
          this.tzOffset = params.timezone_offset;
          this.startTime = params.start_time ? SchedulerCalculations.convertTimeFormat(params.start_time) : null;
          this.endTime = params.end_time ? SchedulerCalculations.convertTimeFormat(params.end_time) : null;
          this.formInit(params.begin_date, params.finish_date, params.terminate_datetime);
          this.schedulerForm.controls.inactivityTime.setValue(params.max_inactivity || this.inactivityLimits.min);
          this.enableIdleTime = params.check_inactivity_required;
          this.considerInactivity = params.consider_inactivity || false;

          if (params.terminate_datetime) {
            const terminate_datetime = params.terminate_datetime.split(' ');
            this.schedulerForm.controls.terminateDate.setValue(terminate_datetime[0]);
            this.terminateTime = SchedulerCalculations.convertTimeFormat(terminate_datetime[1]);
          }

          (this.enableIdleTime && params.max_inactivity)
            ? this.toggleIdleTimes({ checked: true })
            : this.toggleSchedule({ checked: true });
        }
      },
      error => this.resetDialog());
  }

  private checkParentInherit() {
    this.schedulerService.getExploratorySchedule(this.notebook.project, this.notebook.name)
      .subscribe((res: any) => this.parentInherit = res.sync_start_required);
  }

  private validInactivityRange(control) {
    if (control)
      return this.enableIdleTime
        ? (control.value
          && control.value >= this.inactivityLimits.min
          && control.value <= this.inactivityLimits.max ? null : { valid: false })
        : control.value;
  }

  private checkIsActiveSpark() {
    return this.notebook.resources.length > 0 && this.notebook.resources.some(el => el.image === 'docker.dlab-dataengine'
      && (el.status !== 'terminated' && el.status !== 'terminating' && el.status !== 'failed'));
  }

  private resetDialog() {
    this.infoMessage = false;
    this.timeReqiered = false;
    this.terminateDataReqiered = false;
    this.inherit = false;
    this.enableSchedule = false;
    this.considerInactivity = false;
    this.enableIdleTime = false;
    this.tzOffset = _moment().format('Z');
    this.startTime = SchedulerCalculations.convertTimeFormat('09:00');
    this.endTime = SchedulerCalculations.convertTimeFormat('20:00');
    this.terminateTime = null;

    this.schedulerForm.get('startDate').disable();
    this.schedulerForm.get('finishDate').disable();
    this.schedulerForm.get('terminateDate').disable();
  }
}
