text: 'use strict'
  
  var assign = require('lodash/assign')
  
  /**
   * Create an input parameter representing the given
   * binding and value.
   *
   * @param {PropertyBinding} binding
   * @param {String} value
   * @param {BpmnFactory} bpmnFactory
   *
   * @return {ModdleElement}
   */
  function createInputParameter(binding, value, bpmnFactory) {
    var scriptFormat = binding.scriptFormat,
      parameterValue,
      parameterDefinition
  
    if (scriptFormat) {
      parameterDefinition = bpmnFactory.create('flowable:Script', {
        scriptFormat: scriptFormat,
        value: value
      })
    } else {
      parameterValue = value
    }
  
    return bpmnFactory.create('flowable:InputParameter', {
      name: binding.name,
      value: parameterValue,
      definition: parameterDefinition
    })
  }
  
  module.exports.createInputParameter = createInputParameter
  
  /**
   * Create an output parameter representing the given
   * binding and value.
   *
   * @param {PropertyBinding} binding
   * @param {String} value
   * @param {BpmnFactory} bpmnFactory
   *
   * @return {ModdleElement}
   */
  function createOutputParameter(binding, value, bpmnFactory) {
    var scriptFormat = binding.scriptFormat,
      parameterValue,
      parameterDefinition
  
    if (scriptFormat) {
      parameterDefinition = bpmnFactory.create('flowable:Script', {
        scriptFormat: scriptFormat,
        value: binding.source
      })
    } else {
      parameterValue = binding.source
    }
  
    return bpmnFactory.create('flowable:OutputParameter', {
      name: value,
      value: parameterValue,
      definition: parameterDefinition
    })
  }
  
  module.exports.createOutputParameter = createOutputParameter
  
  /**
   * Create flowable property from the given binding.
   *
   * @param {PropertyBinding} binding
   * @param {String} value
   * @param {BpmnFactory} bpmnFactory
   *
   * @return {ModdleElement}
   */
  function createFlowableProperty(binding, value, bpmnFactory) {
    return bpmnFactory.create('flowable:Property', {
      name: binding.name,
      value: value || ''
    })
  }
  
  module.exports.createFlowableProperty = createFlowableProperty
  
  /**
   * Create flowable:in element from given binding.
   *
   * @param {PropertyBinding} binding
   * @param {String} value
   * @param {BpmnFactory} bpmnFactory
   *
   * @return {ModdleElement}
   */
  function createFlowableIn(binding, value, bpmnFactory) {
    var properties = createFlowableInOutAttrs(binding, value)
  
    return bpmnFactory.create('flowable:In', properties)
  }
  
  module.exports.createFlowableIn = createFlowableIn
  
  /**
   * Create flowable:in with businessKey element from given binding.
   *
   * @param {PropertyBinding} binding
   * @param {String} value
   * @param {BpmnFactory} bpmnFactory
   *
   * @return {ModdleElement}
   */
  function createFlowableInWithBusinessKey(binding, value, bpmnFactory) {
    return bpmnFactory.create('flowable:In', {
      businessKey: value
    })
  }
  
  module.exports.createFlowableInWithBusinessKey = createFlowableInWithBusinessKey
  
  /**
   * Create flowable:out element from given binding.
   *
   * @param {PropertyBinding} binding
   * @param {String} value
   * @param {BpmnFactory} bpmnFactory
   *
   * @return {ModdleElement}
   */
  function createFlowableOut(binding, value, bpmnFactory) {
    var properties = createFlowableInOutAttrs(binding, value)
  
    return bpmnFactory.create('flowable:Out', properties)
  }
  
  module.exports.createFlowableOut = createFlowableOut
  
  /**
   * Create flowable:executionListener element containing an inline script from given binding.
   *
   * @param {PropertyBinding} binding
   * @param {String} value
   * @param {BpmnFactory} bpmnFactory
   *
   * @return {ModdleElement}
   */
  function createFlowableExecutionListenerScript(binding, value, bpmnFactory) {
    var scriptFormat = binding.scriptFormat,
      parameterValue,
      parameterDefinition
  
    if (scriptFormat) {
      parameterDefinition = bpmnFactory.create('flowable:Script', {
        scriptFormat: scriptFormat,
        value: value
      })
    } else {
      parameterValue = value
    }
  
    return bpmnFactory.create('flowable:ExecutionListener', {
      event: binding.event,
      value: parameterValue,
      script: parameterDefinition
    })
  }
  
  module.exports.createFlowableExecutionListenerScript = createFlowableExecutionListenerScript
  
  /**
   * Create flowable:field element containing string or expression from given binding.
   *
   * @param {PropertyBinding} binding
   * @param {String} value
   * @param {BpmnFactory} bpmnFactory
   *
   * @return {ModdleElement}
   */
  function createFlowableFieldInjection(binding, value, bpmnFactory) {
    var DEFAULT_PROPS = {
      'string': undefined,
      'expression': undefined,
      'name': undefined
    }
  
    var props = assign({}, DEFAULT_PROPS)
  
    if (!binding.expression) {
      props.string = value
    } else {
      props.expression = value
    }
    props.name = binding.name
  
    return bpmnFactory.create('flowable:Field', props)
  }
  module.exports.createFlowableFieldInjection = createFlowableFieldInjection
  
  // helpers ////////////////////////////
  
  /**
   * Create properties for flowable:in and flowable:out types.
   */
  function createFlowableInOutAttrs(binding, value) {
    var properties = {}
  
    // flowable:in source(Expression) target
    if (binding.target) {
      properties.target = binding.target
  
      if (binding.expression) {
        properties.sourceExpression = value
      } else {
        properties.source = value
      }
    } else
  
    // flowable:(in|out) variables local
    if (binding.variables) {
      properties.variables = 'all'
  
      if (binding.variables === 'local') {
        properties.local = true
      }
    }
  
    // flowable:out source(Expression) target
    else {
      properties.target = value;
  
      ['source', 'sourceExpression'].forEach(function(k) {
        if (binding[k]) {
          properties[k] = binding[k]
        }
      })
    }
  
    return properties
  }
  