 #   the resulting values or a function of the data at that point and index of the data.
 # @option options [Functoon, String] time Either an object key or function to use for the
 #   time-component of resulting real-time plot values.
+# @option options [Function] y(d, i) Maps the data to y values given a data point and the index of the point.
 # @option options [Array] labels Labels to apply to each data layer.
 # @option options [Boolean] autoLabels Apply labels of ascending capital letters to each layer if true.
-# @option options [Boolean] keyLabels Apply labels using the keys passed to the formatter.
+# @option options [Boolean] keyLabels Apply labels using the keys passed to the formatter (defaults to true).
+# @option options [Number] startTime Unix timestamp used as the starting point for auto acsending times in 
+#   real-time data formatting.
 Epoch.Data.Format.keyvalue = (->
+  defaultOptions =
+    type: 'area',
+    x: (d, i) -> parseInt(i)
+    y: (d, i) -> d
+    time: (d, i, startTime) -> parseInt(startTime) + parseInt(i)
+    labels: []
+    autoLabels: false
+    keyLabels: true
+    startTime: parseInt(new Date().getTime() / 1000)
+
+  buildLayers = (data, keys, options, mapFn) ->
+    result = []
+    for j, key of keys
+      values = []
+      for i, d of data
+        values.push mapFn(d, key, parseInt(i))
+      result.push applyLayerLabel({ values: values }, options, parseInt(j), keys)
+    return result
+
+  formatBasicPlot = (data, keys, options) ->
+    buildLayers data, keys, options, (d, key, i) ->
+      if Epoch.isString(options.x)
+        x = d[options.x]
+      else
+        x = options.x(d, parseInt(i))
+      { x: x, y: options.y(d[key], parseInt(i)) }
+
+  formatTimePlot = (data, keys, options, rangeName='y') ->
+    buildLayers data, keys, options, (d, key, i) ->
+      if Epoch.isString(options.time)
+        value = { time: d[options.time] }
+      else
+        value = { time: options.time(d, parseInt(i), options.startTime) }
+      value[rangeName] = options.y(d[key], parseInt(i))
+      value
+
   (data=[], keys=[], options={}) ->
+    return [] unless Epoch.isArray(data) and data.length > 0 and keys.length > 0
+    opt = Epoch.Util.defaults options, defaultOptions
+
+    if opt.type == 'pie' or opt.type == 'time.gauge'
+      return []
+    else if opt.type == 'time.heatmap'
+      formatTimePlot data, keys, opt, 'histogram'
+    else if opt.type.match /^time\./
+      formatTimePlot data, keys, opt
+    else
+      formatBasicPlot data, keys, opt
+
 )()
-
 
 # Convenience data formatting method for easily accessing the various formatters.
 # @param [String] formatter Name of the formatter to use.
 # @param [Array] data Data to format.
 # @param [Object] options Options to pass to the formatter (if any).
-Epoch.data = (formatter, data, options={}) ->
+Epoch.data = (formatter, args...) ->
   return [] unless (formatFn = Epoch.Data.Format[formatter])?
-  formatFn(data, options)
+  formatFn.apply formatFn, args

# It then extracts the value for each key across each of the objects in the array
# to produce multi-layer plot data of the given chart type. Note that this formatter
# also can be passed an <code>x</code> or <code>time</code> option as a string that
# allows the programmer specify a kto define which key to use for the value of the
# first component of each resulting layer value.
#
# @param [Array] data Flat array of objects to format.
# @param [Array] keys List of keys used to extract data from each of the objects.

      formatBasicPlot data, opt
)()

# Formats an input array of tuples such that the first element of the tuple is set
# as the x-coordinate and the second element as the y-coordinate. Supports layers
# of tupled series. For real-time plots the first element of a tuple is set as the
