"use strict";
var __read = (this && this.__read) || function (o, n) {
    var m = typeof Symbol === "function" && o[Symbol.iterator];
    if (!m) return o;
    var i = m.call(o), r, ar = [], e;
    try {
        while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value);
    }
    catch (error) { e = { error: error }; }
    finally {
        try {
            if (r && !r.done && (m = i["return"])) m.call(i);
        }
        finally { if (e) throw e.error; }
    }
    return ar;
};
Object.defineProperty(exports, "__esModule", { value: true });
var request = require("request");
var urlUtil = require("url");
var openGraphParse = require('open-graph').parse;
var config_1 = require("../js/config");
var arrayify = function (value) {
    if (value === void 0) { value = []; }
    return (Array.isArray(value) ? value : [value]);
};
var bufferToBase64 = function (buffer, mimeType) {
    var bufferBase64encoded = Buffer.from(buffer).toString('base64');
    return "data:" + mimeType + ";base64," + bufferBase64encoded;
};
var fetchImageAsBase64 = function (url) {
    var IMAGE_SIZE_LIMIT = 5e6;
    return new Promise(function (resolve) {
        var imageRequest = request({ encoding: null, url: encodeURI(url) }, function (error, response, body) {
            if (!error && response.statusCode === 200) {
                resolve(bufferToBase64(body, response.headers['content-type']));
            }
            else {
                resolve();
            }
        });
        var currentDownloadSize = 0;
        imageRequest.on('data', function (buffer) {
            currentDownloadSize += buffer.length;
            if (currentDownloadSize > IMAGE_SIZE_LIMIT) {
                imageRequest.abort();
                resolve();
            }
        });
    });
};
var fetchOpenGraphData = function (url) {
    var CONTENT_SIZE_LIMIT = 1e6;
    var parsedUrl = urlUtil.parse(url);
    var normalizedUrl = parsedUrl.protocol ? parsedUrl : urlUtil.parse("http://" + url);
    return new Promise(function (resolve, reject) {
        var partialBody = '';
        var getContentRequest = request.get({
            headers: {
                'User-Agent': config_1.USER_AGENT,
            },
            url: urlUtil.format(normalizedUrl),
        });
        getContentRequest.on('response', function (response) {
            if (response.statusCode !== 200) {
                return reject("Request failed with status code \"" + response.statusCode + "\".");
            }
            var contentType = response.headers['content-type'] || '';
            var isHtmlContentType = contentType.match(/.*text\/html/);
            if (!isHtmlContentType) {
                getContentRequest.abort();
                throw new Error("Unhandled format for open graph generation ('" + contentType + "')");
            }
        });
        getContentRequest.on('data', function (buffer) {
            var chunk = buffer.toString();
            partialBody += chunk;
            if (chunk.match('</head>') || partialBody.length > CONTENT_SIZE_LIMIT) {
                getContentRequest.abort();
                resolve(partialBody);
            }
        });
        getContentRequest.on('complete', function () { return reject('No head end tag found in website.'); });
        getContentRequest.on('error', function (error) { return reject(error); });
    }).then(function (body) {
        var _a = __read(body.match(/<head>[\s\S]*?<\/head>/) || [''], 1), head = _a[0];
        return openGraphParse(head);
    });
};
var updateMetaDataWithImage = function (meta, image) {
    if (image) {
        meta.image.data = image;
    }
    else {
        delete meta.image;
    }
    return meta;
};
var getOpenGraphData = function (url, callback) {
    return fetchOpenGraphData(url)
        .then(function (meta) {
        if (meta.image && meta.image.url) {
            var _a = __read(arrayify(meta.image.url), 1), imageUrl = _a[0];
            return fetchImageAsBase64(imageUrl)
                .then(function (uri) { return updateMetaDataWithImage(meta, uri); })
                .catch(function () { return meta; });
        }
        return meta;
    })
        .then(function (meta) {
        if (callback) {
            callback(null, meta);
        }
        return meta;
    })
        .catch(function (error) {
        if (callback) {
            callback(error);
        }
        throw error;
    });
};
exports.getOpenGraphData = getOpenGraphData;
//# sourceMappingURL=openGraph.js.map