
export interface ProgressMonitorReporter {
  report: (msg: string) => void;
  done: () => void;
}

export class ProgressMonitor {

  private started: boolean = false;
  private preWork: number = 0;
  private title: string = '';
  private totalWork: number = 0;
  private finalizing: boolean = false;

  private reporter: ProgressMonitorReporter;

  constructor(reporter: ProgressMonitorReporter) {
      this.reporter = reporter;
      this.preWork = 0;
      this.totalWork = 0;
      this.title = '';
      this.started = false;
      this.finalizing = false;
  }

  handleMessage(err: Error, msg: any): void {
      console.log('progressMonitor recieved message: ' + JSON.stringify(msg.body));
      this.delegateMessage(msg.body);
  }

  delegateMessage(msg: any): void {
      if (msg.op === 'beginTask') {
          const task = msg.task;
          const work = msg.totalWork;
          this.beginTask(task, work);
          return;
      }
      const value = msg.value;
      switch (msg.op) {
          case 'logMessage':
              // this.logMessage(value);
              break;
          case 'done':
              this.done();
              break;
          case 'setTaskName':
              this.setTaskName(value);
              break;
          case 'subTask':
              this.subTask(value);
              break;
          case 'worked':
              this.worked(value);
              break;
      }
      if (!this.started) {
          this.started = true;
          this.report('Launching analysis...');
      }
  }

  beginTask(task: string, total: number): void {
      this.title = 'Analysis in progress';
      this.totalWork = total;
      this.setTitle(this.title);
  }

  done(): void {
      // this.report('Done');
      // this._done = true;
      // this.doClose();
      this.reporter.done();
  }

  // setCancelled(): void {
  //     this.report('Cancelled');
  //     this.isCancelled = true;
  //     this.doClose();
  // }

  setTaskName(task: string): void {
      this.report(task);
  }

  subTask(name: string): void {
      /*let phase = Phase.find(name);
      if (phase) {
          let title = this.computeTitle() + ' - ' + phase;
          this.setTitle(title);
      }*/
  }

  worked(worked: number): void {
      this.preWork += worked;
      this.setTitle(this.computeTitle());
  }

  getPercentangeDone(): number {
      return Math.trunc(Math.min((this.preWork * 100 / this.totalWork), 100));
  }

  computeTitle(): string {
      const done = this.getPercentangeDone();
      let label = this.title;
      if (done > 0) {
          label += ` (${done}% done)`;
      }
      return label;
  }

  setTitle(value: string): void {
      this.report(value);
  }

  report(msg: string): void {
      if (!this.finalizing) {
          if (this.getPercentangeDone() === 99) {
              this.finalizing = true;
              setTimeout(() => null, 500);
              msg = 'Finalizing assessment...';
          }
          this.reporter.report(msg);
      }
      else {
          console.log('progress done or cancelled, cannot report: ' + msg);
      }
  }
}