/*! ****************************************************************************
Copyright (c) Microblink. All rights reserved.

THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED
WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
MERCHANTABLITY OR NON-INFRINGEMENT.
***************************************************************************** */
/**
 * Copyright (c) Microblink Ltd. All rights reserved.
 */
var ApiType;
(function (ApiType) {
    ApiType["Cloud"] = "cloud";
    ApiType["SelfHosted"] = "self-hosted";
})(ApiType || (ApiType = {}));
const GenericMessages = {
    "GENERIC_ERROR": "There was an error during scan action.",
    "UNKNOWN_ERROR": "Oops, something went wrong."
};

/**
 * Copyright (c) Microblink Ltd. All rights reserved.
 */
function getSafeUrl(base, ...args) {
    const impureUrl = [...args].join("/");
    const pureUrl = safeReplaceAll(impureUrl, "//", "/");
    const safeBase = base.endsWith("/") ? base.slice(0, -1) : base;
    const endpoint = pureUrl.startsWith("/") ? pureUrl : "/" + pureUrl;
    return safeBase + endpoint;
}
function safeReplaceAll(input, substr, newSubstr) {
    input = input || "";
    substr = substr || "";
    newSubstr = newSubstr || "";
    while (input.indexOf(substr) > -1) {
        input = input.replace(substr, newSubstr);
    }
    return input;
}
function httpClient(method, url, headers, payload) {
    return new Promise((resolve, reject) => {
        const fetchConfiguration = {
            method,
            headers
        };
        if (payload) {
            fetchConfiguration["body"] = JSON.stringify(payload);
        }
        window.fetch(url, fetchConfiguration)
            .then((response) => {
            const headerEntries = response.headers.entries();
            const headers = {};
            for (const entry of headerEntries) {
                headers[entry[0]] = entry[1];
            }
            const httpResponse = {
                httpStatus: response.status,
                headers
            };
            response.text()
                .then((data) => {
                try {
                    const jsonData = JSON.parse(data);
                    httpResponse["data"] = jsonData;
                }
                catch (_a) {
                    httpResponse["data"] = data;
                }
                resolve(httpResponse);
            })
                .catch((error) => {
                httpResponse["data"] = error;
                reject(httpResponse);
            });
        })
            .catch(error => {
            reject({
                httpStatus: -1,
                headers: {},
                data: error
            });
        });
    });
}
function imageDataToBase64(imageData) {
    const canvas = document.createElement("canvas");
    canvas.width = imageData.width;
    canvas.height = imageData.height;
    const context = canvas.getContext("2d");
    context === null || context === void 0 ? void 0 : context.putImageData(imageData, 0, 0);
    return canvas.toDataURL();
}

/**
 * Copyright (c) Microblink Ltd. All rights reserved.
 */
const CloudMessages = {
    "API_ROLE_IS_NOT_FOUND": "API role is not found",
    "AUTHORIZATION_HEADER_IS_NOT_VALID": "Authorization header is not valid",
    "BAD_REQUEST": "Bad request",
    "FORBIDDEN_RECOGNIZER": "Forbidden recognizer",
    "IMAGE_IS_NOT_ABLE_TO_CONVERT_TO_RAW_PIXELS": "Image is not able to convert to raw pixels",
    "IMAGE_IS_NOT_VALID": "Image is not valid",
    "IMAGE_IS_NOT_VALID_BASE64_STRING": "Image is not valid base64 string",
    "IMAGE_SIZE_IS_TOO_BIG": "Image size is too big",
    "INSUFFICIENT_BALANCE": "Insufficient balance",
    "INTERNAL_SERVER_ERROR": "Internal server error",
    "INVALID_LICENSE_KEY": "Invalid license key",
    "NOT_ALLOWED_TO_EXECUTE_REQUESTED_RECOGNIZER": "Not allowed to execute requested recognizer",
    "SERVER_CANCELED_REQUEST": "Server canceled request",
    "SERVER_TOO_BUSY": "Server too busy"
};
const DefaultHeaders$1 = {
    "Accept": "application/json",
    "Content-Type": "application/json"
};
class ServiceCloud {
    constructor(apiLocation, healthcheckEndpoint, headers) {
        this.apiLocation = apiLocation;
        this.healthcheckEndpoint = healthcheckEndpoint;
        this.headers = Object.assign(DefaultHeaders$1, headers);
        // HTTP header must contain header field and value
        // @see https://tools.ietf.org/html/rfc7230#section-3.2
        for (const key in this.headers) {
            if (!key || !this.headers[key]) {
                delete this.headers[key];
            }
        }
    }
    getHealthcheckResponse() {
        const requestUrl = getSafeUrl(this.apiLocation, this.healthcheckEndpoint);
        return httpClient("GET", requestUrl, this.headers);
    }
    recognize(endpoint, payload, method = "POST") {
        const requestUrl = getSafeUrl(this.apiLocation, endpoint);
        return httpClient(method, requestUrl, this.headers, payload);
    }
}

/**
 * Copyright (c) Microblink Ltd. All rights reserved.
 */
const SelfHostedMessages = {
    "API_ROLE_IS_NOT_FOUND": "API role is not found",
    "AUTHORIZATION_HEADER_IS_NOT_VALID": "Authorization header is not valid",
    "BAD_REQUEST": "Bad request",
    "FORBIDDEN_RECOGNIZER": "Forbidden recognizer",
    "IMAGE_IS_NOT_ABLE_TO_CONVERT_TO_RAW_PIXELS": "Image is not able to convert to raw pixels",
    "IMAGE_IS_NOT_VALID": "Image is not valid",
    "IMAGE_IS_NOT_VALID_BASE64_STRING": "Image is not valid base64 string",
    "IMAGE_SIZE_IS_TOO_BIG": "Image size is too big",
    "INTERNAL_SERVER_ERROR": "Internal server error",
    "INVALID_LICENSE_KEY": "Invalid license key",
    "NOT_ALLOWED_TO_EXECUTE_REQUESTED_RECOGNIZER": "Not allowed to execute requested recognizer",
    "SERVER_CANCELED_REQUEST": "Server canceled request",
    "SERVER_TOO_BUSY": "Server too busy"
};
const DefaultHeaders = {
    "Accept": "application/json",
    "Content-Type": "application/json"
};
class ServiceSelfHosted {
    constructor(apiLocation, healthcheckEndpoint, headers) {
        this.apiLocation = apiLocation;
        this.healthcheckEndpoint = healthcheckEndpoint;
        this.headers = Object.assign(DefaultHeaders, headers);
        // HTTP header must contain header field and value
        // @see https://tools.ietf.org/html/rfc7230#section-3.2
        for (const key in this.headers) {
            if (!key || !this.headers[key]) {
                delete this.headers[key];
            }
        }
    }
    getHealthcheckResponse() {
        const requestUrl = getSafeUrl(this.apiLocation, this.healthcheckEndpoint);
        return httpClient("GET", requestUrl, this.headers);
    }
    recognize(endpoint, payload, method = "POST") {
        const requestUrl = getSafeUrl(this.apiLocation, endpoint);
        return httpClient(method, requestUrl, this.headers, payload);
    }
}

/**
 * Copyright (c) Microblink Ltd. All rights reserved.
 */
const _DEFAULT_CLOUD_LOCATION = "http://localhost";
const _DEFAULT_SELF_HOSTED_LOCATION = "http://localhost";
const _DEFAULT_HEALTHCHECK_ENDPOINT = "/v1/hc";
class Client {
    /**
     * Create new instance of Client service.
     *
     * This class requires API type and optional configuration object.
     */
    constructor(type, configuration) {
        if (!type) {
            throw "API type is not provided!";
        }
        const headers = (configuration === null || configuration === void 0 ? void 0 : configuration.headers) || {};
        const healthcheckEndpoint = (configuration === null || configuration === void 0 ? void 0 : configuration.healthcheckEndpoint) || _DEFAULT_HEALTHCHECK_ENDPOINT;
        const customApiLocation = (configuration === null || configuration === void 0 ? void 0 : configuration.apiLocation) || "";
        let apiMessages = {};
        switch (type) {
            case ApiType.Cloud:
                apiMessages = CloudMessages;
                this.service = new ServiceCloud(customApiLocation || _DEFAULT_CLOUD_LOCATION, healthcheckEndpoint, headers);
                break;
            case ApiType.SelfHosted:
                apiMessages = SelfHostedMessages;
                this.service = new ServiceSelfHosted(customApiLocation || _DEFAULT_SELF_HOSTED_LOCATION, healthcheckEndpoint, headers);
                break;
            default:
                throw "Unsupported API type!";
        }
        this.errorMessages = Object.assign(GenericMessages, apiMessages, (configuration === null || configuration === void 0 ? void 0 : configuration.messages) || {});
    }
    /**
     * Returns a promise which will resolve to `{ status: true }` if API service
     * is available.
     *
     * In case of error, promise will reject and property `details` with full
     * HTTP response will is added to object.
     *
     * Healthcheck endpoint can be configured with
     * `Configuration.healthcheckEndpoint` property. If omitted, default value
     * is used.
     */
    getHealthcheck() {
        return new Promise((resolve, reject) => {
            this.service.getHealthcheckResponse()
                .then((response) => {
                if (response.httpStatus === 200) {
                    resolve({ status: true });
                    return;
                }
                reject({ status: false, response });
            })
                .catch((response) => {
                reject({ status: false, response });
            });
        });
    }
    /**
     * Extract data from image. First argument is API endpoint, while the second
     * one is body which is sent with the request.
     *
     * This method returns a promise which will always resolve/reject to
     * `ResponseRecognition` object.
     *
     * Promise will resolve only when data has been extracted successfuly, or
     * when no data has been extracted. In every other case promise will reject.
     *
     * For full list of endpoints and related payloads see official
     * documentation for Cloud API or Self-hosted API.
     *
     * @example
     * client.recognize( "/v1/recognizers/blinkid", { "imageSource": imageBase64 } )
     *        .then( ( result: ResponseRecognition ) => console.log( result.response.data.result ) )
     *        .catch( ( error: ResponseRecognition ) => console.log( error.error.message ) );
     */
    recognize(endpoint, payload) {
        return new Promise((resolve, reject) => {
            this.service.recognize(endpoint, payload)
                .then((response) => {
                if (response.httpStatus === 200) {
                    resolve({ status: true, response });
                    return;
                }
                const errorCode = response.data.code || "GENERIC_ERROR";
                const recognitionResult = {
                    status: false,
                    response: response,
                    error: {
                        code: errorCode,
                        message: this.errorMessages[errorCode]
                    }
                };
                reject(recognitionResult);
            })
                .catch((response) => {
                let errorCode = "UNKNOWN_ERROR";
                if (response.httpStatus === -1 || (response.httpStatus % 400 < 100)) {
                    errorCode = "GENERIC_ERROR";
                }
                const recognitionResult = {
                    status: false,
                    response: response,
                    error: {
                        code: errorCode,
                        message: this.errorMessages[errorCode]
                    }
                };
                reject(recognitionResult);
            });
        });
    }
    /**
     * Get Base64 representation of an image based on provided instance of ImageData.
     */
    imageDataToBase64(imageData) {
        if (!imageData) {
            throw "Image data is not provided!";
        }
        if (!imageData.width || !imageData.height) {
            throw "Image data is malformed!";
        }
        return imageDataToBase64(imageData);
    }
}

export { ApiType, Client, GenericMessages };
//# sourceMappingURL=client-library.js.map
