SVG.Marker = SVG.invent({
  // Initialize node
  create: 'marker',

  // Inherit from
  inherit: SVG.Container,

  // Add class methods
  extend: {
    // Set width of element
    width: function (width) {
      return this.attr('markerWidth', width)
    },
    // Set height of element
    height: function (height) {
      return this.attr('markerHeight', height)
    },
    // Set marker refX and refY
    ref: function (x, y) {
      return this.attr('refX', x).attr('refY', y)
    },
    // Update marker
    update: function (block) {
      // remove all content
      this.clear()

      // invoke passed block
      if (typeof block === 'function') { block.call(this, this) }

      return this
    },
    // Return the fill id
    toString: function () {
      return 'url(#' + this.id() + ')'
    }
  },

  // Add parent method
  construct: {
    marker: function (width, height, block) {
      // Create marker element in defs
      return this.defs().marker(width, height, block)
    }
  }

})

SVG.extend(SVG.Defs, {
  // Create marker
  marker: function (width, height, block) {
    // Set default viewbox to match the width and height, set ref to cx and cy and set orient to auto
    return this.put(new SVG.Marker())
      .size(width, height)
      .ref(width / 2, height / 2)
      .viewbox(0, 0, width, height)
      .attr('orient', 'auto')
      .update(block)
  }

})

SVG.extend([SVG.Line, SVG.Polyline, SVG.Polygon, SVG.Path], {
  // Create and attach markers
  marker: function (marker, width, height, block) {
    var attr = ['marker']

    // Build attribute name
    if (marker !== 'all') attr.push(marker)
    attr = attr.join('-')

    // Set marker attribute
    marker = arguments[1] instanceof SVG.Marker
      ? arguments[1]
      : this.doc().marker(width, height, block)

    return this.attr(attr, marker)
  }
})