import {Component, Input} from "@angular/core";
import {Task, TaskService, TaskStatus, TaskReference, TaskResource, ProcessVariable, UserService, RolesService, ProcessService} from "@webbpm/base-package";
import {CommonModule} from "@angular/common";
import {FormsModule} from "@angular/forms";

@Component({
    selector: "task-list",
    templateUrl: "./task_list.html",
    imports: [CommonModule, FormsModule]
})
export class TaskListComponent {
  @Input()
  public tasks: Task[];

  @Input()
  public onTimeTasks: Task[];

  @Input()
  public overdueTasks: Task[];

  @Input()
  public visibleTasks: Task[];

  @Input()
  public showMode: string;

  @Input()
  public errorMessage: string;

  @Input()
  public roles: string[];

  constructor(private taskService: TaskService,
              private $taskResource: TaskResource,
              private userService: UserService,
              private rolesService: RolesService,
              private processService: ProcessService) {
    this.tasks = [];
    this.onTimeTasks = [];
    this.overdueTasks = [];
    this.visibleTasks = [];
    this.roles = [];
    this.showMode = 'All';

    this.rolesService.getRoles().then((roles: string[]) => {
      this.roles = roles;
    });

    this.loadTasks();
  }

  private loadTasks(): void {
    this.$taskResource.list()
        .then(
            (tasks: Task[]) => this.initTasks(tasks),
            () => this.errorMessage = "Error load tasks"
        );
  }

  public startTask(task: Task): Promise<any> {
    let taskRef: TaskReference = new TaskReference();
    taskRef.processInstanceId = task.processInstanceId;
    taskRef.taskId = task.id;

    if (task.status == TaskStatus.InProgress) {
      return this.taskService.openTask(taskRef);
    }
    else if (task.status == TaskStatus.Reserved || task.status == TaskStatus.Ready) {
      return this.taskService.startAndOpenTask(taskRef);
    }
  }

  private initTasks(tasks: Task[]): void {
    this.tasks = tasks;
    this.filterOnTimeTasks();
    this.filterOverdueTasks();
    this.filterVisibleTasks();
  }

  public isVisible(task: Task): boolean {
    return this.showMode == 'All' ||
        this.showMode == 'OnTime' && !this.isOverdue(task) ||
        this.showMode == 'Overdue' && this.isOverdue(task);
  }

  public isOverdue(task: Task): boolean {
    if (!task.expirationTime) {
      return false;
    }
    return new Date(task.expirationTime).getTime() <= new Date().getTime();
  }

  public isOnTime(task: Task): boolean {
    return !this.isOverdue(task);
  }

  public startProcess(processDefinitionId: string, processVars?: Array<ProcessVariable | any>) {
    this.processService.start(processDefinitionId, processVars).then(
        (processInstanceId: number) => {
          this.taskService.startAndOpenNextTask(processInstanceId);
        }
    );
  }

  public filterOnTimeTasks() {
    this.onTimeTasks = this.tasks
        .filter((task: Task) => this.isOnTime(task));
  }

  public filterOverdueTasks() {
    this.overdueTasks = this.tasks
        .filter((task: Task) => this.isOverdue(task));
  }

  public filterVisibleTasks() {
    this.visibleTasks = this.tasks
        .filter((task: Task) => this.isVisible(task));
  }

  public hasRole(role: string) {
    return this.roles.includes(role);
  }
}
