import { _PdfDictionary, _PdfName, PdfRotationAngle } from '@syncfusion/ej2-pdf';
import { _getLiteralString, _hexToChar, _isArrayEqual, _skipEscapeSequence } from './utils';
import { _FontStructure } from './text-extraction/font-structure';
import { TextGlyph } from './text-structure';
import { _MatrixHelper } from './text-extraction/matrix-helper';
var _PdfTextParser = /** @class */ (function () {
    function _PdfTextParser() {
        this._textGlyph = [];
        this._textWord = [];
        this._textLine = [];
        this._extractedText = '';
        this._width = 0;
        this._height = 0;
        this._index = 0;
        this._fontSize = 0;
        this._encodedText = [];
        this._previousRect = { x: 0, y: 0, width: 0, height: 0 };
        this._boundingRectangle = { x: 0, y: 0, width: 0, height: 0 };
    }
    _PdfTextParser.prototype._translateTextMatrix = function (x, y, textMatrix) {
        var matrix = new _MatrixHelper(textMatrix._m11, textMatrix._m12, textMatrix._m21, textMatrix._m22, textMatrix._m11 * x + textMatrix._m21 * y + textMatrix._offsetX, textMatrix._m12 * x + textMatrix._m22 * y + textMatrix._offsetY);
        return matrix;
    };
    _PdfTextParser.prototype._getCharacterWidth = function (width, currentFont) {
        var advancedWidth;
        if (currentFont._type === 'TrueType') {
            advancedWidth = width;
        }
        else {
            advancedWidth = 1;
        }
        return advancedWidth;
    };
    _PdfTextParser.prototype._setNewLineWithLeading = function (textState) {
        textState._carriageReturn();
    };
    _PdfTextParser.prototype._setTextMatrix = function (element, textState) {
        textState._setTextMatrix(parseFloat(element[0]), parseFloat(element[1]), parseFloat(element[2]), parseFloat(element[3]), parseFloat(element[4]), parseFloat(element[5]));
        textState._setTextLineMatrix(parseFloat(element[0]), parseFloat(element[1]), parseFloat(element[2]), parseFloat(element[3]), parseFloat(element[4]), parseFloat(element[5]));
    };
    _PdfTextParser.prototype._beginText = function (textState, identityMatrix) {
        textState._textMatrix = identityMatrix.slice();
        textState._textLineMatrix = identityMatrix.slice();
    };
    _PdfTextParser.prototype._setFont = function (element, textState) {
        for (var j = 0; j < element.length; j++) {
            if (element[Number.parseInt(j.toString(), 10)].indexOf('/') !== -1) {
                textState._font = element[Number.parseInt(j.toString(), 10)].replace('/', '');
                break;
            }
        }
        textState._fontSize = Number(element[1]);
    };
    _PdfTextParser.prototype._moveTextPlacementAndSetLeading = function (element, textState) {
        textState._leading = -Number(element[1]);
        textState._translateTextLineMatrix(Number(element[0]), Number(element[1]));
        textState._textMatrix = textState._textLineMatrix.slice();
    };
    _PdfTextParser.prototype._setTextRise = function (element, textState) {
        textState._textRise = Number(element[0]);
    };
    _PdfTextParser.prototype._setCharSpacing = function (element, textState) {
        textState._charSpacing = Number(element[0]);
    };
    _PdfTextParser.prototype._setWordSpacing = function (element, textState) {
        textState._wordSpacing = Number(element[0]);
    };
    _PdfTextParser.prototype._setTextHorizontalScale = function (element, textState) {
        textState._textHScale = Number(element[0]) / 100;
    };
    _PdfTextParser.prototype._updateTextLeading = function (element, textState) {
        textState._leading = Number(element[0]);
    };
    _PdfTextParser.prototype._moveTextPlacement = function (element, textState) {
        textState._translateTextLineMatrix(Number(element[0]), Number(element[1]));
        textState._textMatrix = textState._textLineMatrix.slice();
    };
    _PdfTextParser.prototype._getCurrentTransform = function (font, fontMatrix, textState) {
        var tsm = [textState._fontSize * textState._textHScale, 0, 0, textState._fontSize, 0, textState._textRise];
        if (font._isType3Font && textState._fontSize <= 1 && !_isArrayEqual(fontMatrix, [0.001, 0, 0, 0.001, 0, 0])) {
            var glyphHeight = font._boundingBox[3] - font._boundingBox[1];
            if (glyphHeight > 0) {
                tsm[3] *= glyphHeight * fontMatrix[3];
            }
        }
        return this._transform(textState._ctm, this._transform(textState._textMatrix, tsm));
    };
    _PdfTextParser.prototype._isFoundText = function (x, y, page, redactBounds) {
        var isFound = false;
        var location = [];
        if (y < 0) {
            y = -y;
        }
        var rectValue = { x: 0, y: 0, width: 0, height: 0 };
        var redactionBounds = redactBounds;
        location = this._getRelativeLocation(x, y, page);
        var yPosition = Math.floor(location[1]);
        var count = redactionBounds.length;
        for (var i = 0; i < count; i++) {
            var bounds = redactionBounds[i]._bounds;
            var ypos = Math.floor(redactionBounds[Number.parseInt(i.toString(), 10)]._bounds.y);
            if (ypos === yPosition || (ypos === (yPosition - 1)) || (ypos === (yPosition + 1))) {
                isFound = true;
                break;
            }
            if ((bounds.y >= yPosition && yPosition >= (bounds.y - bounds.height)) || (bounds.y <= yPosition && yPosition <= (bounds.y
                + bounds.height))) {
                isFound = true;
                break;
            }
            var size = page.size;
            yPosition = Math.floor(size.height - y);
            if ((bounds.y >= yPosition && yPosition >= (bounds.y - bounds.height)) || (bounds.y <= yPosition && yPosition <= (bounds.y +
                bounds.height))) {
                isFound = true;
                break;
            }
            if (rectValue.y !== 0) {
                if (rectValue.y < 0) {
                    rectValue.y = -rectValue.y;
                }
                yPosition = Math.floor(y + rectValue.y);
                if ((bounds.y >= yPosition && yPosition >= (bounds.y - bounds.height)) || (bounds.y <= yPosition && yPosition <= (bounds.y +
                    bounds.height))) {
                    isFound = true;
                    break;
                }
                if (rectValue.height < 0) {
                    rectValue.height = -rectValue.height;
                }
                yPosition = Math.floor(rectValue.height - yPosition);
                if ((bounds.y >= yPosition && yPosition >= (bounds.y - bounds.height)) || (bounds.y <= yPosition && yPosition <= (bounds.y +
                    bounds.height))) {
                    isFound = true;
                    break;
                }
            }
        }
        return isFound;
    };
    _PdfTextParser.prototype._getRelativeLocation = function (x, y, page) {
        var location = [x, y];
        if (page.rotation === PdfRotationAngle.angle90) {
            location[0] = page.size.height - y;
            location[1] = x;
        }
        else if (page.rotation === PdfRotationAngle.angle270) {
            location[0] = page.size.width - x;
            location[1] = y;
        }
        return location;
    };
    _PdfTextParser.prototype._transform = function (m1, m2) {
        return [m1[0] * m2[0] + m1[2] * m2[1], m1[1] * m2[0] + m1[3] * m2[1], m1[0] * m2[2] + m1[2] * m2[3], m1[1] * m2[2] + m1[3] * m2[3],
            m1[0] * m2[4] + m1[2] * m2[5] + m1[4], m1[1] * m2[4] + m1[3] * m2[5] + m1[5]];
    };
    _PdfTextParser.prototype._getCropOrMediaBox = function (page) {
        var cropOrMediaBox = [];
        if (page.cropBox[0] !== 0 || page.cropBox[3] !== 0) {
            cropOrMediaBox[0] = page.cropBox[0];
            cropOrMediaBox[1] = page.cropBox[2];
            cropOrMediaBox[2] = page.cropBox[3];
        }
        else if (page.mediaBox[0] !== 0 || page.mediaBox[3] !== 0) {
            cropOrMediaBox[0] = page.mediaBox[0];
            cropOrMediaBox[1] = page.mediaBox[2];
            cropOrMediaBox[2] = page.mediaBox[3];
        }
        return cropOrMediaBox;
    };
    _PdfTextParser.prototype._getSplitText = function (encodedText, font, inputText, isForRedaction) {
        if (isForRedaction === void 0) { isForRedaction = false; }
        var decodedList = [];
        var key = '';
        var encoding = font._encoding;
        var inputType = isForRedaction ? [] : undefined;
        var tempString = '';
        var splittedText;
        var isHex = false;
        var isWidth;
        switch (encodedText[0]) {
            case '(':
                encodedText = encodedText.substring(1, encodedText.length - 1);
                if (encodedText.indexOf('\\\n') !== -1 || encodedText.indexOf('\\(') !== -1 || encodedText.indexOf('\\)') !== -1) {
                    if (encodedText.indexOf('\\\n') !== -1) {
                        encodedText = encodedText.replace(/\\\n/g, '');
                    }
                    if (encodedText.indexOf('\\(') !== -1) {
                        encodedText = encodedText.replace(/\\\(/g, '(');
                    }
                    if (encodedText.indexOf('\\)') !== -1) {
                        encodedText = encodedText.replace(/\\\)/g, ')');
                    }
                }
                if (encodedText.indexOf('\\n') !== -1) {
                    encodedText = encodedText.replace(/\\n/g, '\n');
                }
                if (encodedText.indexOf('\\r') !== -1) {
                    encodedText = encodedText.replace(/\\r/g, '\r');
                }
                encodedText = _getLiteralString(encodedText, encoding);
                encodedText = _skipEscapeSequence(encodedText);
                key = encodedText + 's';
                decodedList.push(key);
                if (isForRedaction) {
                    inputType.push(' ');
                }
                break;
            case '[':
                splittedText = inputText;
                isHex = false;
                for (var i = 0; i < splittedText.length; i++) {
                    var input = splittedText[Number.parseInt(i.toString(), 10)];
                    isWidth = false;
                    if (input.indexOf('\\\n') !== -1) {
                        input = input.replace(/\\\n/g, '');
                    }
                    if (input[0] === '<') {
                        isHex = true;
                        if (isForRedaction) {
                            inputType.push(input);
                        }
                        input = input.slice(1, -1);
                    }
                    else if (input[0] === '(') {
                        input = input.slice(1, -1);
                    }
                    else if (input.length > 0) {
                        input = input.replace('\n', '');
                        decodedList.push(input);
                        if (isForRedaction) {
                            inputType.push(' ');
                        }
                        continue;
                    }
                    if (isHex) {
                        tempString = _hexToChar(input);
                    }
                    else {
                        tempString = _getLiteralString(input, encoding);
                        if (tempString.indexOf('\\') !== -1) {
                            tempString = _skipEscapeSequence(tempString);
                        }
                    }
                    if (!isWidth && input.length > 0) {
                        key = tempString + 's';
                        decodedList.push(key);
                        key = '';
                        if (isForRedaction && !isHex) {
                            inputType.push(' ');
                        }
                        isHex = false;
                    }
                }
                break;
            case '<':
                encodedText = encodedText.substring(1, encodedText.length - 1);
                tempString = _hexToChar(encodedText);
                key = tempString + 's';
                decodedList.push(key);
                break;
        }
        return isForRedaction ? { decodedList: decodedList, inputType: inputType } : { decodedList: decodedList };
    };
    _PdfTextParser.prototype._getPageRotation = function (textState) {
        var rotation = 0;
        if (textState._textMatrix[0] === 0 && textState._textMatrix[1] > 0 && textState._textMatrix[2] < 0 &&
            textState._textMatrix[3] >= 0) {
            rotation = 90;
        }
        else if (textState._textMatrix[0] === 0 && textState._textMatrix[1] < 0 && textState._textMatrix[2] > 0
            && textState._textMatrix[3] === 0) {
            rotation = 270;
        }
        return rotation;
    };
    _PdfTextParser.prototype._splitHexString = function (hexString) {
        var hexList = [];
        if (typeof (hexString) === 'undefined') {
            return hexList;
        }
        hexString = hexString.slice(1, -1);
        var size = hexString.startsWith('0') ? 4 : 2;
        for (var i = 0; i < hexString.length; i += size) {
            var chunk = hexString.substring(i, i + size);
            if (chunk.indexOf('\n') !== -1) {
                var extraChar = hexString.charAt(i + size);
                chunk += extraChar;
                i++;
            }
            hexList.push(chunk);
        }
        return hexList;
    };
    _PdfTextParser.prototype._getFallBackFontDictionary = function (crossReference) {
        var dictionary = new _PdfDictionary(crossReference);
        dictionary.set('BaseFont', new _PdfName('Helvetica'));
        dictionary.set('Type', new _PdfName('FallbackType'));
        dictionary.set('Subtype', new _PdfName('FallbackType'));
        dictionary.set('Encoding', new _PdfName('WinAnsiEncoding'));
        return dictionary;
    };
    _PdfTextParser.prototype._processCommand = function (token, element, state) {
        var args = [];
        switch (token) {
            case 'q':
                state._save();
                break;
            case 'Q':
                state._restore();
                break;
            case 'cm':
                args = [parseFloat(element[0]), parseFloat(element[1]), parseFloat(element[2]), parseFloat(element[3]), parseFloat(element[4]), parseFloat(element[5])];
                state._transform(args);
        }
    };
    _PdfTextParser.prototype._getTextFont = function (fontCollection, textState, crossReference) {
        var currentFont;
        if (fontCollection.get(textState._font)) {
            currentFont = fontCollection.get(textState._font);
        }
        else {
            var dictionary = this._getFallBackFontDictionary(crossReference);
            currentFont = new _FontStructure(dictionary, crossReference);
        }
        return currentFont;
    };
    _PdfTextParser.prototype._getTextContentItem = function (currentFont, text, extraSpacing, textState, page, tempString, previousRect, extractedText, parser, textGlyphs, hex, index, encodedText) {
        text = text.slice(0, -1);
        var fontSize = 0;
        var isHex = false;
        var textBounds = { x: 0, y: 0, width: 0, height: 0 };
        if (typeof (hex) !== 'undefined' && hex.length > 0) {
            isHex = true;
        }
        var glyphs = currentFont._charsToGlyphs(text); // eslint-disable-line
        var ii = glyphs.length;
        var scale = 0;
        if (currentFont._fontMatrix) {
            scale = currentFont._fontMatrix[0];
        }
        else {
            currentFont._fontMatrix = [0.001, 0, 0, 0.001, 0, 0];
            scale = 0.001;
        }
        var rotation = this._getPageRotation(textState);
        for (var i = 0; i < ii; i++) {
            var glyph = glyphs[Number.parseInt(i.toString(), 10)]; // eslint-disable-line
            // this._resultantText += glyph._unicode;
            var width = void 0;
            var charSpacing = textState._charSpacing + (i + 1 === ii ? extraSpacing : 0);
            var glyphWidth = glyph._width;
            if (currentFont._vertical) {
                glyphWidth = glyph.vmetric ? glyph.vmetric[0] : -glyphWidth;
            }
            var scaledDim = glyphWidth * scale * textState._fontSize;
            width = scale * glyphWidth;
            var height = 0;
            var tempFontSize = 0;
            var transform = this._getCurrentTransform(currentFont, currentFont._fontMatrix, textState);
            var cropOrMediaBox = this._getCropOrMediaBox(page);
            var x = transform[4];
            var y = 0;
            if (page.rotation === PdfRotationAngle.angle180 || page.rotation === PdfRotationAngle.angle270) {
                x = cropOrMediaBox[1] - x;
            }
            else {
                x = x - cropOrMediaBox[0];
            }
            if (page.rotation === PdfRotationAngle.angle90 || page.rotation === PdfRotationAngle.angle180) {
                y = transform[5];
            }
            else {
                y = cropOrMediaBox[2] - transform[5];
            }
            if (transform[0] > 0 && !currentFont._dictionary.has('DescendantFonts')) {
                tempFontSize = transform[0];
            }
            else if (transform[3] > 0 && currentFont._dictionary.has('DescendantFonts')) {
                tempFontSize = transform[3];
            }
            else if (transform[1] !== 0 && transform[2] !== 0) {
                if (transform[1] < 0) {
                    tempFontSize = -transform[1];
                }
                else {
                    tempFontSize = transform[1];
                }
            }
            if (!currentFont._vertical) {
                height = transform[0] > 0 && transform[0] > 1 ? tempFontSize : Math.hypot(transform[2], transform[3]);
            }
            else {
                width = Math.hypot(transform[0], transform[1]);
            }
            if (glyph._unicode === ' ') {
                if (!currentFont._vertical) {
                    charSpacing += scaledDim + textState._wordSpacing;
                    textState._translateTextMatrix(charSpacing * (textState._textHScale), 0);
                    width *= tempFontSize;
                    if (rotation === 90) {
                        y = y - width;
                        x = x - height + height / 4;
                    }
                    else if (page.rotation === PdfRotationAngle.angle90 || page.rotation === PdfRotationAngle.angle180) {
                        y = y - height + (height / 1.3333333333333333);
                    }
                    else {
                        y = y - height / 1.3333333333333333;
                    }
                }
                else {
                    charSpacing += -scaledDim + textState._wordSpacing;
                    textState._translateTextMatrix(0, -charSpacing);
                    height += tempFontSize;
                    x = x - width / 2;
                }
            }
            if (glyph._unicode !== ' ') {
                if (!currentFont._vertical) {
                    scaledDim *= textState._textHScale;
                    textState._translateTextMatrix(scaledDim, 0);
                    width *= tempFontSize;
                    if (rotation === 90) {
                        y = y - width;
                        x = x - height + height / 4;
                    }
                    else if (page.rotation === PdfRotationAngle.angle90 || page.rotation === PdfRotationAngle.angle180) {
                        y = y - height + (height / 1.3333333333333333);
                    }
                    else {
                        y = y - (height / 1.3333333333333333);
                    }
                }
                else {
                    textState._translateTextMatrix(0, scaledDim);
                    scaledDim = Math.abs(scaledDim);
                    height += scaledDim + tempFontSize;
                    x = x - width / 2;
                }
            }
            if (page.rotation === PdfRotationAngle.angle0 && rotation === 90) {
                textBounds = { x: x, y: y, width: height, height: width };
            }
            else if (page.rotation === PdfRotationAngle.angle90) {
                textBounds = { x: y, y: x, width: height, height: width };
            }
            else if (page.rotation === PdfRotationAngle.angle180) {
                textBounds = { x: x - width, y: y, width: width, height: height };
            }
            else if (page.rotation === PdfRotationAngle.angle270) {
                textBounds = { x: y, y: x - width, width: height, height: width };
            }
            else {
                textBounds = { x: x, y: y, width: width, height: height };
            }
            extractedText += glyph._unicode;
            if (typeof (textGlyphs) !== 'undefined') {
                var bounds = textBounds;
                var textGlyph = new TextGlyph();
                if (isHex && hex.length >= i) {
                    textGlyph._isHex = true;
                    encodedText[Number.parseInt(index.toString(), 10)] = hex[Number.parseInt(i.toString(), 10)];
                }
                else {
                    encodedText[Number.parseInt(index.toString(), 10)] = glyph._fontCharacter;
                }
                textGlyph._text = glyph._unicode;
                textGlyph._bounds = bounds;
                textGlyph._fontName = currentFont._name;
                textGlyph._fontStyle = currentFont._fontStyle;
                textGlyph._fontSize = textState._fontSize;
                textGlyph._color = textState._textColor;
                textGlyph._width = glyph._width;
                textGlyph._charSpacing = textState._charSpacing;
                textGlyph._wordSpacing = textState._wordSpacing;
                index++;
                if (page.rotation !== PdfRotationAngle.angle0) {
                    textGlyph._isRotated = true;
                }
                else {
                    textGlyph._isRotated = false;
                }
                textGlyphs.push(textGlyph);
            }
            else {
                fontSize = textState._fontSize;
                var result = parser._splitWords(glyph._unicode, tempString, currentFont._name, // eslint-disable-line
                currentFont._fontStyle, page, rotation, textState._textColor, textState._fontSize, textBounds, previousRect);
                previousRect = result.previousRect;
                tempString = result.tempString;
                if (previousRect) {
                    previousRect = { x: textBounds.x, y: textBounds.y,
                        width: textBounds.width, height: textBounds.height };
                }
                else {
                    previousRect = { x: 0, y: 0, width: 0, height: 0 };
                }
            }
            if (charSpacing && glyph._unicode !== ' ') {
                if (!currentFont._vertical) {
                    textState._translateTextMatrix(charSpacing * textState._textHScale, 0);
                }
                else {
                    textState._translateTextMatrix(0, -charSpacing);
                }
            }
        }
        if (typeof (textGlyphs) !== 'undefined') {
            return { textGlyphs: textGlyphs, extractedText: extractedText, encodedText: encodedText, index: index };
        }
        else {
            return { tempString: tempString, extractedText: extractedText, fontSize: fontSize, previousRect: previousRect };
        }
    };
    return _PdfTextParser;
}());
export { _PdfTextParser };
