text: 'use strict'
  var extensionElementsHelper = require('../../../../helper/ExtensionElementsHelper'),
    elementHelper = require('../../../../helper/ElementHelper'),
    cmdHelper = require('../../../../helper/CmdHelper')
  
  var utils = require('../../../../Utils')
  
  var entryFactory = require('../../../../factory/EntryFactory')
  
  var extensionElementsEntry = require('./ExtensionElements')
  
  var ModelUtil = require('bpmn-js/lib/util/ModelUtil'),
    getBusinessObject = ModelUtil.getBusinessObject
  
  var assign = require('lodash/assign')
  
  var DEFAULT_PROPS = {
    stringValue: undefined,
    string: undefined,
    expression: undefined
  }
  
  var ACTIVITI_FIELD_EXTENSION_ELEMENT = 'activiti:FormProperty'
  
  module.exports = function (element, bpmnFactory, translate, options) {
    options = options || {}
  
    var insideListener = !!options.insideListener,
      idPrefix = options.idPrefix || '',
      getSelectedListener = options.getSelectedListener,
      businessObject = options.businessObject || getBusinessObject(element)
  
    var entries = []
  
    var isSelected = function (element, node) {
      return getSelectedField(element, node)
    }
  
    function getSelectedField(element, node) {
      var selected = fieldEntry.getSelected(element, node.parentNode)
  
      if (selected.idx === -1) {
        return
      }
  
      var fields = getActivitiFields(element, node)
  
      return fields[selected.idx]
    }
  
    function getActivitiFields(element, node) {
      if (!insideListener) {
        return (
          (businessObject &&
            extensionElementsHelper.getExtensionElements(businessObject, ACTIVITI_FIELD_EXTENSION_ELEMENT)) ||
          []
        )
      }
      return getActivitiListenerFields(element, node)
    }
  
    function getActivitiListenerFields(element, node) {
      var selectedListener = getSelectedListener(element, node)
      return (selectedListener && selectedListener.fields) || []
    }
  
    function getFieldType(bo) {
      var fieldType = 'string'
  
      var expressionValue = bo && bo.expression
      var stringValue = bo && (bo.string || bo.stringValue)
  
      if (typeof stringValue !== 'undefined') {
        fieldType = 'string'
      } else if (typeof expressionValue !== 'undefined') {
        fieldType = 'expression'
      }
  
      return fieldType
    }
  
    var setOptionLabelValue = function () {
      return function (element, node, option, property, value, idx) {
        var activitiFields = getActivitiFields(element, node)
        var field = activitiFields[idx]
  
        value = field.name ? field.name : '<empty>'
  
        var label = idx + ' : ' + value
  
        option.text = label
      }
    }
  
    var newElement = function () {
      return function (element, extensionElements, value, node) {
        var props = {
          name: '',
          string: ''
        }
  
        var newFieldElem
  
        if (!insideListener) {
          newFieldElem = elementHelper.createElement(
            ACTIVITI_FIELD_EXTENSION_ELEMENT,
            props,
            extensionElements,
            bpmnFactory
          )
          return cmdHelper.addElementsTolist(element, extensionElements, 'values', [newFieldElem])
        } else {
          var selectedListener = getSelectedListener(element, node)
          newFieldElem = elementHelper.createElement(
            ACTIVITI_FIELD_EXTENSION_ELEMENT,
            props,
            selectedListener,
            bpmnFactory
          )
          return cmdHelper.addElementsTolist(element, selectedListener, 'fields', [newFieldElem])
        }
      }
    }
  
    var removeElement = function () {
      return function (element, extensionElements, value, idx, node) {
        var activitiFields = getActivitiFields(element, node)
        var field = activitiFields[idx]
        if (field) {
          if (!insideListener) {
            return extensionElementsHelper.removeEntry(businessObject, element, field)
          }
          var selectedListener = getSelectedListener(element, node)
          return cmdHelper.removeElementsFromList(element, selectedListener, 'fields', null, [field])
        }
      }
    }
  
    var fieldEntry = extensionElementsEntry(element, bpmnFactory, {
      id: idPrefix + 'fields',
      label: translate('Fields'),
      modelProperty: 'fieldName',
      idGeneration: 'false',
  
      businessObject: businessObject,
  
      createExtensionElement: newElement(),
      removeExtensionElement: removeElement(),
  
      getExtensionElements: function (element, node) {
        return getActivitiFields(element, node)
      },
  
      setOptionLabelValue: setOptionLabelValue()
    })
    entries.push(fieldEntry)
  
    entries.push(
      entryFactory.validationAwareTextField({
        id: idPrefix + 'field-name',
        label: translate('Name'),
        modelProperty: 'fieldName',
  
        getProperty: function (element, node) {
          return (getSelectedField(element, node) || {}).name
        },
  
        setProperty: function (element, values, node) {
          var selectedField = getSelectedField(element, node)
          return cmdHelper.updateBusinessObject(element, selectedField, { name: values.fieldName })
        },
  
        validate: function (element, values, node) {
          var bo = getSelectedField(element, node)
  
          var validation = {}
          if (bo) {
            var nameValue = values.fieldName
  
            if (nameValue) {
              if (utils.containsSpace(nameValue)) {
                validation.fieldName = translate('Name must not contain spaces')
              }
            } else {
              validation.fieldName = translate('Parameter must have a name')
            }
          }
  
          return validation
        },
  
        hidden: function (element, node) {
          return !isSelected(element, node)
        }
      })
    )
  
    var fieldTypeOptions = [
      {
        name: translate('String'),
        value: 'string'
      },
      {
        name: translate('Expression'),
        value: 'expression'
      }
    ]
  
    entries.push(
      entryFactory.selectBox({
        id: idPrefix + 'field-type',
        label: translate('Type'),
        selectOptions: fieldTypeOptions,
        modelProperty: 'fieldType',
  
        get: function (element, node) {
          var bo = getSelectedField(element, node)
  
          var fieldType = getFieldType(bo)
  
          return {
            fieldType: fieldType
          }
        },
  
        set: function (element, values, node) {
          var props = assign({}, DEFAULT_PROPS)
  
          var fieldType = values.fieldType
  
          if (fieldType === 'string') {
            props.string = ''
          } else if (fieldType === 'expression') {
            props.expression = ''
          }
  
          return cmdHelper.updateBusinessObject(element, getSelectedField(element, node), props)
        },
  
        hidden: function (element, node) {
          return !isSelected(element, node)
        }
      })
    )
  
    entries.push(
      entryFactory.textBox({
        id: idPrefix + 'field-value',
        label: translate('Value'),
        modelProperty: 'fieldValue',
  
        get: function (element, node) {
          var bo = getSelectedField(element, node)
          var fieldType = getFieldType(bo)
  
          var fieldValue
  
          if (fieldType === 'string') {
            fieldValue = bo && (bo.string || bo.stringValue)
          } else if (fieldType === 'expression') {
            fieldValue = bo && bo.expression
          }
  
          return {
            fieldValue: fieldValue
          }
        },
  
        set: function (element, values, node) {
          var bo = getSelectedField(element, node)
          var fieldType = getFieldType(bo)
  
          var props = assign({}, DEFAULT_PROPS)
  
          var fieldValue = values.fieldValue || undefined
  
          if (fieldType === 'string') {
            props.string = fieldValue
          } else if (fieldType === 'expression') {
            props.expression = fieldValue
          }
  
          return cmdHelper.updateBusinessObject(element, bo, props)
        },
  
        validate: function (element, values, node) {
          var bo = getSelectedField(element, node)
  
          var validation = {}
          if (bo) {
            if (!values.fieldValue) {
              validation.fieldValue = translate('Must provide a value')
            }
          }
  
          return validation
        },
  
        show: function (element, node) {
          return isSelected(element, node)
        }
      })
    )
  
    return entries
  }
  