var dl = require('datalib'),
    log = require('vega-logging'),
    Model = require('../core/Model'),
    View = require('../core/View');

/**
 * Parse graph specification
 * @param spec (object)
 * @param config (optional object)
 * @param viewFactory (optional function)
 * @param callback (error, model)
 */
 function parseSpec(spec /*, [config,] [viewFactory,] callback */) {
  // do not assign any values to callback, as it will change arguments
  var arglen = arguments.length,
      argidx = 2,
      cb = arguments[arglen-1],
      model = new Model(),
      viewFactory = View.factory;

  if (arglen > argidx && dl.isFunction(arguments[arglen - argidx])) {
    viewFactory = arguments[arglen - argidx];
    ++argidx;
  }
  if (arglen > argidx && dl.isObject(arguments[arglen - argidx])) {
    model.config(arguments[arglen - argidx]);
  }

  function onDone(err, value) {
    if (cb) {
      if (cb.length > 1) cb(err, value);
      else if (!err) cb(value);
      cb = null;
    }
  }

  function onError(err) {
    log.error(err);
    onDone(err);
  }

  function onCreate(err) {
    if (err) onError(err);
    else onDone(null, viewFactory(model));
  }

  function parse(spec) {
    try {
      // protect against subsequent spec modification
      spec = dl.duplicate(spec);
      
      var paddingVar = spec.padding || (typeof config !== 'undefined' && config.padding);

      var parsers = require('./'),
          width   = spec.width || (typeof config !== 'undefined' && config.width) || 500,
          height  = spec.height || (typeof config !== 'undefined' && config.height) || 500,
          padding = parsers.padding(paddingVar),
          background = spec.background || (typeof config !== 'undefined' && config.background);

      // create signals for width, height and padding
      model.signal('width', width);
      model.signal('height', height);
      model.signal('padding', padding);

      // initialize model
      model.defs({
        width:      width,
        height:     height,
        padding:    padding,
        viewport:   spec.viewport || null,
        background: parsers.background(background),
        signals:    parsers.signals(model, spec.signals),
        predicates: parsers.predicates(model, spec.predicates),
        marks:      parsers.marks(model, spec, width, height),
        data:       parsers.data(model, spec.data, onCreate)
      });
    } catch (err) { onError(err); }
  }

  if (dl.isObject(spec)) {
    parse(spec);
  } else if (dl.isString(spec)) {
    var opts = dl.extend({url: spec}, model.config().load);
    dl.json(opts, function(err, spec) {
      if (err) onError('SPECIFICATION LOAD FAILED: ' + err);
      else parse(spec);
    });
  } else {
    onError('INVALID SPECIFICATION: Must be a valid JSON object or URL.');
  }
}

module.exports = parseSpec;

parseSpec.schema = {
  "defs": {
    "spec": {
      "title": "Vega visualization specification",
      "type": "object",

      "allOf": [{"$ref": "#/defs/container"}, {
        "properties": {
          "width": {"type": "number"},
          "height": {"type": "number"},
          "viewport": {
            "type": "array",
            "items": {"type": "number"},
            "maxItems": 2
          },

          "background": {"$ref": "#/defs/background"},
          "padding": {"$ref": "#/defs/padding"},

          "signals": {
            "type": "array",
            "items": {"$ref": "#/defs/signal"}
          },

          "predicates": {
            "type": "array",
            "items": {"$ref": "#/defs/predicate"}
          },

          "data": {
            "type": "array",
            "items": {"$ref": "#/defs/data"}
          }
        }
      }]
    }
  }
};

@@ -1316,106 +1316,28 @@
  = s
-pec.padding %7C%7C (typeof config !== 'undefined' && config.padding);%0A%0A      var parsers = require('./
+etVal(spec, 'padding
 '),%0A
@@ -1356,80 +1356,36 @@
 dth 
-  
 = s
-pec.width %7C%7C (typeof config !== 'undefined' && config.
+etVal(spec, '
 width
-) %7C%7C
+',
  500
+)
 ,%0A  
@@ -1403,225 +1403,172 @@
 ght 
- 
 = s
-pec.height %7C%7C (typeof config !== 'undefined' && config.height) %7C%7C 500,%0A          padding = parsers.padding(paddingVar),%0A          background = spec.background %7C%7C (typeof config !== 'undefined' && config.background
+etVal(spec, 'height', 500),%0A          background = setVal(spec, 'background');%0A%0A      var parsers = require('./'),%0A          padding = parsers.padding(paddingVar
 );%0A%0A
@@ -2257,16 +2257,305 @@
  %7D%0A  %7D%0A%0A
+  function setVal(spec, property, defaultVal) %7B%0A    if (spec%5Bproperty%5D) %7B%0A      return spec%5Bproperty%5D;%0A    %7D%0A    if (typeof config !== 'undefined') %7B%0A      return config%5Bproperty%5D%0A    %7D%0A    if (typeof defaultVal !== 'undefined') %7B%0A      return defaultVal;%0A    %7D%0A    return undefined;%0A  %7D%0A%0A
   if (dl

Fix config check bug