import { AxiosResponse } from 'axios';

const canCapture = typeof Error.captureStackTrace === 'function';
const canStack = !!new Error().stack;

/**
 * Abstract error object
 * @class ErrorAbstract
 * @access private
 * @param  {string}      [msg]         Error message
 */
class ErrorAbstract extends Error {
  message: string;

  constructor(msg: string) {
    super(msg);

    this.message = msg;

    if (canCapture) {
      Error.captureStackTrace(this, ErrorAbstract.constructor);
    } else if (canStack) {
      this.stack = new Error().stack;
    } else {
      this.stack = '';
    }
  }
}

/**
 * FeedError
 * @class FeedError
 * @access private
 * @extends ErrorAbstract
 * @memberof Stream.errors
 * @param {String} [msg] - An error message that will probably end up in a log.
 */
export class FeedError extends ErrorAbstract {}

/**
 * SiteError
 * @class SiteError
 * @access private
 * @extends ErrorAbstract
 * @memberof Stream.errors
 * @param  {string}  [msg]  An error message that will probably end up in a log.
 */
export class SiteError extends ErrorAbstract {}

/**
 * MissingSchemaError
 * @method MissingSchemaError
 * @access private
 * @extends ErrorAbstract
 * @memberof Stream.errors
 * @param  {string} msg
 */
export class MissingSchemaError extends ErrorAbstract {}

/**
 * StreamApiError
 * @method StreamApiError
 * @access private
 * @extends ErrorAbstract
 * @memberof Stream.errors
 * @param  {string} msg
 * @param  {object} data
 * @param  {object} response
 */
export class StreamApiError<T> extends ErrorAbstract {
  error: unknown;
  response: AxiosResponse<T>;

  constructor(msg: string, data: unknown, response: AxiosResponse<T>) {
    super(msg);

    this.error = data;
    this.response = response;
  }
}
