"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
    function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
    return new (P || (P = Promise))(function (resolve, reject) {
        function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
        function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
        function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
        step((generator = generator.apply(thisArg, _arguments || [])).next());
    });
};
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"));
//import AES from 'crypto-js/aes';
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 = 'Помилка запиту при відправці';
class PackageModal extends Modal_1.ProcessModal {
    static create(props) {
        return new PackageModal(props);
    }
    constructor(props) {
        super({
            title: props.modalTitle || 'Підписання',
            actionText: props.actionText || 'Підписати',
            actionCallback: () => this._handleActionClick(),
        });
        this.package = null;
        this.m_library = new EUSignCPFrontend_1.default();
        this.privateKey = null;
        this.m_readedPKey = 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">' +
            '<label class="col-form-label col-sm-3 text-right">Тип ключа</label><div class="col-sm-9">' +
            '<div class="form-check"><label class="form-check-label">' +
            '<input type="radio" class="form-check-input" name="pkTypesRadio" value="1" checked>' +
            'Файловий</label></div>' +
            '<div class="form-check"><label class="form-check-label">' +
            '<input type="radio" class="form-check-input" name="pkTypesRadio" value="2">' +
            'Токен (захищений носій)</label</div>' +
            '</div></div>');
        this.modalBodyForm.append('<div class="form-group row mb-2 pkCABlock">' + '<label class="col-form-label col-sm-3 text-right">ЦСК</label><div class="col-sm-9">' + '<select id="pkCASelect" class="form-control select2-init"></select>' + '</div></div>');
        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 keyDeviceBlock d-none">' + '<label class="col-form-label col-sm-3 text-right">Носій</label><div class="col-sm-9">' + '<select id="pkReadKMSelect" class="form-control select2-init"></select>' + '</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>');
        (0, Form_1.initSelect2)();
    }
    _makeHandle() {
        this.modalBody.find('[name=pkTypesRadio]').on('change', (e) => {
            const target = e.currentTarget;
            const val = Number(target.value);
            if (val === 1) {
                this.modalBody.find('.keyDeviceBlock').addClass('d-none');
                this.modalBody.find('.keyFileBlock').removeClass('d-none');
                this.modalBody.find('#pkReadFileSelectField').val('');
                this.StopUpdateKMs();
            }
            else {
                this.modalBody.find('.keyDeviceBlock').removeClass('d-none');
                this.modalBody.find('.keyFileBlock').addClass('d-none');
                this.BeginUpdateKMs();
            }
            this.modalBody.find('#kmPassword').val('');
            this.modalBody.find('#kmPassword').on('keypress', (e) => {
                if (e.code == 'Enter') {
                    e.preventDefault();
                    this._handleActionClick();
                }
            });
        });
        this.modalBody.find('#pkReadKMSelect').on('change', () => this.OnKMSelectChange());
        this.modalBody.find('#pkReadFileSelectField').on('change', (e) => {
            this.handleFileChosen(e);
        });
    }
    handleFileChosen(e) {
        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) => {
                    this.privateKey = data;
                });
            };
            fileReader.readAsDataURL(file);
        }
    }
    _handleActionClick() {
        var _a;
        this.showLoader(PROCESS_STATUS_READ_PRIVATE_KEY);
        this.setError('');
        const issuerCN = ((_a = this.GetSelectedCA()) === null || _a === void 0 ? void 0 : _a.issuerCNs[0]) || null;
        const keyMedia = this.GetSelectedKM();
        this._saveIssuerCN(issuerCN);
        Promise.resolve()
            .then(() => {
            if (keyMedia !== null) {
                return this.m_library.ReadPrivateKey(keyMedia, null, issuerCN);
            }
            else if (this.privateKey !== null) {
                const password = this.GetKMPasswordTextField().val();
                return this.m_library.ReadPrivateKeyBinary(this.privateKey, password, null, issuerCN);
            }
            return Promise.reject(ERROR_NO_KEYMEDIA);
        })
            .then(() => {
            this.m_readedPKey = {};
            if (keyMedia !== null) {
                this.m_readedPKey.keyMedia = keyMedia;
            }
            else 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.m_library.SignData('1', true, true))
            .then((signature) => this.fetchMakePackage(signature))
            .then(() => this.signPackage(this.package))
            .then(() => this.fetchSavePackage(this.package))
            .then((saveResp) => {
            if (saveResp.package) {
                return this.signPackage(saveResp.package)
                    .then(() => this.fetchSavePackage(saveResp.package))
                    .then(() => saveResp);
            }
            else {
                return saveResp;
            }
        })
            .then((saveResp) => {
            var _a;
            this.hideLoader();
            this.modal.close();
            this.props.onSuccess((_a = this.package) === null || _a === void 0 ? void 0 : _a.id, saveResp);
        })
            .catch((error) => {
            this.hideLoader();
            this.setError(error ? error.toString() : ERROR_SOME);
        });
    }
    fetchMakePackage(signature) {
        return new Promise((resolve, reject) => {
            Form_1.$.ajax({
                url: this.props.urlInit,
                method: 'POST',
                data: {
                    p_signature: signature,
                },
            })
                .done((data) => {
                if (data && data.ok) {
                    this.package = data.package;
                    resolve();
                }
                else {
                    reject(data.msg);
                }
            })
                .fail(() => reject(ERROR_URL_INIT));
        });
    }
    signPackage(itemP) {
        return itemP
            ? Promise.all(itemP.files.map((item) => __awaiter(this, void 0, void 0, function* () {
                const content = yield this.m_library.BASE64Decode(item.content);
                item.sign = yield this.m_library.SignData(content, true, true);
                return Promise.resolve();
            }))).then(() => Promise.resolve())
            : Promise.resolve();
    }
    fetchSavePackage(itemP) {
        return new Promise((resolve, reject) => {
            if (!itemP) {
                return resolve();
            }
            let data = `p_package_id=${itemP.id}`;
            itemP.files.forEach((item) => {
                data += `&${item.field}=${encodeURIComponent(item.sign)}`;
                if (item.file_id) {
                    data += `&p_file_id=${item.file_id}`;
                }
            });
            Form_1.$.ajax({
                url: this.props.urlSave,
                method: 'POST',
                data,
            })
                .done((data) => {
                if (data && data.ok) {
                    resolve(data);
                }
                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.m_library.GetKeyMedias())
            .then((KeyMedias) => {
            this.SetCAs();
            this.SetKMs(KeyMedias);
            //this.BeginUpdateKMs();
            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
    SetCAs() {
        const block = this.modalBody.find('.pkCABlock');
        const field = this.modalBody.find('#pkCASelect');
        const localStorage = this._getIssuerCN();
        const options = [];
        // eslint-disable-next-line no-magic-numbers
        if (this.m_library.m_CAs === null || this.m_library.m_CAs.length < 2) {
            block.hide();
        }
        else {
            options.push('Визначити автоматично');
            for (let i = 0; i < this.m_library.m_CAs.length; i++) {
                options.push(this.m_library.m_CAs[i].issuerCNs[0]);
            }
            field.empty();
            Form_1.$.each(options, (index, item) => {
                field.append((0, Form_1.$)('<option/>', {
                    value: index,
                    text: item,
                }));
            });
            block.show();
            if (localStorage !== null) {
                for (let i = 0; i < this.m_library.m_CAs.length; i++) {
                    if (this.m_library.m_CAs[i].issuerCNs[0] === localStorage) {
                        field.val(i);
                    }
                }
            }
        }
    }
    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];
        }
        const index = Number(this.modalBody.find('#pkCASelect').val());
        return index !== 0 ? this.m_library.m_CAs[index - 1] : null;
    }
    //  keyMedia
    GetKMsVisibleNames(keyMediaList) {
        const arr = [];
        if (keyMediaList !== null) {
            keyMediaList.forEach((item) => {
                arr.push(item.visibleName);
            });
        }
        return arr;
    }
    IsKMConnected(keyMedia, keyMediaList) {
        for (let i = 0; i < keyMediaList.length; i++) {
            const element = keyMediaList[i];
            if (keyMedia.typeIndex === element.typeIndex && keyMedia.devIndex === element.devIndex && keyMedia.visibleName === element.visibleName) {
                return true;
            }
        }
        return false;
    }
    IsKMsUpdated(keyMediaList1, keyMediaList2) {
        const visibleNames1 = this.GetKMsVisibleNames(keyMediaList1);
        const visibleNames2 = (keyMediaList2 && this.GetKMsVisibleNames(keyMediaList2)) || [];
        if (visibleNames1.length !== visibleNames2.length) {
            return true;
        }
        for (let i = 0; i < visibleNames1.length; i++) {
            if (visibleNames1[i] !== visibleNames2[i]) {
                return true;
            }
        }
        return false;
    }
    BeginUpdateKMs() {
        if (this.m_updatingKM) {
            this.m_updateKM = true;
        }
        else {
            this.m_updateKM = true;
            this.m_updatingKM = true;
            this.modal.onClose(() => {
                this.StopUpdateKMs();
            });
            this.m_library
                .GetKeyMedias()
                .then((KeyMedias) => {
                this.m_updatingKM = false;
                if (this.m_updateKM) {
                    // @ts-ignore
                    if (this.m_readedPKey !== null && this.m_readedPKey.keyMedia !== null) {
                        // @ts-ignore
                        if (!this.IsKMConnected(this.m_readedPKey.keyMedia, KeyMedias)) {
                            KeyMedias = [];
                        }
                    }
                    if (this.IsKMsUpdated(KeyMedias, this.m_library.m_KMs)) {
                        this.SetKMs(KeyMedias);
                    }
                    setTimeout(() => {
                        if (this.m_updateKM) {
                            this.BeginUpdateKMs();
                        }
                        // eslint-disable-next-line no-magic-numbers
                    }, 1e3);
                }
            })
                .catch((error) => {
                this.m_updatingKM = false;
                if (this.m_updateKM) {
                    this.setError(ERROR_KM_UPDATE_LIST, error);
                }
                this.StopUpdateKMs();
            });
        }
    }
    StopUpdateKMs() {
        this.m_updateKM = false;
    }
    SetKMs(KeyMedias) {
        this.m_library.m_KMs = KeyMedias;
        let selectedKM = null;
        if (this.m_KM) {
            for (let a = 0; a < KeyMedias.length; a++) {
                if (KeyMedias[a].type === this.m_KM.type && KeyMedias[a].device === this.m_KM.device) {
                    selectedKM = KeyMedias[a];
                    break;
                }
            }
        }
        const kmField = this.GetKMSelect();
        //  var i = this.GetKMUserTextField();
        const passwordField = this.GetKMPasswordTextField();
        /*  var n = this.GetKMPasswordConfirmTextField();
        var b = this.GetKMCertsTextField();
        var f = this.GetKMCertsSelectButton();
        var d = this.GetKMButton();*/
        const visibleNames = this.GetKMsVisibleNames(KeyMedias);
        kmField.empty();
        Form_1.$.each(visibleNames, (_index, item) => {
            kmField.append((0, Form_1.$)('<option/>', {
                value: item,
                text: item,
            }));
        });
        if (selectedKM) {
            kmField.val(selectedKM.visibleName);
            this.OnKMSelectChange();
            //  i.prop('disabled', visibleNames.length === 0);
            passwordField.prop('disabled', visibleNames.length === 0);
        }
        /*  n && n.prop('disabled', 0 == visibleNames.length),
            d.attr('disabled', 0 == visibleNames.length),
        b && b.prop('disabled', 0 == visibleNames.length),
        f && f.attr('disabled', 0 == visibleNames.length),*/
        if (visibleNames.length === 0) {
            //  i.val('');
            passwordField.val('');
            /*  n && n.val('');
            b && b.val('');*/
        }
    }
    GetKMSelect() {
        return this.modalBody.find('#pkReadKMSelect');
    }
    OnKMSelectChange() {
        this.modalBody.find('#kmPassword').val('');
    }
    GetSelectedKM() {
        if (this.m_library.m_KMs === null) {
            return null;
        }
        const c = this.GetKMSelect();
        //  const e = this.GetKMUserTextField();
        const passwordTextField = this.GetKMPasswordTextField();
        const visibleName = c.find(':selected').text();
        for (let i = 0; i < this.m_library.m_KMs.length; i++) {
            const n = this.m_library.m_KMs[i];
            if (n.visibleName === visibleName) {
                //const keyMedia = new this.m_library.euSign.EndUserKeyMedia(n);
                const keyMedia = this.m_library.CreateKeyMedia();
                keyMedia.typeIndex = n.typeIndex;
                keyMedia.devIndex = n.devIndex;
                keyMedia.password = passwordTextField.val();
                /*  if (e.is(':visible')) {
                    keyMedia.user = e.val();
                }*/
                return keyMedia;
            }
        }
        return null;
    }
    //  pass
    GetKMPasswordTextField() {
        return this.modalBody.find('#kmPassword');
    }
}
exports.default = PackageModal;
