"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const Form_1 = require("../../Form");
const Modal_1 = require("../../Modal");
const EUSignCPFrontend_1 = __importDefault(require("./EUSignCPFrontend"));
const PROCESS_STATUS_READ_PRIVATE_KEY = 'Зчитування особистого ключа';
const PROCESS_STATUS_SIGN_FILE = 'Накладання підпису на файл';
const PROCESS_STATUS_INSTALL_LIBRARY = 'Ініціалізація криптографічної бібліотеки';
const ERROR_KM_UPDATE_LIST = 'Виникла помилка при оновленні списку носіїв ключової інформації';
const ERROR_GET_JKS_PRIVATE_KEY_INFO = 'Виникла помилка при отриманні інформації про особистий ключ';
const ERROR_NO_KEYMEDIA = 'Не обрано носій';
const ERROR_SOME = 'Помилка';
const ERROR_URL_INIT = 'Помилка запиту при ініціалізації';
const ERROR_URL_SAVE = 'Помилка запиту при відправці';
const ERROR_NO_SIGNATURES = 'Помилка зчитування ЕЦП';
class InvBulkSignModal extends Modal_1.ProcessModal {
    static create(props) {
        return new InvBulkSignModal(props);
    }
    constructor(props) {
        super({
            title: props.modalTitle || 'Підписання',
            actionText: props.actionText || 'Підписати',
            actionCallback: () => this._handleActionClick()
        });
        this.package = [];
        this.m_library = new EUSignCPFrontend_1.default();
        this.privateKey = null;
        this.privateStamp = null;
        this.m_readedPKey = null;
        this.m_readedSKey = null;
        this.m_updatingKM = false;
        this.m_updateKM = false;
        this.m_KM = null;
        this.isLoading = false;
        this.isLoaded = false;
        this.props = props;
        this._makeModal();
        this._makeHandle();
        this._LoadLibrary();
    }
    _makeModal() {
        this.modalBodyForm.append('<div class="form-group row mb-2 keyFileBlock">' + '<label class="col-form-label col-sm-3 text-right">Файл ключа</label><div class="col-sm-9">' + '<input id="pkReadFileSelectField" type="file" class="form-control h-auto"/>' + '</div></div>');
        this.modalBodyForm.append('<div class="form-group row mb-2">' + '<label class="col-form-label col-sm-3 text-right">Пароль ключа</label><div class="col-sm-9">' + '<input id="kmPassword" type="password" class="form-control">' + '</div></div>');
        this.modalBodyForm.append('<div class="form-group row mb-2 stampFileBlock">' + '<label class="col-form-label col-sm-3 text-right">Файл печатки</label><div class="col-sm-9">' + '<input id="stReadFileSelectField" type="file" class="form-control h-auto"/>' + '</div></div>');
        this.modalBodyForm.append('<div class="form-group row mb-2">' + '<label class="col-form-label col-sm-3 text-right">Пароль печатки</label><div class="col-sm-9">' + '<input id="stPassword" type="password" class="form-control">' + '</div></div>');
    }
    _makeHandle() {
        this.StopUpdateKMs();
        this.modalBody.find('#pkReadFileSelectField').on('change', (e) => {
            this.handleFileChosen(e, 'sign');
        });
        this.modalBody.find('#stReadFileSelectField').on('change', (e) => {
            this.handleFileChosen(e, 'stamp');
        });
    }
    handleFileChosen(e, fileType) {
        if (e.target.files && e.target.files[0]) {
            const file = e.target.files[0];
            const fileReader = new FileReader();
            fileReader.onloadend = () => {
                let content = fileReader.result;
                // eslint-disable-next-line no-magic-numbers
                content = content.substring(content.indexOf(';base64,') + 8);
                this.m_library.BASE64Decode(content).then((data) => {
                    if (fileType === 'sign') {
                        this.privateKey = data;
                    }
                    else if (fileType === 'stamp') {
                        this.privateStamp = data;
                    }
                });
            };
            fileReader.readAsDataURL(file);
        }
    }
    _handleActionClick() {
        var _a;
        // console.log('qwerty');
        this.showLoader(PROCESS_STATUS_READ_PRIVATE_KEY);
        this.setError('');
        const issuerCN = ((_a = this.GetSelectedCA()) === null || _a === void 0 ? void 0 : _a.issuerCNs[0]) || null;
        // console.log('issuerCn', issuerCN);
        this._saveIssuerCN(issuerCN);
        Promise.resolve()
            .then(() => {
            if (this.privateKey !== null) {
                const password = this.GetKMPasswordTextField('sign').val();
                return this.m_library.ReadPrivateKeyBinary(this.privateKey, password, null, issuerCN);
            }
            return Promise.reject(ERROR_NO_KEYMEDIA);
        })
            .then(() => {
            this.m_readedPKey = {};
            if (this.privateKey !== null) {
                this.m_readedPKey.privateKey = this.privateKey;
            }
            this.StopUpdateKMs();
        })
            .then(() => this.m_library.GetOwnCertificates())
            .then((certArray) => this.m_library.GetSupportedSignAlgos(certArray))
            .then(() => this.showLoader(PROCESS_STATUS_SIGN_FILE))
            .then(() => this.fetchInitData())
            .then(() => {
            return Promise.all(this.package.map(((item, index) => {
                return this.fetchDocContent(index);
            })));
        })
            .then(() => {
            return Promise.all(this.package.map(((item, index) => {
                return this.m_library.SignData(this.package[index].content, true, true)
                    .then((signature) => {
                    this.package[index].sign = signature;
                    // console.log(`index: ${index}; sign: ${this.package[index].sign}`);
                });
            })));
        })
            .then(() => this.m_library.ResetPrivateKey())
            .then(() => {
            if (this.privateStamp !== null) {
                const password = this.GetKMPasswordTextField('stamp').val();
                return this.m_library.ReadPrivateKeyBinary(this.privateStamp, password, null, issuerCN);
            }
            return Promise.reject(ERROR_NO_KEYMEDIA);
        })
            .then(() => {
            this.m_readedSKey = {};
            if (this.privateStamp !== null) {
                this.m_readedSKey.privateStamp = this.privateStamp;
            }
            this.StopUpdateKMs();
        })
            .then(() => this.m_library.GetOwnCertificates())
            .then((certArray) => this.m_library.GetSupportedSignAlgos(certArray))
            .then(() => {
            return Promise.all(this.package.map(((item, index) => {
                return this.m_library.AppendSign(this.package[index].content, this.package[index].sign)
                    .then((signature) => {
                    this.package[index].sign = signature;
                    // console.log(`index: ${index}; sign: ${this.package[index].sign}`);
                })
                    .then(() => this.m_library.GetSignsCount(this.package[index].sign))
                    .then((signsCount) => {
                    // console.log(`index: ${index}; signsCount: ${signsCount}`);
                    if (signsCount === 0) {
                        return Promise.reject(ERROR_NO_SIGNATURES);
                    }
                    for (let i = 0; i < signsCount; i++) {
                        let signInfo = {};
                        signInfo.signIndex = i;
                        let signerInfo = this.m_library.GetSignerInfo(i, this.package[index].sign);
                        signInfo.ownerCN = signerInfo.GetSubjCN();
                        signInfo.owner = signerInfo.GetSubjFullName();
                        signInfo.ownerCnt = signerInfo.GetSubjCountry();
                        signInfo.ownerDRFO = signerInfo.GetSubjDRFOCode();
                        signInfo.ownerTitle = signerInfo.GetSubjTitle();
                        signInfo.ownerORG = signerInfo.GetSubjOrg();
                        signInfo.ownerEDRPOU = signerInfo.GetSubjEDRPOUCode();
                        signInfo.issuerCN = signerInfo.GetIssuerCN();
                        signInfo.certSerial = signerInfo.GetSerial();
                        if (signerInfo.GetExtKeyUsages() === 'Цифрова печатка') {
                            signInfo.signType = 1;
                        }
                        else {
                            signInfo.signType = 0;
                        }
                        let signTime = this.m_library.GetSignTimeInfo(i, this.package[index].sign);
                        signInfo.signEnd = signTime.GetTime().toLocaleString().replace(',', '');
                        this.package[index].signAttr.push(signInfo);
                    }
                });
            })));
        })
            .then(() => {
            return Promise.all(this.package.map((item, index) => {
                return this.saveSignature(index);
            }));
        })
            .then((saveResp) => {
            this.hideLoader();
            this.modal.close();
            this.props.onSuccess();
        })
            .catch((error) => {
            this.hideLoader();
            this.setError(error ? error.toString() : ERROR_SOME);
        });
    }
    fetchInitData() {
        return new Promise((resolve, reject) => {
            Form_1.$.ajax({
                url: this.props.urlInit,
                method: 'GET'
            })
                .done((data) => {
                if (data && data.ok) {
                    if (data.docs && data.docs.length > 0) {
                        for (const doc of data.docs) {
                            let docRecord = { id: doc };
                            this.package.push(docRecord);
                        }
                        resolve();
                    }
                    else {
                        reject(ERROR_URL_INIT);
                    }
                }
                else {
                    reject(data.msg);
                }
            })
                .fail(() => reject(ERROR_URL_SAVE));
        });
    }
    fetchDocContent(docIndex) {
        return new Promise((resolve, reject) => {
            // console.log('fetch');
            Form_1.$.ajax({
                url: this.props.urlFetch,
                data: {
                    p_id: this.package[docIndex].id
                },
                method: 'GET'
            })
                .done((data) => {
                if (data && data.ok) {
                    this.package[docIndex].content = this.base64ToBuffer(data.msg);
                    this.package[docIndex].signAttr = [];
                    resolve();
                }
                else {
                    reject(data.msg);
                }
            })
                .fail(() => reject(ERROR_URL_SAVE));
        });
    }
    saveSignature(docIndex) {
        return new Promise((resolve, reject) => {
            let charsLength = this.package[docIndex].sign.length;
            if (charsLength === undefined) {
                reject('Some error');
            }
            else {
                const chunks = [];
                for (let i = 0; i < charsLength; i += 10000) {
                    chunks.push(this.package[docIndex].sign.substring(i, i + 10000));
                }
                let signIndexes = [];
                let signEnds = [];
                let signTypes = [];
                let issuerCNs = [];
                let certSerials = [];
                let owners = [];
                let ownerCNs = [];
                let ownerDRFOs = [];
                let ownerTitles = [];
                let ownerCnts = [];
                let ownerORGs = [];
                let ownerEDRPOUs = [];
                this.package[docIndex].signAttr.map((signAttribute) => {
                    signIndexes.push(signAttribute.signIndex);
                    signEnds.push(signAttribute.signEnd);
                    signTypes.push(signAttribute.signType);
                    signAttribute.issuerCN ? issuerCNs.push(signAttribute.issuerCN) : issuerCNs.push('null');
                    signEnds.push(signAttribute.certSerial);
                    signAttribute.owner.trim() ? signEnds.push(signAttribute.owner) : signEnds.push('null');
                    signAttribute.ownerCN ? ownerCNs.push(signAttribute.ownerCN) : signEnds.push('null');
                    signAttribute.ownerDRFO ? ownerDRFOs.push(signAttribute.ownerDRFO) : signEnds.push('null');
                    signAttribute.ownerTitle ? ownerTitles.push(signAttribute.ownerTitle) : signEnds.push('null');
                    signAttribute.ownerCnt ? ownerCnts.push(signAttribute.ownerCnt) : signEnds.push('null');
                    signAttribute.ownerORG ? ownerORGs.push(signAttribute.ownerORG) : signEnds.push('null');
                    signAttribute.ownerEDRPOU ? ownerEDRPOUs.push(signAttribute.ownerEDRPOU) : signEnds.push('null');
                });
                Form_1.$.ajax({
                    url: this.props.urlSave,
                    method: 'POST',
                    data: {
                        p_id: this.package[docIndex].id,
                        p_signature: chunks,
                        p_signIndex: signIndexes,
                        p_signEnd: signEnds,
                        p_signType: signTypes,
                        p_issuerCN: issuerCNs,
                        p_certSerial: certSerials,
                        p_owner: owners,
                        p_ownerCN: ownerCNs,
                        p_ownerDRFO: ownerDRFOs,
                        p_ownerTitle: ownerTitles,
                        p_ownerCnt: ownerCnts,
                        p_ownerORG: ownerORGs,
                        p_ownerEDRPOU: ownerEDRPOUs
                    }
                })
                    .done((data) => {
                    if (data && data.ok) {
                        resolve(data.msg);
                    }
                    else {
                        reject(data.msg);
                    }
                })
                    .fail(() => reject(ERROR_URL_SAVE));
            }
        });
    }
    _LoadLibrary() {
        if (this.isLoading || this.isLoaded) {
            return;
        }
        this.isLoading = true;
        this.showLoader(PROCESS_STATUS_INSTALL_LIBRARY);
        this.hideAction();
        this.m_library
            .loadLib()
            .then(() => this.m_library.initLib())
            .then(() => {
            this.showAction();
            this.hideLoader();
            this.isLoading = false;
            this.isLoaded = true;
        })
            .catch((error) => {
            this.hideLoader();
            this.setError(error.toString().replace('http://iit.com.ua', 'https://iit.com.ua'));
            this.modalBodyForm.hide();
            this.isLoading = false;
        });
    }
    open() {
        this._LoadLibrary();
        super.openModal();
    }
    //  =======================================================
    _saveIssuerCN(issuerCN) {
        if (issuerCN) {
            sessionStorage.setItem('CAServerIndex', issuerCN);
        }
        else {
            sessionStorage.removeItem('CAServerIndex');
        }
    }
    _getIssuerCN() {
        return sessionStorage.getItem('CAServerIndex');
    }
    //  cert
    GetSelectedCA() {
        if (this.m_library.m_CAs === null || this.m_library.m_CAs.length === 0) {
            return null;
        }
        if (this.m_library.m_CAs.length === 1) {
            return this.m_library.m_CAs[0];
        }
    }
    //  keyMedia
    StopUpdateKMs() {
        this.m_updateKM = false;
    }
    //  pass
    GetKMPasswordTextField(type) {
        if (type === 'sign') {
            return this.modalBody.find('#kmPassword');
        }
        else if (type === 'stamp') {
            // console.log('stamp Pass');
            return this.modalBody.find('#stPassword');
        }
        else {
            return;
        }
    }
    // base64 to unit8Arrau
    base64ToBuffer(base64) {
        let binaryString = window.atob(base64);
        let bytes = new Uint8Array(new ArrayBuffer(binaryString.length));
        for (let i = 0; i < binaryString.length; i++) {
            bytes[i] = binaryString.charCodeAt(i);
        }
        return bytes;
    }
}
exports.default = InvBulkSignModal;
