import * as i0 from '@angular/core';
import { NgModule } from '@angular/core';

class CertificateGenModel {
    constructor(guid) {
        if (!guid) {
            throw Error('Не передан GUID для формирования уникального контейнера');
        }
        // проверка подлинности клиента
        this.templateId = '1.3.6.1.5.5.7.3.2';
        this.containerName = '\\\\.\\HDImage\\0000_SLN_' + guid;
        this.providerName = 'Crypto-Pro GOST R 34.10-2012 Cryptographic Service Provider';
        this.providerType = 80;
        this.keyLength = 512;
    }
}
class DnCertificate {
    constructor(item) {
        this.commonName = item.commonName;
        this.surname = item.surname;
        this.givenName = item.givenName;
        this.country = item.country;
        this.state = item.state;
        this.locality = item.locality;
        this.street = item.street;
        this.email = item.email;
        this.inn = item.inn;
        this.snils = item.snils;
        this.unstructuredName = item.unstructuredName;
    }
    _makePartDN(name, oid, value, useQuotesForValues = true, useOids = true) {
        if (!value) {
            return "";
        }
        if (useQuotesForValues)
            return (useOids ? oid : name) + "=\"" + this._x500Encode(value) + "\"";
        return (useOids ? oid : name) + "=" + this._x500Encode(value);
    }
    _x500Encode(source) {
        if (source.includes("\"") || source.includes(",")) {
            return source.replace(/\"/g, "\"\"");
        }
        return source;
    }
    _snils(snils) {
        return snils.match(/\d*/gm).filter(x => x != '').join('');
    }
}
class JuridicalCertificate extends DnCertificate {
    constructor(item) {
        super(item);
        this.organization = item.organization;
        this.organizationUnit = item.organizationUnit;
        this.title = item.title;
        this.innLE = item.innLE;
        this.ogrn = item.ogrn;
    }
    getDn() {
        const array = new Array();
        array.push(this._makePartDN("CN", "2.5.4.3", this.commonName));
        array.push(this._makePartDN("SN", "2.5.4.4", this.surname));
        array.push(this._makePartDN("G", "2.5.4.42", this.givenName));
        array.push(this._makePartDN("O", "2.5.4.10", this.organization));
        array.push(this._makePartDN("OU", "2.5.4.11", this.organizationUnit));
        array.push(this._makePartDN("T", "2.5.4.12", this.title));
        array.push(this._makePartDN("C", "2.5.4.6", this.country));
        array.push(this._makePartDN("S", "2.5.4.8", this.state));
        array.push(this._makePartDN("L", "2.5.4.7", this.locality));
        array.push(this._makePartDN("STREET", "2.5.4.9", this.street));
        array.push(this._makePartDN("E", "1.2.840.113549.1.9.1", this.email));
        array.push(this._makePartDN("UN", "1.2.840.113549.1.9.2", this.unstructuredName));
        array.push(this._makePartDN("INN", "1.2.643.3.131.1.1", this.inn));
        array.push(this._makePartDN("INNLE", "1.2.643.100.4", this.innLE));
        array.push(this._makePartDN("OGRN", "1.2.643.100.1", this.ogrn));
        array.push(this._makePartDN("SNILS", "1.2.643.100.3", this._snils(this.snils)));
        return array.filter(x => x !== "").join(', ');
    }
}
class IndividualCertificate extends DnCertificate {
    constructor(item) {
        super(item);
        this.organization = item.organization;
        this.ogrnip = item.ogrnip;
    }
    getDn() {
        const array = new Array();
        array.push(this._makePartDN("CN", "2.5.4.3", this.commonName));
        array.push(this._makePartDN("SN", "2.5.4.4", this.surname));
        array.push(this._makePartDN("G", "2.5.4.42", this.givenName));
        array.push(this._makePartDN("O", "2.5.4.10", this.organization));
        array.push(this._makePartDN("C", "2.5.4.6", this.country));
        array.push(this._makePartDN("S", "2.5.4.8", this.state));
        array.push(this._makePartDN("L", "2.5.4.7", this.locality));
        array.push(this._makePartDN("STREET", "2.5.4.9", this.street));
        array.push(this._makePartDN("E", "1.2.840.113549.1.9.1", this.email));
        array.push(this._makePartDN("UN", "1.2.840.113549.1.9.2", this.unstructuredName));
        array.push(this._makePartDN("INN", "1.2.643.3.131.1.1", this.inn));
        array.push(this._makePartDN("OGRNIP", "1.2.643.100.5", this.ogrnip));
        array.push(this._makePartDN("SNILS", "1.2.643.100.3", this._snils(this.snils)));
        return array.filter(x => x !== "").join(', ');
    }
}
class PhysicalCertificate extends DnCertificate {
    constructor(item) {
        super(item);
    }
    getDn() {
        const array = new Array();
        array.push(this._makePartDN("CN", "2.5.4.3", this.commonName));
        array.push(this._makePartDN("SN", "2.5.4.4", this.surname));
        array.push(this._makePartDN("G", "2.5.4.42", this.givenName));
        array.push(this._makePartDN("C", "2.5.4.6", this.country));
        array.push(this._makePartDN("S", "2.5.4.8", this.state));
        array.push(this._makePartDN("L", "2.5.4.7", this.locality));
        array.push(this._makePartDN("STREET", "2.5.4.9", this.street));
        array.push(this._makePartDN("E", "1.2.840.113549.1.9.1", this.email));
        array.push(this._makePartDN("UN", "1.2.840.113549.1.9.2", this.unstructuredName));
        array.push(this._makePartDN("INN", "1.2.643.3.131.1.1", this.inn));
        array.push(this._makePartDN("SNILS", "1.2.643.100.3", this._snils(this.snils)));
        return array.filter(x => x !== "").join(', ');
    }
}

class CertificateGeneratorBase {
    setTimeoutRetry(interval, retryCount, check, body, fail) {
        const checkPeriod = interval;
        let checkRetryCount = retryCount;
        const tryWrap = function () {
            checkRetryCount--;
            if (!check()) {
                if (checkRetryCount > 0) {
                    window.setTimeout(tryWrap, checkPeriod);
                    return;
                }
                else {
                    if (fail) {
                        fail();
                        return;
                    }
                }
            }
            body();
        };
        window.setTimeout(tryWrap, checkPeriod);
    }
}

class CertificateGeneratorAsync extends CertificateGeneratorBase {
    constructor() {
        super();
        this._errors = '';
    }
    createRequest(genCert) {
        if (!genCert.providerName && !genCert.providerType) {
            console.error('Для ' + genCert.containerName + ' не указан провайдер для формирования ключа.');
            return;
        }
        const promise = new Promise((resolve, reject) => {
            window.cadesplugin.CreateObjectAsync("X509Enrollment.CX509PrivateKey").then((pKey) => {
                return pKey;
            }).then((pKey) => {
                return pKey.propset_ProviderName(genCert.providerName).then(() => {
                    return pKey;
                });
            }).then((pKey) => {
                return pKey.propset_ProviderType(genCert.providerType).then(() => {
                    return pKey;
                });
            }).then((pKey) => {
                return pKey.propset_KeySpec(1).then(() => {
                    return pKey;
                });
            }).then((pKey) => {
                return pKey.propset_ExportPolicy(1).then(() => {
                    return pKey;
                });
            }).then((pKey) => {
                return pKey.propset_ContainerName(genCert.containerName).then(() => {
                    return pKey;
                });
            }).then((pKey) => {
                if (genCert.keyLength)
                    return pKey.propset_Length(genCert.keyLength).then(() => {
                        return pKey;
                    });
                return pKey;
            }).then((pKey) => {
                return window.cadesplugin.CreateObjectAsync("X509Enrollment.CX509CertificateRequestPkcs10")
                    .then((request) => {
                    //Инициализируем запрос по заданному закрытому ключу:
                    return request.InitializeFromPrivateKey(1, pKey, "")
                        .then(() => {
                        return request;
                    });
                }).then((request) => {
                    return window.cadesplugin.CreateObjectAsync("X509Enrollment.CX500DistinguishedName")
                        .then((dn) => {
                        return dn.Encode(genCert.dn, 0)
                            .then(() => {
                            return request.propset_Subject(dn).then(() => {
                                return request;
                            });
                        });
                    });
                });
            }).then((request) => {
                return this._addOids(request, genCert.oids, reject);
            })
                .then((request) => {
                return this._addTemplate(request, genCert.templateId);
            })
                .then((request) => {
                return this._addKeyUsage(request);
            }).then((request) => {
                return this._enrollRequest(request);
            }).then((request) => {
                resolve(request);
            }).catch((ex) => {
                reject(ex);
            });
        });
        return promise;
    }
    // response - сертификат в формате DER
    installResponse(response) {
        var promise = new Promise((resolve, reject) => {
            this.setTimeoutRetry(1000, 10, () => {
                return window.cadesplugin && window.cadesplugin.CreateObjectAsync;
            }, () => {
                if (window.console && window.console.log) {
                    window.console.log('install-response: ' + response);
                }
                window.cadesplugin.CreateObjectAsync("X509Enrollment.CX509Enrollment").then((enroll) => {
                    enroll.Initialize(1).then(() => {
                        // AllowNone = 0, AllowUntrustedRoot = 4; XCN_CRYPT_STRING_BASE64_ANY = 6
                        enroll.InstallResponse(4, response, 6, "").then((result) => {
                            resolve(result);
                        }).catch((ex) => {
                            ex.installedResponse = response;
                            reject(ex);
                        });
                    }).catch((ex) => { reject(ex); });
                })
                    .catch((ex) => { reject(ex); });
            }, () => {
                reject({ message: 'Ну удаётся найти window.cadesplugin.CreateObjectAsync', number: -1 });
            });
        });
        return promise;
    }
    _enrollRequest(req) {
        return window.cadesplugin.CreateObjectAsync("X509Enrollment.CX509Enrollment").then((enroll) => {
            return enroll
                .InitializeFromRequest(req)
                .then(() => {
                return enroll.CreateRequest(1);
            });
        });
    }
    _addTemplate(req, templateId) {
        return window.cadesplugin.CreateObjectAsync("X509Enrollment.CObjectId")
            .then((templateObjId) => {
            return templateObjId.InitializeFromValue(templateId)
                .then(() => {
                return templateObjId;
            });
        })
            .then((templateObjId) => {
            return window.cadesplugin.CreateObjectAsync("X509Enrollment.CX509ExtensionTemplate").then((templateObj) => {
                return templateObj.InitializeEncode(templateObjId, 1, 0).then(() => {
                    return templateObj;
                });
            });
        })
            .then((templateObj) => {
            return req.X509Extensions.then((ex) => {
                return ex.Add(templateObj).then(() => {
                    return req;
                });
            });
        });
    }
    _addKeyUsage(req) {
        return window.cadesplugin.CreateObjectAsync("X509Enrollment.CX509ExtensionKeyUsage").then((ku) => {
            const CERT_DATA_ENCIPHERMENT_KEY_USAGE = 0x10;
            const CERT_KEY_ENCIPHERMENT_KEY_USAGE = 0x20;
            const CERT_DIGITAL_SIGNATURE_KEY_USAGE = 0x80;
            const CERT_NON_REPUDIATION_KEY_USAGE = 0x40;
            return ku.InitializeEncode(CERT_KEY_ENCIPHERMENT_KEY_USAGE |
                CERT_DATA_ENCIPHERMENT_KEY_USAGE |
                CERT_DIGITAL_SIGNATURE_KEY_USAGE |
                CERT_NON_REPUDIATION_KEY_USAGE).then(() => {
                return req.X509Extensions.then((ex) => {
                    return ex.Add(ku).then(() => {
                        return req;
                    });
                });
            });
        });
    }
    _addOids(req, strOids, reject) {
        return window.cadesplugin.CreateObjectAsync("X509Enrollment.CObjectIds").then((ekuIds) => {
            if (!strOids) {
                strOids = "";
            }
            const oids = strOids.split(';');
            if (oids instanceof Array) {
                const promises = [];
                for (let i = 0; i < oids.length; i++) {
                    if (oids[i] !== "") {
                        promises.push(this._getOid(oids[i]).then((ekuId) => {
                            return ekuIds.Add(ekuId).then((ekuId) => { return ekuId; });
                        }));
                    }
                }
                Promise.all(promises).then((values) => {
                    return ekuIds;
                }).then((ekuIds) => {
                    return ekuIds.Count.then((count) => {
                        if (count > 0) {
                            if (this._errors !== "") {
                                reject(this._errors);
                            }
                            return window.cadesplugin.CreateObjectAsync("X509Enrollment.CX509ExtensionEnhancedKeyUsage")
                                .then((ekuExtension) => {
                                return ekuExtension.InitializeEncode(ekuIds).then(() => { return ekuExtension; });
                            }).then((ekuExtension) => {
                                return req.X509Extensions.then((ex) => {
                                    return ex.Add(ekuExtension)
                                        .then(() => {
                                        return req;
                                    });
                                });
                            });
                        }
                        return req;
                    });
                });
            }
            return req;
        });
    }
    _getOid(value) {
        return window.cadesplugin.CreateObjectAsync("X509Enrollment.CObjectId")
            .then((ekuId) => {
            return ekuId.InitializeFromValue(value)
                .then(() => {
                return ekuId;
            })
                .catch((ex) => {
                this._errors += "{Error on add OID " + value + ", '" + JSON.stringify(ex) + "'} ";
            });
        });
    }
}

class CertificateGeneratorSync extends CertificateGeneratorBase {
    constructor() {
        super();
    }
    createRequest(genCert) {
        const promise = new Promise(function (resolve, reject) {
            try {
                if (!genCert.providerName && !genCert.providerType) {
                    console.error('Для ' + genCert.containerName + ' не указан провайдер для формирования ключа.');
                    return;
                }
                var errors = "";
                //Приватный ключ
                var pKey = window.cadesplugin.CreateObject("X509Enrollment.CX509PrivateKey");
                pKey.ProviderName = genCert.providerName;
                pKey.ProviderType = genCert.providerType;
                pKey.KeySpec = 1; //X509KeySpec.XCN_AT_KEYEXCHANGE
                pKey.ExportPolicy = 1; //XCN_NCRYPT_ALLOW_EXPORT_FLAG
                pKey.ContainerName = genCert.containerName;
                if (genCert.keyLength) {
                    pKey.Length = genCert.keyLength;
                }
                //Запрос на сертификат
                var req = window.cadesplugin.CreateObject("X509Enrollment.CX509CertificateRequestPkcs10");
                req.InitializeFromPrivateKey(1, pKey, "");
                //dn
                const dn = window.cadesplugin.CreateObject("X509Enrollment.CX500DistinguishedName");
                dn.Encode(genCert.dn, 0);
                req.Subject = dn;
                const ekuIds = window.cadesplugin.CreateObject("X509Enrollment.CObjectIds");
                if (!genCert.oids) {
                    genCert.oids = "";
                }
                const oids = genCert.oids.split(';');
                if (oids instanceof Array) {
                    for (let i = 0; i < oids.length; i++) {
                        const ekuId = window.cadesplugin.CreateObject("X509Enrollment.CObjectId");
                        if (oids[i] !== "") {
                            try {
                                ekuId.InitializeFromValue(oids[i]);
                                ekuIds.Add(ekuId);
                            }
                            catch (ex) {
                                errors += "{Error on add OID " + oids[i] + ", '" + JSON.stringify(ex) + "'} ";
                            }
                        }
                    }
                }
                ;
                if (ekuIds.Count > 0) {
                    if (errors !== "") {
                        throw errors;
                    }
                    var ekuExtension = window.cadesplugin.CreateObject("X509Enrollment.CX509ExtensionEnhancedKeyUsage");
                    ekuExtension.InitializeEncode(ekuIds);
                    req.X509Extensions.Add(ekuExtension);
                }
                const templateObjId = window.cadesplugin.CreateObject("X509Enrollment.CObjectId");
                templateObjId.InitializeFromValue(genCert.templateId);
                const templateObj = window.cadesplugin.CreateObject("X509Enrollment.CX509ExtensionTemplate");
                templateObj.InitializeEncode(templateObjId, 1, 0);
                req.X509Extensions.Add(templateObj);
                const ku = window.cadesplugin.CreateObject("X509Enrollment.CX509ExtensionKeyUsage");
                const CERT_DATA_ENCIPHERMENT_KEY_USAGE = 0x10;
                const CERT_KEY_ENCIPHERMENT_KEY_USAGE = 0x20;
                const CERT_DIGITAL_SIGNATURE_KEY_USAGE = 0x80;
                const CERT_NON_REPUDIATION_KEY_USAGE = 0x40;
                ku.InitializeEncode(CERT_KEY_ENCIPHERMENT_KEY_USAGE |
                    CERT_DATA_ENCIPHERMENT_KEY_USAGE |
                    CERT_DIGITAL_SIGNATURE_KEY_USAGE |
                    CERT_NON_REPUDIATION_KEY_USAGE);
                req.X509Extensions.Add(ku);
                // Объект, реализующий IX509Enrollment
                var enroll = window.cadesplugin.CreateObject("X509Enrollment.CX509Enrollment");
                enroll.InitializeFromRequest(req);
                resolve(enroll.CreateRequest(1)); //EncodingType.XCN_CRYPT_STRING_BASE64
            }
            catch (e) {
                reject(e);
            }
        });
        return promise;
    }
    installResponse(response) {
        var promise = new Promise(function (resolve, reject) {
            try {
                this.setTimeoutRetry(1000, 10, function () {
                    return window.cadesplugin && window.cadesplugin.CreateObject;
                }, function () {
                    if (window.console && window.console.log) {
                        window.console.log('install-response: ' + response);
                    }
                    try {
                        var enroll = window.cadesplugin.CreateObject("X509Enrollment.CX509Enrollment");
                        enroll.Initialize(1);
                        // AllowNone = 0, AllowUntrustedRoot = 4; XCN_CRYPT_STRING_BASE64_ANY = 6
                        enroll.InstallResponse(4, response, 6, "");
                        resolve(true);
                    }
                    catch (e) {
                        e.installedResponse = response;
                        reject(e);
                    }
                }, function () {
                    reject({ message: 'Ну удаётся найти window.cadesplugin.CreateObject', number: -1 });
                });
            }
            catch (e) {
                reject(e);
            }
        });
        return promise;
    }
    ;
}

function initGenerator() {
    window.CertificateGeneratorFactory = new CertificateGeneratorFactory();
}
class CertificateGeneratorFactory {
    get() {
        if (this._checkAsyncPlugin()) {
            return new CertificateGeneratorAsync();
        }
        return new CertificateGeneratorSync();
    }
    _checkAsyncPlugin() {
        return !!window.cadesplugin.CreateObjectAsync;
    }
}

class Certificate {
}

class PluginService {
    constructor() { }
    initPlugin(name) {
        const promise = new Promise((resolve, reject) => {
            window.cadesplugin.CreateObjectAsync(name).then((plugin) => {
                resolve(plugin);
            }).catch((err) => {
                reject(err);
            });
        });
        return promise;
    }
    initPlugins(names) {
        const promise = new Promise((resolve, reject) => {
            const plugins = {};
            const promises = [];
            for (let i = 0; i < names.length; i++) {
                promises.push(this.createObject(names[i]));
            }
            Promise.all(promises).then((values) => {
                for (let i = 0; i < names.length; i++) {
                    plugins[names[i]] = values[i];
                }
                resolve(plugins);
            }).catch((err) => {
                reject(err);
            });
        });
        return promise;
    }
    createObject(name) {
        const promise = new Promise((resolve, reject) => {
            window.cadesplugin.CreateObjectAsync(name).then((plugin) => {
                resolve(plugin);
            }).catch(() => {
                reject({ message: 'PluginService.createObject.exception: Fail when use cadesplugin.CreateObjectAsync() for ' + name });
            });
        });
        return promise;
    }
}

class StorePluginService {
    constructor(consts) {
        this.consts = consts;
    }
    initStore() {
        const promise = new Promise((resolve, reject) => {
            const pluginService = new PluginService();
            pluginService.initPlugin(this.consts.STORE).then((plugin) => {
                resolve(plugin);
            }).catch((err) => {
                reject(err);
            });
        });
        return promise;
    }
    open() {
        const promise = new Promise((resolve, reject) => {
            this.initStore().then((plugin) => {
                plugin.Open(this.consts.CAPICOM_CURRENT_USER_STORE, this.consts.CAPICOM_MY_STORE, this.consts.CAPICOM_STORE_OPEN_MAXIMUM_ALLOWED)
                    .then(() => {
                    resolve(plugin);
                }).catch(() => {
                    reject({ message: 'StorePluginService.openStore.exception' });
                });
            }).catch((err) => {
                reject(err);
            });
        });
        return promise;
    }
    close(plugin) {
        const promise = new Promise((resolve, reject) => {
            plugin.Close().then(() => {
                resolve({});
            }).catch(() => {
                reject({ message: 'StorePluginService.closeStore.exception' });
            });
        });
        return promise;
    }
}

class CertificateService {
    constructor(consts) {
        this.consts = consts;
        this._storePluginService = new StorePluginService(consts);
    }
    getCertificateByHash(hash) {
        const promise = new Promise((resolve, reject) => {
            this._getAllCertificates().then((certs) => {
                certs.Find(this.consts.CAPICOM_CERTIFICATE_FIND_SHA1_HASH, hash).then((collectionCert) => {
                    collectionCert.Item(1).then((cert) => {
                        this._storePluginService.close(this._pluginStore).then(() => {
                            resolve(cert);
                        }).catch((err) => {
                            reject(err);
                        });
                    }).catch(() => {
                        reject({ message: 'CertificateService.getCertificateByHash.exception: Fail when getting Item' });
                    });
                }).catch(() => {
                    reject({ message: 'CertificateService.getCertificateByHash.exception: Fail when getting Find' });
                });
            }).catch((err) => {
                reject(err);
            });
        });
        return promise;
    }
    getAll() {
        const promise = new Promise((resolve, reject) => {
            this._getCertificateCount().then((count) => {
                const promises = [];
                for (let i = 1; i <= count; i++) {
                    promises.push(this._mappingCertToCerVm(i));
                }
                Promise.all(promises).then((viewModels) => {
                    this._storePluginService.close(this._pluginStore).then(() => {
                        resolve(viewModels);
                    }).catch((err) => {
                        reject(err);
                    });
                }).catch(() => {
                    reject({ message: 'CertificateService.getAll.exception' });
                });
            }).catch((err) => {
                reject(err);
            });
        });
        return promise;
    }
    _getCertificateCount() {
        const promise = new Promise((resolve, reject) => {
            this._getAllCertificates().then((certs) => {
                certs.Count.then((count) => {
                    resolve(count);
                }).catch(() => {
                    reject({ message: 'CertificateService.getCertificateCount.exception: Fail when getting Count' });
                });
            }).catch((err) => {
                reject(err);
            });
        });
        return promise;
    }
    _mappingCertToCerVm(index) {
        const promise = new Promise((resolve, reject) => {
            this._getCertByIndex(index).then((cert) => {
                const vm = new Certificate();
                const promises = [
                    cert['Thumbprint'],
                    cert['SubjectName'],
                    cert['ValidFromDate'],
                    cert['ValidToDate']
                ];
                Promise.all(promises).then((values) => {
                    vm.Thumbprint = values[0];
                    vm.SubjectName = values[1];
                    vm.ValidFromDate = values[2];
                    vm.ValidToDate = values[3];
                    const promisesInfo = [
                        cert.GetInfo(this.consts.CAPICOM_INFO_SUBJECT_SIMPLE_NAME),
                        cert.GetInfo(this.consts.CAPICOM_INFO_ISSUER_SIMPLE_NAME)
                    ];
                    Promise.all(promisesInfo).then((infos) => {
                        vm.Subject = infos[0];
                        vm.Issuer = infos[1];
                        resolve(vm);
                    }).catch(() => {
                        reject({ message: 'CertificateService.mappingCertToCerVm.exception: Fail when getting Subject, Issuer' });
                    });
                }).catch(() => {
                    reject({ message: 'CertificateService.mappingCertToCerVm.exception: Fail when getting Thumbprint, SubjectName, ValidFromDate, ValidToDate' });
                });
            }).catch((err) => {
                reject(err);
            });
        });
        return promise;
    }
    _getCertByIndex(index) {
        const promise = new Promise((resolve, reject) => {
            this._getAllCertificates().then((certs) => {
                certs.Item(index).then((cert) => {
                    resolve(cert);
                }).catch(() => {
                    reject({ message: 'CertificateService.getCertByIndex.exception: Fail when getting Item for index ' + index });
                });
            }).catch((err) => {
                reject(err);
            });
        });
        return promise;
    }
    _getAllCertificates() {
        const promise = new Promise((resolve, reject) => {
            if (this._pluginStore === undefined) {
                this._storePluginService.open().then((plugin) => {
                    this._pluginStore = plugin;
                    this._pluginStore.Certificates.then((certs) => {
                        resolve(certs);
                    }).catch(() => {
                        reject({ message: 'CertificateService.Certificates.exception: Fail when getting Certificates from NEW pluginStore' });
                    });
                }).catch((err) => {
                    reject(err);
                });
                return;
            }
            this._pluginStore.Certificates.then((certs) => {
                resolve(certs);
            }).catch(() => {
                reject({ message: 'CertificateService.Certificates.exception: Fail when getting Certificates from CACHED pluginStore' });
            });
        });
        return promise;
    }
}

class SignDateConverterService {
    constructor(_vt) {
        this._vt = _vt;
    }
    convertDate(date) {
        if (this._vt === true) {
            try {
                return date.getVarDate();
            }
            catch (err) {
                return date;
            }
        }
        if (typeof (date) === 'object' && date instanceof Date) {
            return new Date(date);
        }
        return date;
    }
}

class CryptoSignService {
    constructor(consts) {
        this.consts = consts;
    }
    sign(data, hash, isDetached, isEncode) {
        const model = {
            data: data,
            hash: hash,
            isDetached: isDetached,
            isEncode: isEncode === undefined ? true : isEncode
        };
        const promise = new Promise((resolve, reject) => {
            const pluginService = new PluginService();
            const names = [
                this.consts.CPSIGNER,
                this.consts.SIGNEDDATA,
                this.consts.CPATTRIBUTE
            ];
            pluginService.initPlugins(names).then((plugins) => {
                this.signData(model, plugins).then((signedData) => {
                    resolve(signedData);
                }).catch((err) => {
                    reject(err);
                });
            }).catch((err) => {
                reject(err);
            });
        });
        return promise;
    }
    signData(model, plugins) {
        const promise = new Promise((resolve, reject) => {
            this.initSignerPlugin(model, plugins).then(() => {
                const contentEncoding = model.isEncode ? this.consts.CADESCOM_BASE64_TO_BINARY : this.consts.CADESCOM_STRING_TO_UCS2LE;
                const promises = [
                    plugins[this.consts.SIGNEDDATA].propset_ContentEncoding(contentEncoding),
                    plugins[this.consts.SIGNEDDATA].propset_Content(model.data)
                ];
                Promise.all(promises).then(() => {
                    plugins[this.consts.SIGNEDDATA].SignCades(plugins[this.consts.CPSIGNER], this.consts.CADES_BES, model.isDetached, this.consts.CAPICOM_ENCODE_BASE64)
                        .then((signedMessage) => {
                        resolve(signedMessage);
                    }).catch(() => {
                        reject({ message: 'SignService.signData.exception: Fail when getting SignCades' });
                    });
                }).catch(() => {
                    reject({ message: 'SignService.signData.exception: Fail when getting ContentEncoding, Content' });
                });
            }).catch((err) => {
                reject(err);
            });
        });
        return promise;
    }
    initSignerPlugin(model, plugins) {
        const promise = new Promise((resolve, reject) => {
            const certificateService = new CertificateService(this.consts);
            certificateService.getCertificateByHash(model.hash).then((cert) => {
                this.initSignerPluginWithAuthenticatedAttributes2(plugins[this.consts.CPSIGNER], plugins[this.consts.CPATTRIBUTE]).then(() => {
                    const promises = [
                        (plugins[this.consts.CPSIGNER]).propset_Certificate(cert),
                        (plugins[this.consts.CPSIGNER]).propset_Options(this.consts.CAPICOM_CERTIFICATE_INCLUDE_END_ENTITY_ONLY)
                    ];
                    Promise.all(promises).then(() => {
                        resolve({});
                    }).catch(() => {
                        reject({ message: 'SignService.initSignerPlugin.exception: Fail when getting Certificate, Options' });
                    });
                }).catch((err) => {
                    reject(err);
                });
            }).catch((err) => {
                reject(err);
            });
        });
        return promise;
    }
    initSignerPluginWithAuthenticatedAttributes2(signPlugin, attrPlugin) {
        const promise = new Promise((resolve, reject) => {
            this.initCpTimeAttributePlugin(attrPlugin).then((attrPlugin2) => {
                signPlugin.AuthenticatedAttributes2.then((attr) => {
                    attr.Add(attrPlugin2).then(() => {
                        resolve({});
                    }).catch(() => {
                        reject({ message: 'SignService.initSignerPluginWithAuthenticatedAttributes2.exception: Fail when getting Add' });
                    });
                }).catch(() => {
                    reject({ message: 'SignService.initSignerPluginWithAuthenticatedAttributes2.exception: Fail when getting AuthenticatedAttributes2' });
                });
            }).catch((err) => {
                reject(err);
            });
        });
        return promise;
    }
    initCpTimeAttributePlugin(plugin) {
        const promise = new Promise((resolve, reject) => {
            const signDateConverterService = new SignDateConverterService(false);
            const date = signDateConverterService.convertDate(new Date());
            const promises = [
                plugin.propset_Name(this.consts.CAPICOM_AUTHENTICATED_ATTRIBUTE_SIGNING_TIME),
                plugin.propset_Value(date)
            ];
            Promise.all(promises).then(() => {
                resolve(plugin);
            }).catch(() => {
                reject({ message: 'SignService.initCpAttributePlugin.exception: Fail when getting Name, Value' });
            });
        });
        return promise;
    }
}

class CryptoProviderConst {
    constructor() {
        this.CADES_BES = 1; // не улучшенная эцп
        this.CADESCOM_CADES_X_LONG_TYPE_1 = 0x5d;
        this.CADESCOM_CADES_DEFAULT = 0;
        this.CADESCOM_STRING_TO_UCS2LE = 0x00; // Данные будут перекодированы в UCS-2 little endian.
        this.CADESCOM_BASE64_TO_BINARY = 0x01; // Данные будут перекодированы в бинарный массив.
        this.CAPICOM_AUTHENTICATED_ATTRIBUTE_SIGNING_TIME = 0;
        this.CAPICOM_CERTIFICATE_FIND_SUBJECT_NAME = 1;
        this.CAPICOM_CERTIFICATE_FIND_SHA1_HASH = 0;
        this.CAPICOM_CERTIFICATE_INCLUDE_CHAIN_EXCEPT_ROOT = 0;
        this.CAPICOM_CERTIFICATE_INCLUDE_WHOLE_CHAIN = 1;
        this.CAPICOM_CERTIFICATE_INCLUDE_END_ENTITY_ONLY = 2;
        this.CAPICOM_CURRENT_USER_STORE = 2;
        this.CAPICOM_ENCODE_BASE64 = 0;
        this.CAPICOM_MY_STORE = 'My';
        this.CAPICOM_STORE_OPEN_MAXIMUM_ALLOWED = 2;
        this.CAPICOM_STORE_OPEN_READ_ONLY = 0;
        this.CAPICOM_VERIFY_SIGNATURE_ONLY = 0;
        this.CAPICOM_INFO_SUBJECT_SIMPLE_NAME = 0;
        this.CAPICOM_INFO_ISSUER_SIMPLE_NAME = 1;
        this.CAPICOM_INFO_SUBJECT_EMAIL_NAME = 2;
        this.CAPICOM_INFO_ISSUER_EMAIL_NAME = 3;
        this.STORE = 'CAPICOM.Store';
        this.CPSIGNER = 'CAdESCOM.CPSigner';
        this.SIGNEDDATA = 'CAdESCOM.CadesSignedData';
        this.CPATTRIBUTE = 'CADESCOM.CPAttribute';
        this.ABOUT = 'CAdESCOM.About';
        this.CADES_MIME_TYPE = 'application/x-cades';
        this.ACTIVATION_MESSAGE_PATTERN = '{0}CryptoProvider Activated';
    }
}
class BaseCryptoProvider {
    constructor() {
        this.consts = new CryptoProviderConst();
    }
}

class AsyncCryptoProvider extends BaseCryptoProvider {
    constructor() {
        super();
        console.log(this.consts.ACTIVATION_MESSAGE_PATTERN.replace('{0}', 'Async'));
    }
    version() {
        const promise = new Promise((resolve, reject) => {
            const pluginService = new PluginService();
            pluginService.initPlugin(this.consts.ABOUT).then((about) => {
                about.Version.then(function (version) {
                    resolve(version);
                }).catch((err) => {
                    console.error(err);
                    reject({ message: 'Произошла ошибка при попытке получить версию крипто-плагина cadesplugin.' });
                });
            }).catch((err) => {
                console.error(err);
                reject({ message: 'AsyncCryptoProvider.Version.exception: Fail when getting About' });
            });
        });
        return promise;
    }
    getCertCollection() {
        const promise = new Promise((resolve, reject) => {
            const certificateService = new CertificateService(this.consts);
            certificateService.getAll().then((certs) => {
                resolve(certs);
            }).catch((err) => {
                console.error(err);
                reject({ message: 'Произошла ошибка при попытке получить список установленных сертификатов.' });
            });
        });
        return promise;
    }
    sign(dataBase64, hash, isDetached, isEncode) {
        const promise = new Promise((resolve, reject) => {
            const signService = new CryptoSignService(this.consts);
            signService.sign(dataBase64, hash, isDetached, isEncode).then((signedMessage) => {
                resolve({ signature: signedMessage });
            }).catch((err) => {
                console.error(err);
                reject({ message: 'Произошла ошибка при попытке подписи.' });
            });
        });
        return promise;
    }
}

class BrowsersConstansts {
    constructor() {
        this.MICROSOFT_INTERNET_EXPLORER = 'Microsoft Internet Explorer';
        this.NETSCAPE = 'Netscape';
    }
}
class Browsers {
    static isEdge() {
        return navigator.userAgent.match(/edge/i) !== null;
    }
    static isChrome40() {
        return navigator.userAgent.match(/chrome\/(([3]\d)|([4][0-4]))\./i) !== null;
    }
    static isChrome45() {
        return navigator.userAgent.match(/chrome\/(([4][5-9])|([5-9]\d)|(\d\d\d))\./i) !== null;
    }
    static isFirefox40() {
        return navigator.userAgent.match(/firefox\/(([3]\d)|([4]\d)|([5][0-1]))\./i) !== null;
    }
    static isFirefox52() {
        return navigator.userAgent.match(/firefox\/(([5][2-9])|([6-9]\d)|(\d\d\d))\./i) !== null;
    }
    static isOpera() {
        return navigator.userAgent.match(/opr/i) !== null;
    }
    static isYandexBrowser() {
        return navigator.userAgent.match(/yabrowser/i) !== null;
    }
}

class GenericCryptoProvider extends BaseCryptoProvider {
    constructor(mode) {
        super();
        this._mode = mode;
        let value = '';
        for (const prop in window.CryptoProviderCodes) {
            if (window.CryptoProviderCodes.hasOwnProperty(prop) && window.CryptoProviderCodes[prop] === mode.code) {
                value = prop;
            }
        }
        console.log(this.consts.ACTIVATION_MESSAGE_PATTERN.replace('{0}', value));
    }
    version() {
        const promise = new Promise((resolve, reject) => {
            reject({ code: this._mode.code });
        });
        return promise;
    }
    getCertCollection() {
        const promise = new Promise((resolve, reject) => {
            reject({ code: this._mode.code });
        });
        return promise;
    }
    sign() {
        const promise = new Promise((resolve, reject) => {
            reject({ code: this._mode.code });
        });
        return promise;
    }
}

class SyncCryptoProvider extends BaseCryptoProvider {
    constructor() {
        super();
        console.log(this.consts.ACTIVATION_MESSAGE_PATTERN.replace('{0}', 'Sync'));
    }
    version() {
        const promise = new Promise((resolve, reject) => {
            try {
                const about = this._createObject(this.consts.ABOUT);
                resolve(about.Version);
            }
            catch (err) {
                console.error(err);
                reject({ message: 'Произошла ошибка при попытке получить версию крипто-плагина cadesplugin.' });
            }
        });
        return promise;
    }
    getCertCollection() {
        const promise = new Promise((resolve, reject) => {
            this._getCertCollection().then((certs) => {
                resolve(certs);
            }).catch((err) => {
                console.error(err);
                reject({ message: 'Произошла ошибка при попытке получить список установленных сертификатов.' });
            });
        });
        return promise;
    }
    sign(dataBase64, hash, isDetached, isEncode) {
        const promise = new Promise((resolve, reject) => {
            this._signBase64(dataBase64, hash, isDetached, isEncode).then((signedMessage) => {
                resolve({ signature: signedMessage });
            }).catch((err) => {
                console.error(err);
                reject({ message: 'Произошла ошибка при попытке подписи.' });
            });
        });
        return promise;
    }
    _signBase64(toSign, hash, isDetached, isEncode) {
        const promise = new Promise((resolve, reject) => {
            try {
                const store = this._createObject(this.consts.STORE);
                const signer = this._createObject(this.consts.CPSIGNER);
                isEncode = isEncode === undefined ? true : isEncode;
                store.Open(this.consts.CAPICOM_CURRENT_USER_STORE, this.consts.CAPICOM_MY_STORE, this.consts.CAPICOM_STORE_OPEN_MAXIMUM_ALLOWED);
                const oCertificates = store.Certificates.Find(this.consts.CAPICOM_CERTIFICATE_FIND_SHA1_HASH, hash);
                if (oCertificates.Count === 0) {
                    throw new Error('Certificate not found');
                }
                const oCertificate = oCertificates.Item(1);
                signer.Certificate = oCertificate;
                const oSignedData = this._createObject(this.consts.SIGNEDDATA);
                const contentEncoding = isEncode ? this.consts.CADESCOM_BASE64_TO_BINARY : this.consts.CADESCOM_STRING_TO_UCS2LE;
                oSignedData.ContentEncoding = contentEncoding;
                oSignedData.Content = toSign;
                signer.Options = this.consts.CAPICOM_CERTIFICATE_INCLUDE_END_ENTITY_ONLY;
                const oTimeNow = new Date();
                const signDateConverterService = new SignDateConverterService(true);
                const oSigningTimeAttr = this._createObject(this.consts.CPATTRIBUTE);
                oSigningTimeAttr.Name = this.consts.CAPICOM_AUTHENTICATED_ATTRIBUTE_SIGNING_TIME;
                oSigningTimeAttr.Value = signDateConverterService.convertDate(oTimeNow);
                signer.AuthenticatedAttributes2.Add(oSigningTimeAttr);
                const signedMessage = oSignedData.SignCades(signer, this.consts.CADES_BES, isDetached, this.consts.CAPICOM_ENCODE_BASE64);
                store.Close();
                resolve(signedMessage);
            }
            catch (err) {
                reject({ message: err.message });
            }
        });
        return promise;
    }
    _getCertCollection() {
        const promise = new Promise((resolve, reject) => {
            try {
                const store = this._createObject(this.consts.STORE);
                store.Open(this.consts.CAPICOM_CURRENT_USER_STORE, this.consts.CAPICOM_MY_STORE, this.consts.CAPICOM_STORE_OPEN_MAXIMUM_ALLOWED);
                const count = store.Certificates.Count;
                const certs = [];
                for (let i = 1; i <= count; i++) {
                    const cert = store.Certificates.Item(i);
                    const vm = new Certificate();
                    vm.Thumbprint = cert.Thumbprint;
                    vm.SubjectName = cert.SubjectName;
                    vm.ValidFromDate = cert.ValidFromDate;
                    vm.ValidToDate = cert.ValidToDate;
                    vm.Subject = cert.GetInfo(this.consts.CAPICOM_INFO_SUBJECT_SIMPLE_NAME);
                    vm.Issuer = cert.GetInfo(this.consts.CAPICOM_INFO_ISSUER_SIMPLE_NAME);
                    certs.push(vm);
                }
                store.Close();
                resolve(certs);
            }
            catch (e) {
                reject({ message: e.message });
            }
        });
        return promise;
    }
    _createObject(name) {
        const bConst = new BrowsersConstansts();
        switch (navigator.appName) {
            case bConst.MICROSOFT_INTERNET_EXPLORER:
                return new ActiveXObject(name);
            case bConst.NETSCAPE:
                try {
                    return new ActiveXObject(name);
                }
                catch (err) {
                    return window.cadesplugin.CreateObject(name);
                }
            default:
                return window.cadesplugin.CreateObject(name);
        }
    }
}

class CryptoProviderFactory {
    constructor() {
        this._disabled = false;
        window.cadesplugin_skip_extension_install = 1;
    }
    createCryptoProvider() {
        const cryptoProvider = new GenericCryptoProvider({ code: window.CryptoProviderCodes.Disabled });
        this._consts = cryptoProvider.consts;
        this._cryptoProvider = cryptoProvider;
        const mode = { code: window.CryptoProviderCodes.Disabled };
        this._getBrowserBehavior(mode);
        switch (mode.code) {
            case window.CryptoProviderCodes.Async:
                return new AsyncCryptoProvider();
            case window.CryptoProviderCodes.Sync:
                return new SyncCryptoProvider();
            case window.CryptoProviderCodes.Installer:
                return new GenericCryptoProvider({ code: window.CryptoProviderCodes.Installer });
            case window.CryptoProviderCodes.NotSupported:
                return new GenericCryptoProvider({ code: window.CryptoProviderCodes.NotSupported });
        }
        return this._cryptoProvider;
    }
    _getBrowserBehavior(mode) {
        const bConst = new BrowsersConstansts();
        switch (navigator.appName) {
            case bConst.MICROSOFT_INTERNET_EXPLORER:
                try {
                    const about = new ActiveXObject(this._consts.ABOUT);
                    mode.code = window.CryptoProviderCodes.Sync;
                }
                catch (err) {
                    mode.code = window.CryptoProviderCodes.Installer;
                }
                break;
            case bConst.NETSCAPE:
                if (Browsers.isEdge()) {
                    mode.code = window.CryptoProviderCodes.NotSupported;
                    // checkAsyncPlugin(); не включать, пока не будет отработан сценарий отсутствия установленного расширения
                    return;
                }
                if (Browsers.isOpera() || Browsers.isYandexBrowser()) {
                    checkAsyncPlugin();
                    return;
                }
                if (Browsers.isChrome45()) {
                    checkAsyncPlugin();
                    return;
                }
                if (Browsers.isChrome40()) {
                    checkPlugin();
                    return;
                }
                if (Browsers.isFirefox52()) {
                    checkAsyncPlugin();
                    return;
                }
                if (Browsers.isFirefox40()) {
                    checkPlugin();
                    return;
                }
                checkPlugin();
                break;
            default:
                checkPlugin();
        }
        function checkPlugin() {
            try {
                const aboutMain = new ActiveXObject(this._consts.ABOUT);
                mode.code = window.CryptoProviderCodes.Sync;
            }
            catch (ex) {
                const mimetype = navigator.mimeTypes[this._consts.CADES_MIME_TYPE];
                if (mimetype === undefined) {
                    mode.code = window.CryptoProviderCodes.Installer;
                }
                else {
                    try {
                        const aboutElse = window.cadesplugin.CreateObject(this._consts.ABOUT);
                        mode.code = window.CryptoProviderCodes.Sync;
                    }
                    catch (er) {
                        mode.code = window.CryptoProviderCodes.Installer;
                    }
                }
            }
        }
        function checkAsyncPlugin() {
            const isAsync = !!window.cadesplugin.CreateObjectAsync;
            if (isAsync) {
                mode.code = window.CryptoProviderCodes.Async;
            }
            else {
                mode.code = window.CryptoProviderCodes.Sync;
            }
        }
    }
    get() {
        if (this._cryptoProvider !== undefined) {
            this._cryptoProvider.version().then((version) => {
                console.log('cadesplugin: ' + version);
            });
            return this._cryptoProvider;
        }
        if (this._disabled) {
            this._cryptoProvider = new GenericCryptoProvider({ code: window.CryptoProviderCodes.Installer });
            return this._cryptoProvider;
        }
        this._cryptoProvider = this.createCryptoProvider();
        this._cryptoProvider.version().then((version) => {
            console.log('cadesplugin: ' + version);
        });
        return this._cryptoProvider;
    }
    disable() {
        this._disabled = true;
    }
}

function initCtypto() {
    window.CryptoProviderCodes = {
        Sync: 1,
        Async: 2,
        NotSupported: 3,
        Installer: 4,
        Disabled: 5
    };
    window.CryptoProviderFactory = new CryptoProviderFactory();
    window.addEventListener('message', (event) => {
        if (event.data === 'cadesplugin_load_error') {
            window.CryptoProviderFactory.disable();
        }
    }, false);
    document.addEventListener('error', (event) => {
        const element = event.target;
        if (element !== undefined && element.src !== undefined && element.src.match(/nmcades_plugin/i)) {
            if (Browsers.isOpera() || Browsers.isYandexBrowser()) {
                inlinePlugin();
                return;
            }
            window.CryptoProviderFactory.disable();
        }
        function inlinePlugin() {
            document.addEventListener('DOMContentLoaded', () => {
                createCadesPluginObject();
            });
            function createCadesPluginObject() {
                const elem = document.createElement('object');
                elem.setAttribute('id', 'cadesplugin');
                elem.setAttribute('type', 'application/x-cades');
                elem.setAttribute('style', 'visibility=hidden');
                document.getElementsByTagName('body')[0].appendChild(elem);
            }
        }
    }, true);
}

class CryptoModule {
    static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: CryptoModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); }
    static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "20.3.18", ngImport: i0, type: CryptoModule }); }
    static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: CryptoModule }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: CryptoModule, decorators: [{
            type: NgModule,
            args: [{
                    imports: [],
                    providers: [],
                    exports: []
                }]
        }] });

/**
 * Generated bundle index. Do not edit.
 */

export { CertificateGenModel, CertificateGeneratorFactory, CryptoModule, CryptoProviderFactory, DnCertificate, IndividualCertificate, JuridicalCertificate, PhysicalCertificate, initCtypto, initGenerator };
//# sourceMappingURL=sellan-crypto.mjs.map
