 spec = {
   selector: '.cont'
   size:
-    width: 600
+    width:  800
     height: 600
   dataSpec:
     from: data
     dimensions:
+      Time:   { type: 'continuous', bin: 'second' }
       Letter: { type: 'categorical' }
       Number: { type: 'ordinal' }
     metrics:
+      Const:  { agg: 'const' }
       Count:  { agg: 'count' }
-      Walk:   { agg: 'avg' }
+      Walk:   { agg: 'average' }
   plot:
     type: 'facet'
+    method: 'vertical'
+    mapping: { area: 'Const' }
     split: 'Letter'
     scale:
-      x: { type: 'linear', column: 'Time' }
-    plot:
-      type: 'points'
-      mapping:
-        x: 'Time'
-        y: 'Walk'
-        color: 'Letter'
-      scale:
-        y: { type: 'linear', column: 'Walk' }
-        color: { type: 'color', column: 'Letter' }
+      x: { type: 'linear', from: 'Time' }
+    # plot:
+    #   split: 'Time'
+    #   type: 'point'
+    #   mapping:
+    #     x: 'Time'
+    #     y: 'Walk'
+    #     color: 'Letter'
+    #   scale:
+    #     y: { type: 'linear', from: 'Walk' }
+    #     color: { type: 'color', from: 'Letter' }
 }
 
 #facet.plot spec
-facet.makeData spec
-
-
-
+console.log '-----------'
+console.log facet.makeData(spec)
+console.log '-----------'
+
+testCarData = [
+  { make: 'Honda',  model: 'Civic',   price: 10000 }
+  { make: 'Honda',  model: 'Civic',   price: 10100 }
+  { make: 'Honda',  model: 'Element', price: 13000 }
+  { make: 'Toyota', model: 'Corrola', price: 11000 }
+  { make: 'Toyota', model: 'Corrola', price: 11100 }
+  { make: 'BMW',    model: 'M3',      price: 51000 }
+  { make: 'BMW',    model: 'M5',      price: 61000 }
+]
+
+console.log facet.data(testCarData).query {
+  dimensions:
+    'Make': { type: 'categorical' }
+    'Model': { type: 'categorical' }
+  metrics:
+    'Total Price': { agg: 'sum', column: 'price' }
+    'Avg Price': { agg: 'average', column: 'price' }
+    'Count': { agg: 'count' }
+  splits: [
+    { split: 'Make',  apply: ['Count', 'Total Price', 'Avg Price'] }
+    { split: 'Model', apply: ['Count', 'Total Price', 'Avg Price'] }
+  ]
+}
+
+# what is the most common model of car for each manufacturer
+# carSales.split('Mfr', [], 'alphbetic').split('Model', 'count', 'sort desc limit 1')
+# carSales.split('Mfr', Model_most_popular, 'alphbetic')
+

# Dimension = {row} -> String
# Metric = {row} -> Number
# [Metric] = {row} -> [Number]

aggregartion = {
  sum: (values) ->
    s = 0
    s += v for v in values
    return s

  average: (values) ->
    s = 0
    s += v for v in values
    return s / values.length
}

sortedUniq = (arr) ->
  u = []

    newObj[k] = v
  return newObj

makeArray = (obj) ->
  if obj? then (if obj.splice then obj else [obj]) else []

acc = (column) ->
  throw "no such column" unless column?
  return column if typeof column is 'function'
  return (d) -> d[column]

cross = (arrays) ->
  vectorName = []
  vectorValues = []
  retLength = 1
  for k,vs of arrays
    return [] unless vs.splice
    vectorName.push(k)
    vectorValues.push(vs)
    retLength *= vs.length

  return [] unless vectorValues.length

  ret = []
  i = 0
  while i < retLength
    row = {}
    k = i
    for vs,j in vectorValues
      t = k % vs.length
      row[vectorName[j]] = vs[t]
      k = Math.floor(k / vs.length)

    ret[i] = row
    i++

  return ret


window.tile = {
  vertical: (rect, datas) ->
    total = 0
    for d in datas
      total += d

    scale = rect.height / total
    rects = []
    y = 0
    for d in datas
      h = d * scale
      rects.push {
        x: 0
        y: y
        width: rect.width
        height: h
      }
      y += h

    return rects
}

# ------------------------------------------------------------------

# Valid:
# {name, column} = {name}
# {name, type: all }
facet.dimension = do ->
  binMap = {
    millisecond: 1
    second: 1000
    minute: 60 * 1000
    hour: 60 * 60 * 1000
    day: 24 * 60 * 60 * 1000
    week: 7 * 24 * 60 * 60 * 1000
  }
  return (name, {column, type, bin}) ->
    throw "name can not start with $  (#{name})" if name[0] is '$'
    column = name.toLowerCase() unless column
    switch type
      when 'all'
        fn = (row) -> '$all'
      when 'categorical'
        throw 'categorical dimension must have column' unless column
        fn = (row) -> row[column]
      when 'ordinal'
        throw 'ordinal dimension must have column' unless column
        fn = (row) -> row[column]
      when 'continuous'
        throw 'continuous dimension must have column' unless column
        throw 'continuous dimension must have bin' unless bin
        bin = binMap[bin] if binMap[bin]
        fn = (row) -> Math.floor(row[column] / bin)
      else
        throw 'must have a type'
    fn.$name = name
    return fn

# Valid:
# {column}
# {agg: 'count' }
facet.metric = do ->
  aggregartion = {
    sum: (values) ->
      sum = 0
      for v in values
        sum += v
      return sum

    average: (values) ->
      sum = 0
      for v in values
        sum += v
      return sum / values.length

    uniq: (values) ->
      seen = {}
      count = 0
      for v in values
        continue if seen[v]
        count++
        seen[v] = 1
      return count

    common: (values) ->
      counts = {}
      # to do
      return values[0]
  }
  return (name, {column, agg}) ->
    throw "name can not start with $  (#{name})" if name[0] is '$'
    column = name.toLowerCase() unless column
    if agg is 'const'
      fn = (rows) -> 1
    else if agg is 'count'
      fn = (rows) -> rows.length
    else if column
      a = aggregartion[agg]
      throw "invalid agg (#{agg})" unless a
      fn = (rows) -> a(rows.map((d) -> d[column]))
    else
      throw "needs agg == 'count' or column"
    fn.$name = name
    return fn


# combine =
#  sort: <dimension or metric name>
#  order: asc | desc
#  skip: <number>
#  limit: <number>
facet.data = (rows) ->
  splits = []
  dimensions = {}
  metrics = {}

  makeSac = ({split, apply, combine}, breakdown) -> (rows) ->
    buckets = {}
