/*
 * SDK Pullenti Unitext, version 4.33, fabruary 2026. Copyright (c) 2013-2026, Pullenti. All rights reserved. 
 * Non-Commercial Freeware and Commercial Software. 
 * This class is generated using the converter UniSharping (www.unisharping.ru) from Pullenti C# project. 
 * The latest version of the code is available on the site www.pullenti.ru
 */

const Utils = require("./../../../unisharp/Utils");
const Hashtable = require("./../../../unisharp/Hashtable");
const StringBuilder = require("./../../../unisharp/StringBuilder");

const EncodingStandard = require("./../../../util/EncodingStandard");
const EncodingWrapper = require("./../../../util/EncodingWrapper");

class EmlPart {
    
    constructor() {
        this.attrs = new Hashtable();
        this.data = null;
        this.stringData = null;
        this.stringDataPos = 0;
        this.contentType = null;
        this.contentCharset = null;
        this.contentLocation = null;
        this.contentId = null;
        this.filename = null;
        this.boundaryRef = null;
        this.boundaryId = null;
    }
    
    toString() {
        let tmp = new StringBuilder();
        if (this.boundaryId === null) 
            tmp.append("(*) ");
        tmp.append("Attrs: ").append(this.attrs.length).append(", String: ").append((this.stringData === null ? 0 : this.stringData.length)).append(", Data: ").append((this.data === null ? 0 : this.data.length));
        if (this.contentType !== null) 
            tmp.append(" ").append(this.contentType);
        if (this.contentCharset !== null) 
            tmp.append(" ").append(this.contentCharset);
        if (this.stringData !== null) {
            tmp.append("  ");
            if (this.stringData.length < 40) 
                tmp.append(this.stringData);
            else 
                tmp.append(this.stringData.substring(0, 0 + 40) + "...");
        }
        return tmp.toString();
    }
    
    static tryParse(txt, pos) {
        const MhtHelper = require("./MhtHelper");
        for (; pos.value < txt.length; pos.value++) {
            if (!Utils.isWhitespace(txt[pos.value])) 
                break;
        }
        if ((pos.value + 1) >= txt.length) 
            return null;
        let res = new EmlPart();
        if (txt[pos.value] === '-' && txt[pos.value + 1] === '-') {
            let p0 = pos.value + 2;
            for (pos.value += 2; pos.value < txt.length; pos.value++) {
                if (Utils.isWhitespace(txt[pos.value])) 
                    break;
            }
            res.boundaryId = txt.substring(p0, p0 + pos.value - p0);
            for (; pos.value < txt.length; pos.value++) {
                if (!Utils.isWhitespace(txt[pos.value])) 
                    break;
            }
        }
        let attrValue = new StringBuilder();
        for (; pos.value < txt.length; pos.value++) {
            let p0 = pos.value;
            let isAttr = false;
            for (; pos.value < txt.length; pos.value++) {
                if (Utils.isWhitespace(txt[pos.value])) 
                    break;
                else if (txt[pos.value] === ':') {
                    isAttr = true;
                    break;
                }
            }
            if (!isAttr) 
                break;
            let attrName = txt.substring(p0, p0 + pos.value - p0).trim();
            if (attrName === "From") {
            }
            pos.value++;
            attrValue.length = 0;
            for (; pos.value < txt.length; pos.value++) {
                let ch = txt[pos.value];
                if (ch === ' ' || (ch.charCodeAt(0)) === 9) {
                    if (attrValue.length === 0 || attrValue.charAt(attrValue.length - 1) === ' ') 
                        continue;
                    attrValue.append(' ');
                    continue;
                }
                if ((ch.charCodeAt(0)) !== 0xD && (ch.charCodeAt(0)) !== 0xA) {
                    attrValue.append(ch);
                    continue;
                }
                if (((pos.value + 1) < txt.length) && (ch.charCodeAt(0)) === 0xD && (txt.charCodeAt(pos.value + 1)) === 0xA) 
                    pos.value++;
                if (((pos.value + 1) < txt.length) && (((txt.charCodeAt(pos.value + 1)) === 0xD || (txt.charCodeAt(pos.value + 1)) === 0xA || !Utils.isWhitespace(txt[pos.value + 1])))) 
                    break;
            }
            if (!res.attrs.containsKey(attrName)) 
                res.attrs.put(attrName, MhtHelper._decodeString(attrValue.toString()));
        }
        let transfEnc = null;
        for (const a of res.attrs.entries) {
            if (Utils.compareStrings(a.key, "CONTENT-TYPE", true) === 0) {
                res.contentType = a.value;
                let i = a.value.indexOf(';');
                if (i > 0) 
                    res.contentType = res.contentType.substring(0, 0 + i);
                res.contentType = MhtHelper._corrString(res.contentType);
                i = a.value.indexOf("boundary=");
                if (i > 0) 
                    res.boundaryRef = MhtHelper._corrString(a.value.substring(i + 9).trim());
                i = a.value.indexOf("charset=");
                if (i > 0) 
                    res.contentCharset = MhtHelper._corrString(a.value.substring(i + 8).trim());
            }
            else if (Utils.compareStrings(a.key, "CONTENT-TRANSFER-ENCODING", true) === 0) 
                transfEnc = MhtHelper._corrString(a.value).toLowerCase();
            else if (Utils.compareStrings(a.key, "CONTENT-ID", true) === 0) {
                res.contentId = Utils.notNull(MhtHelper._corrString(a.value), "");
                if (res.contentId.length > 2 && res.contentId[0] === '<') 
                    res.contentId = res.contentId.substring(1, 1 + res.contentId.length - 2);
            }
            else if (Utils.compareStrings(a.key, "CONTENT-LOCATION", true) === 0) 
                res.contentLocation = MhtHelper._corrString(a.value);
            else if (Utils.compareStrings(a.key, "CONTENT-DISPOSITION", true) === 0) {
                let i = a.value.indexOf("filename=");
                if (i > 0) 
                    res.filename = MhtHelper._corrString(a.value.substring(i + 9).trim());
            }
        }
        if (transfEnc === null && ((res.contentType === "text/plain" || res.contentType === "text/html"))) 
            transfEnc = "7bit";
        if (transfEnc === null) 
            return res;
        let isQP = transfEnc === "quoted-printable";
        let is64 = transfEnc === "base64";
        if (res.boundaryId === null) {
            if (!isQP && !is64) 
                return res;
        }
        let enc = null;
        if (isQP && res.contentCharset !== null) {
            try {
                enc = new EncodingWrapper(EncodingStandard.UNDEFINED, res.contentCharset);
            } catch (ex) {
            }
        }
        if (isQP && enc === null) 
            enc = new EncodingWrapper(EncodingStandard.ACSII);
        let buf = new Array();
        res.stringDataPos = pos.value;
        let _data = new StringBuilder();
        for (; pos.value < txt.length; pos.value++) {
            let ch = txt[pos.value];
            if ((ch === '-' && ((pos.value + 1) < txt.length) && txt[pos.value + 1] === '-') && (((txt.charCodeAt(pos.value - 1)) === 0xD || (txt.charCodeAt(pos.value - 1)) === 0xA)) && !Utils.isNullOrEmpty(res.boundaryId)) {
                let j = 0;
                for (j = 0; (j < res.boundaryId.length) && ((pos.value + 2 + j) < txt.length); j++) {
                    if (res.boundaryId[j] !== txt[pos.value + 2 + j]) 
                        break;
                }
                if (j >= res.boundaryId.length) {
                    if (((pos.value + 4 + j) < txt.length) && txt[pos.value + j + 2] === '-' && txt[pos.value + j + 3] === '-') 
                        pos.value += (j + 4);
                    break;
                }
            }
            if (isQP && ch === '=' && ((pos.value + 2) < txt.length)) {
                if (EmlPart._toInt(txt[pos.value + 1]) >= 0 && EmlPart._toInt(txt[pos.value + 2]) >= 0) {
                    let k = (EmlPart._toInt(txt[pos.value + 1]) * 16) + EmlPart._toInt(txt[pos.value + 2]);
                    buf.push(k);
                    pos.value += 2;
                    continue;
                }
                if ((txt.charCodeAt(pos.value + 1)) === 0xD || (txt.charCodeAt(pos.value + 1)) === 0xA) {
                    pos.value++;
                    if ((txt.charCodeAt(pos.value + 1)) === 0xD || (txt.charCodeAt(pos.value + 1)) === 0xA) 
                        pos.value++;
                    continue;
                }
            }
            if (is64 && Utils.isWhitespace(ch)) 
                continue;
            if (isQP) {
                if (buf.length > 0) {
                    _data.append(enc.getString(buf, 0, -1));
                    buf.splice(0, buf.length);
                }
                _data.append(ch);
            }
            else 
                _data.append(ch);
        }
        if (is64) {
            if (_data.length > 0) {
                let str = _data.toString();
                let ii = str.indexOf("--");
                if (ii > 0) 
                    str = str.substring(0, 0 + ii);
                try {
                    res.data = Utils.decodeBase64(str);
                } catch (ex) {
                }
            }
        }
        else if (isQP) {
            if (buf.length > 0) {
                _data.append(enc.getString(buf, 0, -1));
                buf.splice(0, buf.length);
            }
            if (_data.length > 0) 
                res.stringData = _data.toString();
        }
        else {
            if (transfEnc !== "7bit") {
            }
            res.stringData = _data.toString();
        }
        return res;
    }
    
    static _toInt(ch) {
        if (ch >= '0' && ch <= '9') 
            return (ch.charCodeAt(0)) - ('0'.charCodeAt(0));
        if (ch >= 'A' && ch <= 'F') 
            return 10 + (((ch.charCodeAt(0)) - ('A'.charCodeAt(0))));
        if (ch >= 'a' && ch <= 'f') 
            return 10 + (((ch.charCodeAt(0)) - ('a'.charCodeAt(0))));
        return -1;
    }
}


module.exports = EmlPart