/**
 * Define generic server errors here.
 * For more info see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error
 */

"use strict";

const ErrorCodes = require('../../shared/constants/ErrorCodes');
const UtilHttpStatus = require('../../shared/utils/UtilHttpStatus');

function createError(name, defaultMessage, errorCode, httpStatusCode) {

    const SubClass =  function (message) {

        this.name = name;
        this.message = message || defaultMessage;

        if(errorCode){
            this.errorCode = errorCode;
        }
        if(httpStatusCode){
            this.httpStatusCode = httpStatusCode;
        }

        // Set the name so the stack displays the correct error name and message
        const err = new Error(this.message);
        err.name = this.name;
        this.stack = err.stack;

    };

    SubClass.prototype = Object.create(Error.prototype);
    SubClass.prototype.constructor = SubClass;

    return SubClass;
}

function buildError(name, defaultMessage, errorCode) {
    const ObjectError = createError(name, defaultMessage, errorCode);
    return new ObjectError();
}

class ServerError extends Error {
    constructor(message){
        super(message != null ? message : "Server Error.");
        this.name = "ServerError";
        this.httpStatusCode = UtilHttpStatus.INTERNAL_SERVER_ERROR;
    }
}

class NotFoundError extends Error {
    constructor(message){
        super(message != null ? message : "Not Found Error.");
        this.name = "NotFoundError";
        this.httpStatusCode = UtilHttpStatus.NOT_FOUND;
    }
}

class InvalidRequestError extends Error {
    constructor(message){
        super(message != null ? message : "Invalid request Error.");
        this.name = "InvalidRequestError";
        this.httpStatusCode = UtilHttpStatus.BAD_REQUEST;
    }
}

class AccountNotFoundError extends Error {
    constructor(message){
        super(message != null ? message : "Account not found.");
        this.name = "AccountNotFoundError";
    }
}

class AccountUniqueResultError extends Error {
    constructor(message){
        super(message != null ? message : "There is more than one account with the " +
            "specified email address. Please see an Administrator.");
        this.name = "AccountUniqueResultError";
    }
}

class NoAccountTemplateError extends Error {
    constructor(message){
        super(message != null ? message : "Account template undefined.");
        this.name = "NoAccountTemplateError";
        this.errorCode = ErrorCodes.ERROR_NO_ACCOUNT_TEMPLATE;
    }
}

class NoAccountSecurityTemplateError extends Error {
    constructor(message){
        super(message != null ? message : "Account security template undefined.");
        this.name = "NoAccountSecurityTemplateError";
        this.errorCode = ErrorCodes.ERROR_NO_ACCOUNT_SECURITY_TEMPLATE;
    }
}

class NoAccountControlTemplateError extends Error {
    constructor(message){
        super(message != null ? message : "Account control template undefined.");
        this.name = "NoAccountControlTemplateError";
        this.errorCode = ErrorCodes.ERROR_NO_ACCOUNT_CONTROL_TEMPLATE;
    }
}

class NoPermissionError extends Error {
    constructor(message){
        super(message != null ? message : "Account has no permission.");
        this.name = "NoPermissionError";
        this.httpStatusCode = UtilHttpStatus.FORBIDDEN;
    }
}
class PasswordResetRequired extends Error {
    constructor(message){
        super(message != null ? message : "Password reset required.");
        this.name = "PasswordResetRequired";
        this.errorCode = ErrorCodes.ERROR_PASSWORD_RESET_REQUIRED;
    }
}

module.exports = {
    //http
    ServerError,
    InvalidRequestError,
    NotFoundError,
    NoPermissionError,
    //non-http
    AccountNotFoundError,
    AccountUniqueResultError,
    NoAccountTemplateError,
    NoAccountSecurityTemplateError,
    NoAccountControlTemplateError,
    PasswordResetRequired,
    buildError: buildError
};
