﻿
// ReSharper disable InconsistentNaming

export class Client {
    private http: { fetch(url: RequestInfo, init?: RequestInit): Promise<Response> };
    private baseUrl: string;
    protected jsonParseReviver: ((key: string, value: any) => any) | undefined = undefined;

    constructor(baseUrl?: string, http?: { fetch(url: RequestInfo, init?: RequestInit): Promise<Response> }) {
        this.http = http ? http : window as any;
        this.baseUrl = baseUrl ?? "https://myapi.centralus-01.azurewebsites.net/";
    }

    /**
     */
    _2fa(body: TwoFactorRequest): Promise<TwoFactorResponse> {
        let url_ = this.baseUrl + "/manage/2fa";
        url_ = url_.replace(/[?&]$/, "");

        const content_ = JSON.stringify(body);

        let options_: RequestInit = {
            body: content_,
            method: "POST",
            headers: {
                "Content-Type": "application/json",
                "Accept": "application/json"
            }
        };

        return this.http.fetch(url_, options_).then((_response: Response) => {
            return this.process2fa(_response);
        });
    }

    protected process2fa(response: Response): Promise<TwoFactorResponse> {
        const status = response.status;
        let _headers: any = {}; if (response.headers && response.headers.forEach) { response.headers.forEach((v: any, k: any) => _headers[k] = v); };
        if (status === 200) {
            return response.text().then((_responseText) => {
            let result200: any = null;
            let resultData200 = _responseText === "" ? null : JSON.parse(_responseText, this.jsonParseReviver);
            result200 = TwoFactorResponse.fromJS(resultData200);
            return result200;
            });
        } else if (status === 400) {
            return response.text().then((_responseText) => {
            let result400: any = null;
            let resultData400 = _responseText === "" ? null : JSON.parse(_responseText, this.jsonParseReviver);
            result400 = HttpValidationProblemDetails.fromJS(resultData400);
            return throwException("Bad Request", status, _responseText, _headers, result400);
            });
        } else if (status === 404) {
            return response.text().then((_responseText) => {
            return throwException("Not Found", status, _responseText, _headers);
            });
        } else if (status !== 200 && status !== 204) {
            return response.text().then((_responseText) => {
            return throwException("An unexpected server error occurred.", status, _responseText, _headers);
            });
        }
        return Promise.resolve<TwoFactorResponse>(null as any);
    }
}

export class HttpValidationProblemDetails implements IHttpValidationProblemDetails {
    type?: string | undefined;
    title?: string | undefined;
    status?: number | undefined;
    detail?: string | undefined;
    instance?: string | undefined;
    errors?: { [key: string]: string[]; };

    [key: string]: any;

    constructor(data?: IHttpValidationProblemDetails) {
        if (data) {
            for (var property in data) {
                if (data.hasOwnProperty(property))
                    (this as any)[property] = (data as any)[property];
            }
        }
    }

    init(_data?: any) {
        if (_data) {
            for (var property in _data) {
                if (_data.hasOwnProperty(property))
                    this[property] = _data[property];
            }
            this.type = _data["type"];
            this.title = _data["title"];
            this.status = _data["status"];
            this.detail = _data["detail"];
            this.instance = _data["instance"];
            if (_data["errors"]) {
                this.errors = {} as any;
                for (let key in _data["errors"]) {
                    if (_data["errors"].hasOwnProperty(key))
                        (this.errors as any)![key] = _data["errors"][key] !== undefined ? _data["errors"][key] : [];
                }
            }
        }
    }

    static fromJS(data: any): HttpValidationProblemDetails {
        data = typeof data === 'object' ? data : {};
        let result = new HttpValidationProblemDetails();
        result.init(data);
        return result;
    }

    toJSON(data?: any) {
        data = typeof data === 'object' ? data : {};
        for (var property in this) {
            if (this.hasOwnProperty(property))
                data[property] = this[property];
        }
        data["type"] = this.type;
        data["title"] = this.title;
        data["status"] = this.status;
        data["detail"] = this.detail;
        data["instance"] = this.instance;
        if (this.errors) {
            data["errors"] = {};
            for (let key in this.errors) {
                if (this.errors.hasOwnProperty(key))
                    (data["errors"] as any)[key] = (this.errors as any)[key];
            }
        }
        return data;
    }
}

export interface IHttpValidationProblemDetails {
    type?: string | undefined;
    title?: string | undefined;
    status?: number | undefined;
    detail?: string | undefined;
    instance?: string | undefined;
    errors?: { [key: string]: string[]; };

    [key: string]: any;
}

export class TwoFactorRequest implements ITwoFactorRequest {
    enable?: boolean | undefined;
    twoFactorCode?: string | undefined;
    resetSharedKey?: boolean;
    resetRecoveryCodes?: boolean;
    forgetMachine?: boolean;

    [key: string]: any;

    constructor(data?: ITwoFactorRequest) {
        if (data) {
            for (var property in data) {
                if (data.hasOwnProperty(property))
                    (this as any)[property] = (data as any)[property];
            }
        }
    }

    init(_data?: any) {
        if (_data) {
            for (var property in _data) {
                if (_data.hasOwnProperty(property))
                    this[property] = _data[property];
            }
            this.enable = _data["enable"];
            this.twoFactorCode = _data["twoFactorCode"];
            this.resetSharedKey = _data["resetSharedKey"];
            this.resetRecoveryCodes = _data["resetRecoveryCodes"];
            this.forgetMachine = _data["forgetMachine"];
        }
    }

    static fromJS(data: any): TwoFactorRequest {
        data = typeof data === 'object' ? data : {};
        let result = new TwoFactorRequest();
        result.init(data);
        return result;
    }

    toJSON(data?: any) {
        data = typeof data === 'object' ? data : {};
        for (var property in this) {
            if (this.hasOwnProperty(property))
                data[property] = this[property];
        }
        data["enable"] = this.enable;
        data["twoFactorCode"] = this.twoFactorCode;
        data["resetSharedKey"] = this.resetSharedKey;
        data["resetRecoveryCodes"] = this.resetRecoveryCodes;
        data["forgetMachine"] = this.forgetMachine;
        return data;
    }
}

export interface ITwoFactorRequest {
    enable?: boolean | undefined;
    twoFactorCode?: string | undefined;
    resetSharedKey?: boolean;
    resetRecoveryCodes?: boolean;
    forgetMachine?: boolean;

    [key: string]: any;
}

export class TwoFactorResponse implements ITwoFactorResponse {
    sharedKey!: string;
    recoveryCodesLeft!: number;
    recoveryCodes?: string[] | undefined;
    isTwoFactorEnabled!: boolean;
    isMachineRemembered!: boolean;

    [key: string]: any;

    constructor(data?: ITwoFactorResponse) {
        if (data) {
            for (var property in data) {
                if (data.hasOwnProperty(property))
                    (this as any)[property] = (data as any)[property];
            }
        }
    }

    init(_data?: any) {
        if (_data) {
            for (var property in _data) {
                if (_data.hasOwnProperty(property))
                    this[property] = _data[property];
            }
            this.sharedKey = _data["sharedKey"];
            this.recoveryCodesLeft = _data["recoveryCodesLeft"];
            if (Array.isArray(_data["recoveryCodes"])) {
                this.recoveryCodes = [] as any;
                for (let item of _data["recoveryCodes"])
                    this.recoveryCodes!.push(item);
            }
            this.isTwoFactorEnabled = _data["isTwoFactorEnabled"];
            this.isMachineRemembered = _data["isMachineRemembered"];
        }
    }

    static fromJS(data: any): TwoFactorResponse {
        data = typeof data === 'object' ? data : {};
        let result = new TwoFactorResponse();
        result.init(data);
        return result;
    }

    toJSON(data?: any) {
        data = typeof data === 'object' ? data : {};
        for (var property in this) {
            if (this.hasOwnProperty(property))
                data[property] = this[property];
        }
        data["sharedKey"] = this.sharedKey;
        data["recoveryCodesLeft"] = this.recoveryCodesLeft;
        if (Array.isArray(this.recoveryCodes)) {
            data["recoveryCodes"] = [];
            for (let item of this.recoveryCodes)
                data["recoveryCodes"].push(item);
        }
        data["isTwoFactorEnabled"] = this.isTwoFactorEnabled;
        data["isMachineRemembered"] = this.isMachineRemembered;
        return data;
    }
}

export interface ITwoFactorResponse {
    sharedKey: string;
    recoveryCodesLeft: number;
    recoveryCodes?: string[] | undefined;
    isTwoFactorEnabled: boolean;
    isMachineRemembered: boolean;

    [key: string]: any;
}

export class ApiException extends Error {
    override message: string;
    status: number;
    response: string;
    headers: { [key: string]: any; };
    result: any;

    constructor(message: string, status: number, response: string, headers: { [key: string]: any; }, result: any) {
        super();

        this.message = message;
        this.status = status;
        this.response = response;
        this.headers = headers;
        this.result = result;
    }

    protected isApiException = true;

    static isApiException(obj: any): obj is ApiException {
        return obj.isApiException === true;
    }
}

function throwException(message: string, status: number, response: string, headers: { [key: string]: any; }, result?: any): any {
    if (result !== null && result !== undefined)
        throw result;
    else
        throw new ApiException(message, status, response, headers, null);
}