'use strict';

var tslib = require('tslib');
var locator = require('./locator.js');
var index = require('./decoder/index.js');
var extractor = require('./extractor.js');
var binarizer = require('./binarizer.js');

/**
 * @module QRCode
 * @author nuintun
 * @author <NAME>
 * @license https://raw.githubusercontent.com/cozmo/jsQR/master/LICENSE
 */
function scan(matrix) {
    var locations = locator.locate(matrix);
    if (!locations) {
        return null;
    }
    for (var _i = 0, locations_1 = locations; _i < locations_1.length; _i++) {
        var location_1 = locations_1[_i];
        var extracted = extractor.extract(matrix, location_1);
        var decoded = index.decode(extracted.matrix);
        if (decoded) {
            var dimension = location_1.dimension;
            return tslib.__assign(tslib.__assign({}, decoded), { location: {
                    topLeft: extracted.mappingFunction(0, 0),
                    topRight: extracted.mappingFunction(dimension, 0),
                    bottomLeft: extracted.mappingFunction(0, dimension),
                    bottomRight: extracted.mappingFunction(dimension, dimension),
                    topLeftFinder: location_1.topLeft,
                    topRightFinder: location_1.topRight,
                    bottomLeftFinder: location_1.bottomLeft,
                    bottomRightAlignment: decoded.version > 1 ? location_1.alignmentPattern : null
                } });
        }
    }
}
var defaultOptions = {
    canOverwriteImage: true,
    greyScaleWeights: {
        red: 0.2126,
        green: 0.7152,
        blue: 0.0722,
        useIntegerApproximation: false
    },
    inversionAttempts: 'attemptBoth'
};
function disposeImageEvents(image) {
    image.onload = null;
    image.onerror = null;
}
var Decoder = /*#__PURE__*/ (function () {
    function Decoder() {
        this.options = defaultOptions;
    }
    /**
     * @public
     * @method setOptions
     * @param {object} options
     */
    Decoder.prototype.setOptions = function (options) {
        if (options === void 0) { options = {}; }
        options = options || {};
        this.options = tslib.__assign(tslib.__assign({}, defaultOptions), options);
        return this;
    };
    /**
     * @public
     * @method decode
     * @param {Uint8ClampedArray} data
     * @param {number} width
     * @param {number} height
     * @returns {DecoderResult}
     */
    Decoder.prototype.decode = function (data, width, height) {
        var options = this.options;
        var canOverwriteImage = options.canOverwriteImage, greyScaleWeights = options.greyScaleWeights, inversionAttempts = options.inversionAttempts;
        var tryInvertedFirst = inversionAttempts === 'onlyInvert' || inversionAttempts === 'invertFirst';
        var invert = tryInvertedFirst || inversionAttempts === 'attemptBoth';
        var _a = binarizer.binarize(data, width, height, invert, greyScaleWeights, canOverwriteImage), binarized = _a.binarized, inverted = _a.inverted;
        var result = scan(tryInvertedFirst ? inverted : binarized);
        if (!result && (options.inversionAttempts === 'attemptBoth' || options.inversionAttempts === 'invertFirst')) {
            result = scan(tryInvertedFirst ? binarized : inverted);
        }
        return result;
    };
    /**
     * @public
     * @method scan
     * @param {string} src
     * @returns {Promise}
     */
    Decoder.prototype.scan = function (src) {
        var _this = this;
        return new Promise(function (resolve, reject) {
            var image = new Image();
            // Image cross origin
            image.crossOrigin = 'anonymous';
            image.onload = function () {
                disposeImageEvents(image);
                var width = image.width;
                var height = image.height;
                var canvas = document.createElement('canvas');
                var context = canvas.getContext('2d');
                canvas.width = width;
                canvas.height = height;
                context.drawImage(image, 0, 0);
                var data = context.getImageData(0, 0, width, height).data;
                var result = _this.decode(data, width, height);
                if (result) {
                    return resolve(result);
                }
                return reject(new Error('failed to decode image'));
            };
            image.onerror = function () {
                disposeImageEvents(image);
                reject(new Error("failed to load image: " + src));
            };
            image.src = src;
        });
    };
    return Decoder;
}());

exports.Decoder = Decoder;
