import { ErrorHandler, Injectable } from '@angular/core';
import { LoggingService } from '@app/_services/logging.service';
import { HttpErrorResponse } from '@angular/common/http';
import { Router } from '@angular/router';

// A generalized http response error
export class HttpError extends Error {
  public status: number;
  constructor(message: string, status: number) {
    super(message);
    this.status = status;
    this.name = 'HttpError';
  }
}

@Injectable()
export class GlobalErrorHandler extends ErrorHandler {
  private sentencesForWarningLogging: Array<string> = [];

  constructor(private loggingService: LoggingService, private router: Router) {
    super();
  }

  handleError(error: Error): void {
    this.logError(error);
    const message: string = error.message ? error.message : error.toString();

    // if (error.status) {
    //   error = new Error(message);
    // }

    const errorTraceString: string = `Error message:\n${message}.\nStack trace: ${error.stack}`;

    const isWarning: boolean = this.isWarning(errorTraceString);
    if (isWarning) {
      this.loggingService.sendWarnLevelMessage(errorTraceString, { error });
    } else {
      this.loggingService.sendErrorLevelMessage(errorTraceString, this, { error });
    }

    throw error;
  }

  logError(error: any): void {
    const route: string = this.router.url;
    if (error instanceof HttpErrorResponse) {
      this.loggingService.sendErrorLevelMessage(
        `There was an HTTP error on route ${route}.\n${error.message}.\nStatus code: ${
          (error as HttpErrorResponse).status
        }`,
        this,
        { error }
      );
    } else if (error instanceof TypeError) {
      this.loggingService.sendErrorLevelMessage(
        `There was a Type error on route ${route}.\n${error.message}`,
        this,
        { error }
      );
    } else if (error instanceof Error) {
      this.loggingService.sendErrorLevelMessage(
        `There was a general error on route ${route}.\n${error.message}`,
        this,
        { error }
      );
    } else {
      this.loggingService.sendErrorLevelMessage(
        `Nobody threw an error but something happened on route ${route}!`,
        this,
        { error }
      );
    }
  }

  private isWarning(errorTraceString: string): boolean {
    let isWarning: boolean = true;
    if (errorTraceString.includes('/src/app/')) {
      isWarning = false;
    }

    this.sentencesForWarningLogging.forEach((whiteListSentence: string) => {
      if (errorTraceString.includes(whiteListSentence)) {
        isWarning = true;
      }
    });

    return isWarning;
  }
}
