import Locator from '../services/Locator';

interface ResponseError
{
    code: number | string;
}

interface ResponseWithErrors
{
    errors: ResponseError[];
}

function hasErrorsPayload(value: unknown): value is ResponseWithErrors
{
    return Boolean(
        value
        && typeof value === 'object'
        && 'errors' in value
        && Array.isArray((value as ResponseWithErrors).errors),
    );
}

function getErrorDescriptionByCode(code: number | string): string
{
    switch (code)
    {
        case 101:
        case 102:
        case 103:
        case 104:
        case 105:
        case 201:
        case 202:
        case 203:
        case 204:
        case 205:
        case 206:
        case 301:
        case 302:
        case 303:
        case 401:
        case 402:
        case '301nodep':
        case '206i':
        case 'some_error':
        case 'many_tabs_error':
            return Locator.locales.get(code as string);
        case 'default':
        default:
        {
            const textLocale = Locator.locales.get('default').split('{code}');

            return `${textLocale[0]} ${code} ${textLocale[1]}`;
        }
    }
}

/**
 * Throws typed errors when response payload indicates failure.
 * @param response
 * @param showPreloader
 */
export function checkForErrors(response: unknown, showPreloader?: boolean): void
{
    if (response instanceof NetworkError)
    {
        throw response;
    }

    if (hasErrorsPayload(response))
    {
        const [firstError] = response.errors;

        if (firstError)
        {
            throw new ResponseResultError(firstError.code, showPreloader);
        }
    }
}

export class ResponseResultError extends Error
{
    readonly code: number | string;

    readonly showPreloader?: boolean;

    constructor(code: number | string, showPreloader?: boolean)
    {
        super(getErrorDescriptionByCode(code));
        this.code = code;
        this.showPreloader = showPreloader;
    }
}

export class NetworkError extends Error
{
    constructor()
    {
        super('The client can\'t connect to the server');
    }
}
