//@include lib_Class.js

/**
 * @private
 * Creates a signed PDF file
 * Combines a given file with a signature image.
 * The signature image is retrieved as base64 content from a "properties" property of a data node or form a form blob field
 *
 * @author MW, ELO Digital Office GmbH
 *
 * @eloas
 * @requires sol.common.as.FunctionBase
 * @requires sol.common.JsonUtils
 * @requires sol.common.RepoUtils
 * @requires sol.common.WfUtils
 *
 * Sample node configuration:
 *
 *    {
 *      "$directRule": "sol.common.CreateSignedPdf" ,
 *      "field": {
 *        "type": "FORMBLOB",
 *        "key": "WO_SIGNATURE"
 *      },
 *      "signatureBasePath": "ARCPATH[(E10E1000-E100-E100-E100-E10E10E10E00)]:/Business Solutions/visitor/Configuration/Reports/Signature",
 *      "signatureType": "Default"
 *    }
 *
 *    {
 *      "$function": "sol.common.as.functions.CreateSignedPdf" ,
 *      "dataNodeName": "[data] signature",
 *      "templateId": "ARCPATH:/Administration/Business Solutions/visitor/Configuration/Reports/Signature/Signature",
 *      "name": "signed"
 *    }
 */
sol.define("sol.common.as.functions.CreateSignedPdf", {
  extend: "sol.common.as.FunctionBase",

  requiredProperty: ["objId", "flowId", "dataNodeName"],

  /**
   * @cfg {String} objId (required)
   * Object ID of the PDF file that should be signed
   */

  /**
   * @cfg {String} flowId (required)
   * Workflow ID
   */

  /**
   * @cfg {String} dataNodeName
   * Name which holds the base64 string with the signature
   */

  /**
   * @cfg {String} field
   * Field that contains the signature data
   */

  /**
   * @cfg {String} name (optional)
   * Name of the created document, default will be the name of the original element
   */

  /**
   * @cfg {String} templateId (optional)
   * Object ID of the FOP template. Either this, or `signatureBasePath` and `signatureType` has to be set. If a `templateId` is defined, it has priority.
   */

  /**
   * @cfg {String} signatureBasePath (optional)
   * ARCPATH with the signatur types. If not set, `templateId` has to be defined. If a `templateId` is defined, it has priority.
   */

  /**
   * @cfg {String} signatureType (optional)
   * The template name for the signature (in the `signatureBasePath`). If not set, `templateId` has to be defined. If a `templateId` is defined, it has priority.
   */

  /**
   * @cfg {String} dstFolderId (optional)
   * Folder ID of the destination folder
   */

  initialize: function (config) {
    var me = this;
    me.$super("sol.common.as.FunctionBase", "initialize", [config]);

  },

  getName: function () {
    return "SignPdf";
  },

  process: function () {
    var me = this,
        wfDiagram, dataNode, blobValue, blobData, imageData, imageDataParts, fopRenderer, sord, srcObjUrl, srcTempFilePath,
        data, signatureFopResult, srcDocInputStream, signatureInputStream, mergedOutputStream, signatureTypeFromDocument,
        connectionLanguage, documentLanguage;

    if (!me.templateId && !me.signatureBasePath) {
      throw "IllegalArgumentException: either a 'templateId' or 'signatureBasePath' has to be defined";
    }

    me.signatureType = me.signatureType || me.signaturType; // Correct spelling mistake

    sord = ixConnect.ix().checkoutSord(me.objId, SordC.mbAllIndex, LockC.NO);

    connectionLanguage = ixConnect.loginResult.clientInfo.language;
    documentLanguage = sol.common.SordUtils.getValue(sord, { type: "MAP", key: "SIGNATURE_LANGUAGE" });
    ixConnect.loginResult.clientInfo.language = documentLanguage;

    if (me.signatureBasePath) {
      signatureTypeFromDocument = sol.common.SordUtils.getValue(sord, { type: "MAP", key: "SIGNATURE_FO_TEMPLATE" });

      me.signatureType = signatureTypeFromDocument || me.signatureType;

      if (!me.signatureType) {
        throw "IllegalArgumentException: if a 'signatureBasePath' is defined, a 'signatureType' is mandatory";
      }

      me.logger.debug(["signatureBasePath={0}, signatureType={1}", me.signatureBasePath, me.signatureType]);
    }

    if (me.dataNodeName) {
      wfDiagram = sol.common.WfUtils.getWorkflow(me.flowId);
      dataNode = sol.common.WfUtils.getNodeByName(wfDiagram, me.dataNodeName);

      if (!dataNode) {
        throw "Data node '" + me.dataNodeName + "' not found.";
      }

      imageData = dataNode.properties + "";
    }

    if (me.field) {
      blobValue = sol.common.SordUtils.getValue(sord, me.field);
      blobData = JSON.parse(blobValue);
      imageData = blobData.signature;
    }

    if (!imageData) {
      throw "Image data is empty";
    }

    imageDataParts = imageData.split(";base64,");
    if (imageDataParts && (imageDataParts.length == 2)) {
      imageData = imageDataParts[1];
    }

    me.dstFolderId = me.dstFolderId || sord.parentId;
    me.name = me.name || sord.name;
    me.templateId = me.getTemplateId();

    data = { srcTempFilePath: srcTempFilePath, srcObjUrl: srcObjUrl, imageData: imageData, sord: sol.common.SordUtils.getTemplateSord(sord).sord };

    me.logger.debug(["Create signature PDF: imageData={0}" + imageData]);

    fopRenderer = sol.create("sol.common.as.renderer.Fop", { templateId: me.templateId, toStream: true });
    signatureFopResult = fopRenderer.render(me.name, data);

    signatureInputStream = me.convertOutputStreamToInputStream(signatureFopResult.outputStream);

    srcDocInputStream = sol.common.RepoUtils.downloadToStream(me.objId);
    mergedOutputStream = new ByteArrayOutputStream();
    sol.common.as.PdfUtils.mergePdfStreams([srcDocInputStream, signatureInputStream], mergedOutputStream);
    sol.common.RepoUtils.saveToRepo({ objId: me.objId, name: me.name, outputStream: mergedOutputStream, extension: "pdf", versionIncrement: 1 });

    if (connectionLanguage) {
      ixConnect.loginResult.clientInfo.language = connectionLanguage;
    }

    return { passOn: true };
  },

  /**
   * @private
   * Converts an output stream to an input stream
   * @param {java.io.OutputStream} outputStream
   * @return {java.io.InputStream}
   */
  convertOutputStreamToInputStream: function (outputStream) {
    if (!outputStream) {
      throw "Output stream is empty";
    }
    var inputStream = new ByteArrayInputStream(outputStream.toByteArray());
    outputStream.close();
    return inputStream;
  },

  /**
   * @private
   * @return {String}
   */
  getTemplateId: function () {
    var me = this;
    return me.templateId || sol.common.RepoUtils.getObjIdFromRelativePath(me.signatureBasePath, "/" + me.signatureType);
  }
});