/*
Получение информации по ключу авторизации
NCALayer.sign('AUTH', null, result => {
  console.log(result)
});

получение информации по ключу и данных для подписания при согласовании/утверждении или просто подписания документа
NCALayer.sign('SIGN','documentID', result => {
  console.log(result)
});
*/

this.NCALayer = {
  SOCKET_URL: 'wss://127.0.0.1:13579/',
  storageName: "PKCS12",
  webSocket: null,
  info: {},
  keysConstType: null,
  documentID: null,
  successHandler: null,
  connect: null,

  initNCALayerSocket: function(){
    let me = this;
    this.webSocket = new WebSocket(this.SOCKET_URL);

    this.webSocket.onclose = function(event) {
      if(event.wasClean) {
        console.log(`[NCALayer] Соединение успешно закрыто, код: ${event.code} причина: ${event.reason}`);
      } else {
        console.log('[NCALayer] Соединение прервано');
      }
      me.webSocket = null;
      me.connect = null;
    }

    this.webSocket.onerror = function(error) {
      Cons.hideLoader();
      me.connect = null;
      console.log('[NCALayer error]', error);
      UIkit.modal.alert(`<span>Убедитесь что программа NCALayer запущена и повторите попытку.<br><a href="https://pki.gov.kz/ncalayer/" target="_blank">Инструкция по запуску программы</a></span>`);
    }

    this.webSocket.onmessage = function(event) {
      const result = parseNcaLayerMsg(event);
      if(result.hasOwnProperty('code')) {
        if(result.code == 200) {
          if (result.responseObject.hasOwnProperty('keyId')) {
            const {certNotAfter, certNotBefore, algorithm, subjectDn} = result.responseObject
            me.info.certNotAfter = AS.FORMS.DateUtils.formatDate(new Date(Number(certNotAfter)), AS.FORMS.DateUtils.DATE_FORMAT_FULL);
            me.info.certNotBefore = AS.FORMS.DateUtils.formatDate(new Date(Number(certNotBefore)), AS.FORMS.DateUtils.DATE_FORMAT_FULL);
            me.info.algorithm = algorithm;

            const keyInfo = subjectDn.split(",");
            keyInfo.forEach(item => {
              const keyValue = item.split('=');
              me.info[keyValue[0]] = keyValue[1];
            });

            if(me.keysConstType == 'SIGN' && me.documentID) {
              me.signDocument();
            } else {
              if(me.successHandler) me.successHandler(me.info);
            }
          } else {
            me.info = {...me.info, ...result.responseObject};
            if(result.responseObject.hasOwnProperty('signedData')) me.verificationKey();
          }
        } else {
          showMessage("Ошибка проверки ключа.", "error");
          console.log('[NCALayer onmessage error]', result);
        }
      }
    }

    this.webSocket.onopen = function(event) {
      me.connect = true;
      console.log('[NCALayer] Соединение установлено');
    }
  },

  getNCALayerSocket: function(){
    if(!this.webSocket || [2, 3].includes(Number(this.webSocket.readyState))) {
      this.initNCALayerSocket();
    }
    return this.webSocket;
  },

  getKeyInfo: function(){
    const param = {
      module: 'kz.arta.synergy.signmodule',
      method: 'getFullKeyInfo',
      args: [this.storageName]
    };

    if(!this.webSocket) this.webSocket = this.getNCALayerSocket();

    setTimeout(() => {
      this.webSocket.send(JSON.stringify(param));
    }, 100);
  },

  signDocument: async function(socket){
    const { rawdata } = await AS.FORMS.ApiUtils.simpleAsyncGet(`rest/api/docflow/doc/document_info?documentID=${this.documentID}`);

    const param = {
      module: 'kz.arta.synergy.signmodule',
      method: 'signDocument',
      args: ["", "SIGN", rawdata]
    };

    if(!this.webSocket) this.webSocket = this.getNCALayerSocket();

    setTimeout(() => {
      this.webSocket.send(JSON.stringify(param));
    }, 100);
  },

  verificationKey: async function() {
    try {
      const {dataForSign, certificate, signedData, CN} = this.info;

      const verificationkey = await AS.FORMS.ApiUtils.simpleAsyncPost("rest/sign/verificationkey", null, "text", {
        uuid: AS.OPTIONS.currentUser.userid,
        pemCer: certificate,
        edsInfo: CN
      });

      if(verificationkey === null || verificationkey.indexOf("::::") === -1)
      throw new Error('Произошла ошибка проверки ключа.');
      if(verificationkey === "CERT REVOKED") throw new Error('Сертификат отозван.');
      if(verificationkey === "CERT END") throw new Error('Сертификат просрочен.');

      const certID = verificationkey.split('::::')[0];
      const alg = verificationkey.split('::::')[1];

      this.info.certID = certID;
      this.info.alg = alg;

      if(this.successHandler) this.successHandler(this.info);
    } catch (err) {
      showMessage(err.message, "error");
    }
  },

  sign: function(keysConstType = 'AUTH', documentID = null, handler) {
    if(!this.webSocket) this.initNCALayerSocket();
    this.keysConstType = keysConstType;
    this.documentID = documentID;
    this.info = {};

    if(handler && typeof handler == 'function') {
      this.successHandler = handler;
    } else {
      this.successHandler = null;
    }

    const timerID = setInterval(() => {
      if(this.connect) {
        this.getKeyInfo();
        clearInterval(timerID);
      }
    }, 500);
  }
};

const parseNcaLayerMsg = event => {
  if(event.data == "OK") return event.data;
  const data = JSON.parse(event.data);
  if(data) return({...data});
  return event;
}
