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

//@include lib_Class.js
//@include lib_sol.common.Config.js
//@include lib_sol.common.SordUtils.js
//@include lib_sol.common.DateUtils.js
//@include lib_sol.common.ix.ServiceBase.js
//@include lib_sol.checklist.Utils.js

var logger = sol.create("sol.Logger", { scope: "sol.checklist.ix.services.Checklist" });

/**
 * Provides service functions for the checklist module.
 *
 * The element used as checklist, has to define a `SOL_TYPE` field with the value from the checklist configuration defined in `checklist.solObjectType`.
 *
 * # Model
 * The model of the checklist is stored in the description of a sord as JSON string.
 *
 * A checklist contains an `items` property which holds an array of checklist items.
 *
 * Each checklist item has the following form:
 *
 *     {
 *       id: 23,
 *       text: "a label",
 *       notes: "a description",                      // optional
 *       checked: true,
 *       checkDate: "20160824113000",                 // only set, if checked=true
 *       checkUser: { id: "7", name: "mmustermann" }, // only set, if checked=true
 *       marked: false
 *     }
 *
 * # Results
 * All function (except {@link #RF_sol_checklist_service_ReadChecklist ReadChecklist}) return a standardized response format:
 *
 *     {
 *       status: "SUCCESS"        // possible values: SUCCESS|FAILURE|RECURRENCE
 *       item: {...}              // optional, e.g. added, removed, updated item
 *       error: "some.error.code" // only if 'status' is 'FAILURE'
 *     }
 *
 * ## Errorcodes
 *
 * |Code|Description|
 * |:------|:------|
 * |checklist.save|Error while saving checklist|
 * |checklist.item.invalid||
 * |checklist.item.notFound|Item not found|
 * |checklist.item.notMoved|Item not moved|
 * |checklist.missing.itemId|Missing property 'itemId'|
 * |checklist.missing.check|Missing property 'check'|
 * |checklist.missing.mark|Missing property 'mark'|
 * |checklist.missing.item.id|Edit item has not defined an 'id'|
 * |checklist.missing.fromIdx|Missing property 'fromIdx'|
 * |checklist.missing.toIdx|Missing property 'toIdx'|
 *
 * # Usage
 *
 * ## Edit checklist
 *
 *     sol.common.IxUtils.execute("RF_sol_checklist_service_EditChecklist", { objId: "4711",  checklistname: "checklist4711", checklistdesc: "Water cologne" });
 *
 *     // result //
 *     {
 *       status: "SUCCESS"
 *     }
 *
 * ## Read checklist
 *
 *     sol.common.IxUtils.execute("RF_sol_checklist_service_ReadChecklist", { objId: "4711" });
 *
 *     // result //
 *     {
 *       items: [ ... ],
 *       writable: true
 *     }
 *
 * ## Move an checklist item
 *
 *     sol.common.IxUtils.execute("RF_sol_checklist_service_MoveItem", {
 *       objId: "4711",
 *       fromIdx: 2,
 *       toIdx: 4
 *     });
 *
 *     // result (the added item) //
 *     {
 *       status: "SUCCESS"
 *     }
 *
 * ## Add checklist item
 *
 *     sol.common.IxUtils.execute("RF_sol_checklist_service_AddItem", {
 *       objId: "4711",
 *       item: {
 *         text: "a label",
 *         notes: "optional description"
 *       }
 *     });
 *
 *     // result (the added item) //
 *     {
 *       status: "SUCCESS",
 *       item: {
 *         id: 23,
 *         text: "a label",
 *         notes: "optional description",
 *         checked: false,
 *         marked: false
 *       }
 *     }
 *
 * ## Remove checklist item
 *
 *     sol.common.IxUtils.execute("RF_sol_checklist_service_RemoveItem", {
 *       objId: "4711",
 *       itemId: 23
 *     });
 *
 *     // result (including the removed item) //
 *     {
 *       status: "SUCCESS",
 *       item: {
 *         id: 23,
 *         text: "a label",
 *         notes: "optional description",
 *         checked: false,
 *         marked: false
 *       }
 *     }
 *
 * ## Edit checklist item
 * Only `text` and `notes` can be edited this way.
 *
 *     sol.common.IxUtils.execute("RF_sol_checklist_service_EditItem", {
 *       objId: "4711",
 *       item: {
 *         id: 23,
 *         text: "an edited label",
 *         notes: "edit"
 *       }
 *     });
 *
 *     // result //
 *     {
 *       status: "SUCCESS",
 *       item: {
 *         id: 23,
 *         text: "an edited label",
 *         notes: "edit",
 *         checked: false,
 *         marked: false
 *       }
 *     }
 *
 * ## Check checklist item
 * Check an item:
 *
 *     sol.common.IxUtils.execute("RF_sol_checklist_service_CheckItem", {
 *       objId: "4711",
 *       itemId: 23,
 *       check: true
 *     });
 *
 *     // result //
 *     {
 *       status: "SUCCESS",
 *       item: {
 *         id: 23,
 *         text: "a label",
 *         notes: "optional description",
 *         checked: true,
 *         checkDate: "20160824113000",
 *         checkUser: { id: "7", name: "mmustermann" },
 *         marked: false
 *       }
 *     }
 *
 * Uncheck an item:
 *
 *     sol.common.IxUtils.execute("RF_sol_checklist_service_CheckItem", {
 *       objId: "4711",
 *       itemId: 23,
 *       check: false
 *     });
 *
 *     // result //
 *     {
 *       status: "SUCCESS",
 *       item: {
 *         id: 23,
 *         text: "a label",
 *         notes: "optional description",
 *         checked: false,
 *         marked: false
 *       }
 *     }
 *
 * Uncheck again:
 *
 *     sol.common.IxUtils.execute("RF_sol_checklist_service_CheckItem", {
 *       objId: "4711",
 *       itemId: 23,
 *       check: false
 *     });
 *
 *     // result, item was not altered, but will be returned anyway (it might have been altered by another user) //
 *     {
 *       status: "RECURRENCE",
 *       item: {
 *         id: 23,
 *         text: "a label",
 *         notes: "optional description",
 *         checked: false,
 *         marked: false
 *       }
 *     }
 *
 * ## Mark checklist item
 * Mark an item:
 *
 *     sol.common.IxUtils.execute("RF_sol_checklist_service_MarkItem", {
 *       objId: "4711",
 *       itemId: 23,
 *       mark: true
 *     });
 *
 * Unmark an item:
 *
 *     sol.common.IxUtils.execute("RF_sol_checklist_service_MarkItem", {
 *       objId: "4711",
 *       itemId: 23,
 *       mark: false
 *     });
 *
 * Results equivalent to checking and unchecking.
 *
 * @author PZ, ELO Digital Office GmbH
 * @version 1.00.000
 *
 * @eloix
 * @requires moment.js
 * @requires sol.common.Config
 * @requires sol.common.SordUtils
 * @requires sol.common.DateUtils
 * @requires sol.common.ix.RfUtils
 * @requires sol.common.ix.ServiceBase
 */
sol.define("sol.checklist.ix.services.Checklist", {
  extend: "sol.common.ix.ServiceBase",

  requiredConfig: ["objId"],

  /**
   * @private
   * @property {de.elo.ix.client.SordZ}
   */
  sordZ: SordC.mbAllIndex,

  /**
   * @private
   * @property {Object}
   */
  STATUS: {
    SUCCESS: "SUCCESS",
    FAILURE: "FAILURE",
    RECURRENCE: "RECURRENCE"
  },

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

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

    if (!sol.checklist.Utils.isChecklist(me.sord)) {
      throw "selected element is not a checklist";
    }
  },

  /**
   * Loads the checklist object from the description of a Sord.
   * @return {Object} The checklist
   */
  readChecklist: function () {
    var me = this,
        desc, checklist;

    try {
      desc = String(me.sord.desc);

      if (desc && (desc.length > 0)) {
        checklist = JSON.parse(desc);
      }
    } catch (ex) {
      me.logger.warn("error parsing checklist from sord description", ex);
    }

    if (!checklist || !checklist.items) {
      checklist = { items: [] };
    }

    checklist.writable = me.hasWriteAccess(me.sord);
    return checklist;
  },

  /**
   * Moves an item.
   * @return {Object} The checklist
   */
  moveItem: function () {
    var me = this,
        checklist, moved, success, status, error;

    if (typeof me.fromIdx === "undefined") {
      return me.buildResponse(me.STATUS.FAILURE, null, "checklist.missing.fromIdx");
    }

    if (typeof me.toIdx === "undefined") {
      return me.buildResponse(me.STATUS.FAILURE, null, "checklist.missing.toIdx");
    }

    checklist = me.readChecklist();

    moved = me.moveItemInArray(checklist.items, me.fromIdx, me.toIdx);
    if (!moved) {
      return me.buildResponse(me.STATUS.FAILURE, null, "checklist.item.notMoved");
    }

    success = me.saveChecklist(checklist);
    status = (success) ? me.STATUS.SUCCESS : me.STATUS.FAILURE;
    error = (!success) ? "checklist.save" : null;

    return me.buildResponse(status, null, error);
  },

  /**
   * Adds an item to a checklist.
   * @return {Object}
   */
  addItem: function () {
    var me = this,
        checklist, newItem, success, status, error;

    if (!me.validateItem(me.item)) {
      return me.buildResponse(me.STATUS.FAILURE, null, "checklist.item.invalid");
    }

    checklist = me.readChecklist();

    newItem = {
      id: sol.checklist.Utils.getNextId(checklist),
      text: me.item.text,
      checked: false,
      marked: false
    };

    if (me.item.notes) {
      newItem.notes = me.item.notes;
    }

    checklist.items.push(newItem);

    success = me.saveChecklist(checklist);
    status = (success) ? me.STATUS.SUCCESS : me.STATUS.FAILURE;
    error = (!success) ? "checklist.save" : null;

    return me.buildResponse(status, newItem, error);
  },

  /**
   * Removes an item from a checklist.
   * @return {Object}
   */
  removeItem: function () {
    var me = this,
        checklist, idx, removedItems, success, status, error, removedItem;

    if (typeof me.itemId === "undefined") {
      return me.buildResponse(me.STATUS.FAILURE, null, "checklist.missing.itemId");
    }

    checklist = me.readChecklist();
    idx = me.getItemIndex(checklist, me.itemId);

    if (typeof idx !== "undefined") {
      removedItems = checklist.items.splice(idx, 1);
      success = me.saveChecklist(checklist);
      status = (success) ? me.STATUS.SUCCESS : me.STATUS.FAILURE;
      error = (!success) ? "checklist.save" : null;
    } else {
      status = me.STATUS.FAILURE;
      error = "checklist.item.notFound";
    }

    removedItem = (success && removedItems && (removedItems.length === 1)) ? removedItems[0] : null;

    return me.buildResponse(status, removedItem, error);
  },

  /**
   * Edits an item of a checklist.
   * @return {Boolean}
   */
  editItem: function () {
    var me = this,
        checklist, idx, editedItem, success, status, error;

    if (!me.validateItem(me.item)) {
      return me.buildResponse(me.STATUS.FAILURE, null, "checklist.item.invalid");
    }

    if (typeof me.item.id === "undefined") {
      return me.buildResponse(me.STATUS.FAILURE, null, "checklist.missing.item.id");
    }

    checklist = me.readChecklist();
    idx = me.getItemIndex(checklist, me.item.id);

    if (typeof idx !== "undefined") {
      me.mergeItem(checklist.items[idx], me.item);
      editedItem = checklist.items[idx];
      success = me.saveChecklist(checklist);
      status = (success) ? me.STATUS.SUCCESS : me.STATUS.FAILURE;
      error = (!success) ? "checklist.save" : null;
    } else {
      status = me.STATUS.FAILURE;
      error = "checklist.item.notFound";
    }

    return me.buildResponse(status, editedItem, error);
  },

  /**
   * Marks an item as checked/unchecked and handles the `checkUser` and `checkDate` attributes.
   * @return {Object}
   */
  checkItem: function () {
    var me = this,
        checklist, idx, checkedItem, dirty, success, status, error;

    if (typeof me.itemId === "undefined") {
      return me.buildResponse(me.STATUS.FAILURE, null, "checklist.missing.itemId");
    }

    if (typeof me.check === "undefined") {
      return me.buildResponse(me.STATUS.FAILURE, null, "checklist.missing.check");
    }

    if (!me.user) {
      me.user = ixConnect.loginResult.user;
      me.logger.debug(["use user from ixConnect: name={0}, id={1}", me.user.name, me.user.id]);
    }

    checklist = me.readChecklist();
    idx = me.getItemIndex(checklist, me.itemId);

    if (typeof idx !== "undefined") {
      checkedItem = checklist.items[idx];
      dirty = me.checkItemObject(checklist.items[idx], me.check, me.user);
      if (dirty) {
        success = me.saveChecklist(checklist);
        status = (success) ? me.STATUS.SUCCESS : me.STATUS.FAILURE;
        error = (!success) ? "checklist.save" : null;
      } else {
        status = me.STATUS.RECURRENCE;
      }
    } else {
      status = me.STATUS.FAILURE;
      error = "checklist.item.notFound";
    }

    return me.buildResponse(status, checkedItem, error);
  },

  /**
   * Marks an item as marked.
   * @return {Object}
   */
  markItem: function () {
    var me = this,
        checklist, idx, markedItem, success, status, error;

    if (typeof me.itemId === "undefined") {
      return me.buildResponse(me.STATUS.FAILURE, null, "checklist.missing.itemId");
    }

    if (typeof me.mark === "undefined") {
      return me.buildResponse(me.STATUS.FAILURE, null, "checklist.missing.mark");
    }

    checklist = me.readChecklist();
    idx = me.getItemIndex(checklist, me.itemId);

    if (typeof idx !== "undefined") {
      markedItem = checklist.items[idx];
      if (checklist.items[idx].marked !== me.mark) {
        checklist.items[idx].marked = me.mark;
        success = me.saveChecklist(checklist);
        status = (success) ? me.STATUS.SUCCESS : me.STATUS.FAILURE;
        error = (!success) ? "checklist.save" : null;
      } else {
        status = me.STATUS.RECURRENCE;
      }
    } else {
      status = me.STATUS.FAILURE;
      error = "checklist.item.notFound";
    }

    return me.buildResponse(status, markedItem, error);
  },

  /**
   * @private
   * Checks, if a sord was checked out with write access.
   * @param {de.elo.ix.client.Sord} sord
   * @return {Boolean}
   */
  hasWriteAccess: function (sord) {
    var flags, hasWriteAccess;

    flags = sord.access;
    hasWriteAccess = (flags & CONST.ACCESS.LUR_WRITE) === CONST.ACCESS.LUR_WRITE;

    return hasWriteAccess;
  },

  /**
   * @private
   * Checks if an item is valid.
   * @param {Object} item
   * @return {Boolean}
   */
  validateItem: function (item) {
    if (!item || !item.text) {
      return false;
    }
    return true;
  },

  /**
   * @private
   * Saves a checklist
   * @param {Object} checklist
   * @return {Boolean}
   */
  saveChecklist: function (checklist) {
    var me = this,
        success = false,
        desc;

    try {
      checklist.writable = undefined;
      desc = JSON.stringify(checklist, null, 2);
      me.sord.desc = desc;
      ixConnect.ix().checkinSord(me.sord, me.sordZ, LockC.NO);
      success = true;
    } catch (ex) {
      me.logger.warn("error saving checklist to sord description", ex);
    }
    return success;
  },

  /**
   * @private
   * Edits a checklist
   * @param {Object} checklist
   * @return {Boolean}
   */
  editChecklist: function () {
    var me = this,
        checklist, success, status, error;

    if (typeof me.checklistname === "undefined") {
      return me.buildResponse(me.STATUS.FAILURE, null, "checklist.missing.name");
    }

    checklist = me.readChecklist();


    if (me.checklistname) {
      me.sord.name = me.checklistname;
    }

    if (me.checklistdesc) {
      sol.common.SordUtils.setObjKeyValue(me.sord, "CHECKLIST_DESC", me.checklistdesc);
    }

    success = me.saveChecklist(checklist);
    status = (success) ? me.STATUS.SUCCESS : me.STATUS.FAILURE;
    error = (!success) ? "checklist.save" : null;

    return me.buildResponse(status, null, error);

  },

  /**
   * @private
   * Retrieves the index of an item by the ID.
   * @param {Object} checklist
   * @param {Number} id
   * @return {Number}
   */
  getItemIndex: function (checklist, id) {
    var i, idx;
    for (i = 0; i < checklist.items.length; i++) {
      if (checklist.items[i].id === id) {
        idx = i;
        break;
      }
    }
    return idx;
  },

  /**
   * @private
   * Merges an item to another.
   * @param {Object} dst Destination item
   * @param {Object} src Source item
   */
  mergeItem: function (dst, src) {
    if (!dst || !src) {
      return;
    }
    if (src.text) {
      dst.text = src.text;
    }
    if (!sol.common.StringUtils.isBlank(src.notes)) {
      dst.notes = src.notes;
    } else {
      dst.notes = undefined;
    }
  },

  /**
   * @private
   * Moves an element inside an array from one position to another.
   * @param {Object[]} items
   * @param {Number} fromIdx
   * @param {Number} toIdx
   * @return {Boolean}
   */
  moveItemInArray: function (items, fromIdx, toIdx) {
    if ((fromIdx < 0) || (fromIdx >= items.length)) {
      return false;
    }
    if (toIdx < 0) {
      toIdx = 0;
    }
    if (toIdx >= items.length) {
      toIdx = items.length - 1;
    }
    items.splice(toIdx, 0, items.splice(fromIdx, 1)[0]);
    return true;
  },

  /**
   * @private
   * Checks, or unchecks an item.
   * @param {Object} item
   * @param {Boolean} check
   * @param {de.elo.ix.client.UserInfo} user (optional) only required if `check` is `true`
   * @return {Boolean}
   */
  checkItemObject: function (item, check, user) {
    var me = this,
        edited = false;
    if ((check === true) && (item.checked !== true)) {
      item.checked = true;
      item.checkDate = sol.common.DateUtils.dateToIso(new Date());
      item.checkUser = me.createUser(user);
      edited = true;
    } else if ((check === false) && (item.checked === true)) {
      item.checked = false;
      item.checkDate = undefined;
      item.checkUser = undefined;
      edited = true;
    }
    return edited;
  },

  /**
   * @private
   * Creates a user representation.
   * @param {de.elo.ix.client.UserInfo} user
   * @return {Object} A user representation
   * @return {String} return.id The user id
   * @return {String} return.name The ELO user name
   */
  createUser: function (user) {
    var userObj;
    if (user) {
      userObj = {
        id: String(user.id),
        name: String(user.name)
      };
    }
    return userObj;
  },

  /**
   * @private
   * Builds the response object.
   * @param {String} status
   * @param {Object} item (optional)
   * @param {String} error (optional)
   * @return {Object}
   */
  buildResponse: function (status, item, error) {
    var response = { status: status };
    if (item) {
      response.item = item;
    }
    if (error) {
      response.error = error;
    }
    return response;
  }

});

/**
 * @member sol.checklist.ix.services.Checklist
 * @method RF_sol_checklist_service_ReadChecklist
 * @static
 * @inheritdoc sol.common.ix.ServiceBase#RF_ServiceBaseName
 */
function RF_sol_checklist_service_ReadChecklist(ec, args) {
  var rfUtils = sol.common.ix.RfUtils,
      params, service, result;

  logger.enter("RF_sol_checklist_service_ReadChecklist", args);

  params = rfUtils.parseAndCheckParams(ec, arguments.callee.name, args, "objId");
  service = sol.create("sol.checklist.ix.services.Checklist", params);
  result = rfUtils.stringify(service.readChecklist());

  logger.exit("RF_sol_checklist_service_ReadChecklist", result);

  return result;
}

/**
 * @member sol.checklist.ix.services.Checklist
 * @method RF_sol_checklist_service_EditChecklist
 * @static
 * @inheritdoc sol.common.ix.ServiceBase#RF_ServiceBaseName
 */
function RF_sol_checklist_service_EditChecklist(ec, args) {
  var rfUtils = sol.common.ix.RfUtils,
      params, service, result;

  logger.enter("RF_sol_checklist_service_EditChecklist", args);

  params = rfUtils.parseAndCheckParams(ec, arguments.callee.name, args, "objId");
  service = sol.create("sol.checklist.ix.services.Checklist", params);
  result = rfUtils.stringify(service.editChecklist());

  logger.exit("RF_sol_checklist_service_EditChecklist", result);

  return result;
}

/**
 * @member sol.checklist.ix.services.Checklist
 * @method RF_sol_checklist_service_MoveItem
 * @static
 * @inheritdoc sol.common.ix.ServiceBase#RF_ServiceBaseName
 */
function RF_sol_checklist_service_MoveItem(ec, args) {
  var rfUtils = sol.common.ix.RfUtils,
      params, service, result;

  logger.enter("RF_sol_checklist_service_MoveItem", args);

  params = rfUtils.parseAndCheckParams(ec, arguments.callee.name, args, "objId");
  service = sol.create("sol.checklist.ix.services.Checklist", params);
  result = rfUtils.stringify(service.moveItem());

  logger.exit("RF_sol_checklist_service_MoveItem", result);

  return result;
}

/**
 * @member sol.checklist.ix.services.Checklist
 * @method RF_sol_checklist_service_AddItem
 * @static
 * @inheritdoc sol.common.ix.ServiceBase#RF_ServiceBaseName
 */
function RF_sol_checklist_service_AddItem(ec, args) {
  var rfUtils = sol.common.ix.RfUtils,
      params, service, result;

  logger.enter("RF_sol_checklist_service_AddItem", args);

  params = rfUtils.parseAndCheckParams(ec, arguments.callee.name, args, "objId");
  service = sol.create("sol.checklist.ix.services.Checklist", params);
  result = rfUtils.stringify(service.addItem());

  logger.exit("RF_sol_checklist_service_AddItem", result);

  return result;
}

/**
 * @member sol.checklist.ix.services.Checklist
 * @method RF_sol_checklist_service_RemoveItem
 * @static
 * @inheritdoc sol.common.ix.ServiceBase#RF_ServiceBaseName
 */
function RF_sol_checklist_service_RemoveItem(ec, args) {
  var rfUtils = sol.common.ix.RfUtils,
      params, service, result;

  logger.enter("RF_sol_checklist_service_RemoveItem", args);

  params = rfUtils.parseAndCheckParams(ec, arguments.callee.name, args, "objId");
  service = sol.create("sol.checklist.ix.services.Checklist", params);
  result = rfUtils.stringify(service.removeItem());

  logger.exit("RF_sol_checklist_service_RemoveItem", result);

  return result;
}

/**
 * @member sol.checklist.ix.services.Checklist
 * @method RF_sol_checklist_service_EditItem
 * @static
 * @inheritdoc sol.common.ix.ServiceBase#RF_ServiceBaseName
 */
function RF_sol_checklist_service_EditItem(ec, args) {
  var rfUtils = sol.common.ix.RfUtils,
      params, service, result;

  logger.enter("RF_sol_checklist_service_EditItem", args);

  params = rfUtils.parseAndCheckParams(ec, arguments.callee.name, args, "objId");
  service = sol.create("sol.checklist.ix.services.Checklist", params);
  result = rfUtils.stringify(service.editItem());

  logger.exit("RF_sol_checklist_service_EditItem", result);

  return result;
}

/**
 * @member sol.checklist.ix.services.Checklist
 * @method RF_sol_checklist_service_CheckItem
 * @static
 * @inheritdoc sol.common.ix.ServiceBase#RF_ServiceBaseName
 */
function RF_sol_checklist_service_CheckItem(ec, args) {
  var rfUtils = sol.common.ix.RfUtils,
      params, service, result;

  logger.enter("RF_sol_checklist_service_CheckItem", args);

  params = rfUtils.parseAndCheckParams(ec, arguments.callee.name, args, "objId");
  params.user = ec.user;
  service = sol.create("sol.checklist.ix.services.Checklist", params);
  result = rfUtils.stringify(service.checkItem());

  logger.exit("RF_sol_checklist_service_CheckItem", result);

  return result;
}

/**
 * @member sol.checklist.ix.services.Checklist
 * @method RF_sol_checklist_service_MarkItem
 * @static
 * @inheritdoc sol.common.ix.ServiceBase#RF_ServiceBaseName
 */
function RF_sol_checklist_service_MarkItem(ec, args) {
  var rfUtils = sol.common.ix.RfUtils,
      params, service, result;

  logger.enter("RF_sol_checklist_service_MarkItem", args);

  params = rfUtils.parseAndCheckParams(ec, arguments.callee.name, args, "objId");
  service = sol.create("sol.checklist.ix.services.Checklist", params);
  result = rfUtils.stringify(service.markItem());

  logger.exit("RF_sol_checklist_service_MarkItem", result);

  return result;
}