import { IsString } from 'class-validator';
import { ForbiddenError, NotAcceptableError, NotFoundError, UnauthorizedError } from 'routing-controllers';

/**
 * Error to throw when a jwt could not be parsed.
 * For example: Wrong signature or expired.
 */
export class IllegalJWTError extends UnauthorizedError {
	@IsString()
	name = "IllegalJWTError"

	@IsString()
	message = "Your provided jwt could not be parsed."
}

/**
 * Error to throw when user is nonexistant or refreshtoken is invalid.
 * This can happen if someone provides a JWT with a invalid user id or the refreshTokenCount of the user is higher that the provided jwt's is.
 */
export class UserNonexistantOrRefreshtokenInvalidError extends UnauthorizedError {
	@IsString()
	name = "UserNonexistantOrRefreshtokenInvalidError"

	@IsString()
	message = "User is nonexistant or refreshtoken is invalid."
}

/**
 * Error to throw when provided credentials are invalid.
 * We don't have seperate errors for username/mail and passwords to protect against guessing attacks.
 */
export class InvalidCredentialsError extends UnauthorizedError {
	@IsString()
	name = "InvalidCredentialsError"

	@IsString()
	message = "Your provided credentials are invalid."
}

/**
 * Error to throw when a jwt does not have permission for this route/action.
 * Mainly used be the @Authorized decorator (via the authchecker).
 */
export class NoPermissionError extends ForbiddenError {
	@IsString()
	name = "NoPermissionError"

	@IsString()
	message = "Your provided jwt does not have permission for this route/ action."
}

/**
 * Error to throw when no username and no email is set.
 * Because we have to identify users somehow.
 */
export class UsernameOrEmailNeededError extends NotAcceptableError {
	@IsString()
	name = "UsernameOrEmailNeededError"

	@IsString()
	message = "Auth needs to have email or username set! \n You provided neither."
}

/**
 * Error to throw when no password is provided for a new user.
 * Passwords are the minimum we need for user security.
 */
export class PasswordNeededError extends NotAcceptableError {
	@IsString()
	name = "PasswordNeededError"

	@IsString()
	message = "No password is provided - you need to provide it."
}

/**
 * Error to throw when no user could be found for a certain query.
 */
export class UserNotFoundError extends NotFoundError {
	@IsString()
	name = "UserNotFoundError"

	@IsString()
	message = "The user you provided couldn't be located in the system. \n Please check your request."
}

/**
 * Error to throw when no jwt was provided (but one had to be).
 */
export class JwtNotProvidedError extends NotAcceptableError {
	@IsString()
	name = "JwtNotProvidedError"

	@IsString()
	message = "No jwt was provided."
}

/**
 * Error to throw when user was not found or the jwt's refresh token count was invalid.
 */
export class UserNotFoundOrRefreshTokenCountInvalidError extends NotAcceptableError {
	@IsString()
	name = "UserNotFoundOrRefreshTokenCountInvalidError"

	@IsString()
	message = "User was not found or the refresh token count is invalid."
}

/**
 * Error to throw when refresh token count was invalid
 */
export class RefreshTokenCountInvalidError extends NotAcceptableError {
	@IsString()
	name = "RefreshTokenCountInvalidError"

	@IsString()
	message = "Refresh token count is invalid."
}

/**
 * Error to throw when someone tries to reset a user's password more than once in 15 minutes.
 */
export class ResetAlreadyRequestedError extends NotAcceptableError {
	@IsString()
	name = "ResetAlreadyRequestedError"

	@IsString()
	message = "You already requested a password reset in the last 15 minutes. \n Please wait until the old reset code expires before requesting a new one."
}

/**
 * Error to throw when someone tries a disabled user's password or login as a disabled user.
 */
export class UserDisabledError extends NotAcceptableError {
	@IsString()
	name = "UserDisabledError"

	@IsString()
	message = "This user is currently disabled. \n Please contact your administrator if this is a mistake."
}