importPackage(Packages.java.io);
importPackage(Packages.de.elo.ix.client);

//@include lib_Class.js
//@include lib_sol.common.ix.FunctionBase.js

var logger = sol.create("sol.Logger", { scope: "sol.common.ix.functions.Blackening" });

/**
 * Imprints annotated areas for blackening into a document.
 *
 * <b>Please note</b> that if blackening should be done irreversible <b>version control must be disabled</b>.
 *
 * If a user is set in the configuration, this user will be used to determine which blackening annotations should be imprinted;
 * If no user is defined, all ACL will be removed from the blackening annotations, which lead to the result that all blackening annotations will be imprinted.
 *
 * # As workflow node
 *
 * ObjId is set based on the element that the workflow is attached to.
 * Following configuration should be applied to the comments field.
 *
 *     {
 *       "user": "John Doe",
 *       "force": true
 *     }
 *
 * # As IX function call
 *
 * In addition to the workflow node configuration the objId must be passed.
 *
 *     sol.common.IxUtils.execute("RF_sol_function_ix_Blackening", {
 *       objId: "4711",
 *       user: "John Doe",
 *       force: true
 *     });
 *
 * # Prerequisites
 *
 * Blackening only supports documents. If function is called from a workflow which is based on a document, nothing can be blacked.
 *
 * @author PZ, ELO Digital Office GmbH
 * @version 1.0
 *
 * @eloix
 * @requires  sol.common.JsonUtils
 * @requires  sol.common.WfUtils
 * @requires  sol.common.ix.RfUtils
 * @requires  sol.common.ix.FunctionBase
 *
 */
sol.define("sol.common.ix.functions.Blackening", {
  extend: "sol.common.ix.FunctionBase",

  requiredConfig: ["objId"],

  /**
   * @cfg {String} objId (required)
   */

  /** @cfg {string} user
   * if a user is set, this user will be used, to determine, which blackening annotations should be imprinted;
   * if no user is defined, all ACL will be removed from the blackening annotations -> all annotations will be imprinted
   */
  user: undefined,

  /** @cfg {Boolean} [force=false]
   * if true, the imprint will be forced, even if the object is locked
   */
  force: false,

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

  /**
   * Imprint the blackening annotations
   */
  process: function () {
    var me = this,
        lockZ, ed, blackeningConn, inputStream, data;

    lockZ = me.force ? LockC.FORCE : LockC.NO;

    if (me.user) {
      blackeningConn = ixConnectAdmin.createConnectionForUser(me.user);
    } else {
      me.removeBlackeningNoteAcl(me.objId);
      blackeningConn = ixConnectAdmin;
    }

    ed = blackeningConn.ix().checkoutDoc(me.objId, null, EditInfoC.mbSordDoc, lockZ);

    if (!me.isDocument(ed.sord)) {
      me.logger.warn("blackening can only be used on documents");
      return;
    }

    inputStream = blackeningConn.download(ed.document.docs[0].url, 0, -1);
    data = me.byteArrayFromStream(inputStream);

    ed.document = blackeningConn.ix().checkinDocBegin(ed.document);
    ed.document.docs[0].uploadResult = blackeningConn.upload(ed.document.docs[0].url, new ByteArrayInputStream(data), data.length, ed.document.docs[0].contentType);
    ed.document = blackeningConn.ix().checkinDocEnd(ed.sord, SordC.mbAll, ed.document, lockZ);

    inputStream.close();
  },

  isDocument: function (sord) {
    return sord && (sord.type >= SordC.LBT_DOCUMENT) && (sord.type <= SordC.LBT_DOCUMENT_MAX);
  },

  byteArrayFromStream: function (inputStream) {
    var baos = new ByteArrayOutputStream(),
        reads = inputStream.read(),
        data;

    while (reads != -1) {
      baos.write(reads);
      reads = inputStream.read();
    }

    data = baos.toByteArray();

    baos.close();

    return data;
  },

  removeBlackeningNoteAcl: function (objId) {
    var notes = ixConnectAdmin.ix().checkoutNotes(objId, null, NoteC.mbAll, LockC.NO),
        changed = [];

    notes.forEach(function (note) {
      if (note.type == NoteC.TYPE_ANNOTATION_MARKER) {
        note.aclItems = [];
        changed.push(note);
      }
    });

    if (changed.length > 0) {
      ixConnectAdmin.ix().checkinNotes(objId, changed, NoteC.mbAll, LockC.NO);
    }
  }
});


/**
 * @member sol.common.ix.functions.Blackening
 * @static
 * @inheritdoc sol.common.ix.FunctionBase#onEnterNode
 */
function onEnterNode(clInfo, userId, wFDiagram, nodeId) {
  logger.enter("onEnterNode_Blackening", { flowId: wFDiagram.id, nodeId: nodeId });
  var params = sol.common.WfUtils.parseAndCheckParams(wFDiagram, nodeId),
      module;

  params.objId = wFDiagram.objId;
  module = sol.create("sol.common.ix.functions.Blackening", params);

  module.process();

  logger.exit("onEnterNode_Blackening");
}


/**
 * @member sol.common.ix.functions.Blackening
 * @static
 * @inheritdoc sol.common.ix.FunctionBase#onExitNode
 */
function onExitNode(clInfo, userId, wFDiagram, nodeId) {
  logger.enter("onExitNode_Blackening", { flowId: wFDiagram.id, nodeId: nodeId });
  var params = sol.common.WfUtils.parseAndCheckParams(wFDiagram, nodeId),
      module;

  params.objId = wFDiagram.objId;
  module = sol.create("sol.common.ix.functions.Blackening", params);

  module.process();

  logger.exit("onExitNode_Blackening");
}


/**
 * @member sol.common.ix.functions.Blackening
 * @method RF_sol_function_Blackening
 * @static
 * @inheritdoc sol.common.ix.FunctionBase#RF_FunctionName
 */
function RF_sol_function_Blackening(iXSEContext, args) {
  logger.enter("RF_sol_function_Blackening", args);
  var params = sol.common.ix.RfUtils.parseAndCheckParams(iXSEContext, arguments.callee.name, args, "objId"),
      module = sol.create("sol.common.ix.functions.Blackening", params);

  module.process();

  logger.exit("RF_sol_function_Blackening");
}