var exec = require ('child_process') .exec;
var xml2json = require ('node-xml2json');

var set = {
  bin: 'vnstat',
  iface: 'eth0'
};

// Load config
function getConfig (callback) {
  exec (set.bin +' --showconfig', function (err, text, stderr) {
    if (err) {
      var error = new Error ('no config');
      error.details = text;
      error.error = err;
      callback (error);
    }

    var config = {};
    var i;

    text = text.split ('\n');
    for (i = 0; i < text.length; i++) {
      var line = text [i] .trim ();
      if (line.substr (0,1) != '#') {
        line.replace (/(\w+)\s+(.+)/, function (s, key, val) {
          config [key] = val.slice (0, 1) === '"' ? val.slice (1, -1) : val;
        });
      }
    }
    callback (null, config);
  });
}

// parse interface
function fixInterface (iface) {
  var i;

  // id
  if (iface.id && iface.id [0]) {
    iface.id = iface.id [0];
  }

  // days
  if (iface.traffic.days.day [0]) {
    for (i = 0; i < iface.traffic.days.day.length; i++) {
      iface.traffic.days.day [i] .rx = iface.traffic.days.rx [i] || iface.traffic.days.day [i] .rx || 0;
      iface.traffic.days.day [i] .tx = iface.traffic.days.tx [i] || iface.traffic.days.day [i] .tx || 0;
    }
    iface.traffic.days = iface.traffic.days.day;
  } else if (iface.traffic.days.day.id) {
    var day = iface.traffic.days.day;
    day.rx = iface.traffic.days.rx || iface.traffic.days.day.rx || 0;
    day.tx = iface.traffic.days.tx || iface.traffic.days.day.tx || 0;
    iface.traffic.days = [day];
  }

  // months
  if (iface.traffic.months.month [0]) {
    for (i = 0; i < iface.traffic.months.month.length; i++) {
      iface.traffic.months.month [i] .rx = iface.traffic.months.rx [i] || iface.traffic.months.month [i] .rx || 0;
      iface.traffic.months.month [i] .tx = iface.traffic.months.tx [i] || iface.traffic.months.month [i] .tx || 0;
    }
    iface.traffic.months = iface.traffic.months.month;
  } else if (iface.traffic.months.month.id) {
    var month = iface.traffic.months.month;
    month.rx = iface.traffic.months.rx || 0;
    month.tx = iface.traffic.months.tx || 0;
    iface.traffic.months = [month];
  }

  // hours
  iface.traffic.hours = iface.traffic.hours.hour || iface.traffic.hour || [];

  // tops
  if (!iface.traffic.tops.top) {
    iface.traffic.tops = [];
  } else {
    iface.traffic.tops = iface.traffic.tops.top;
  }

  return iface;
}

// --dumpdb
function dumpdb (iface, callback) {
  if (typeof iface === 'function') {
    callback = iface;
    iface = set.iface;
  }
  exec (set.bin +' -i '+ iface +' --dumpdb --xml', function (err, xml, stderr) {
    var error = null;
    if (err instanceof Error) {
      error = new Error (stderr.trim ());
      callback (error);
    }

    try {
      xml = xml2json.parser (xml.trim ());
      if (!xml.vnstat) {
        error = new Error ('invalid xml');
        error.details = xml;
      } else {
        if (xml.vnstat.interface [0]) {
          // multiple
          var ifaces = {};
          var i;
          for (i = 0; i < xml.vnstat.interface.length; i++) {
            iface = fixInterface (xml.vnstat.interface [i]);
            ifaces [iface.id || iface.nick] = iface;
          }
          xml = ifaces;
        } else {
          // just one iface
          xml = fixInterface (xml.vnstat.interface);
        }
      }
    }
    catch (e) {
      error = new Error ('can not process');
      error.details = xml || '';
      error.error = e;
      xml = null;
    }
    finally {
      callback (error, xml);
    }
  });
};

// Setup
module.exports = function (setup) {
  if (setup instanceof Object) {
    for (var key in setup) {
      set [key] = setup [key];
    }
  }

  return {
    dumpdb: dumpdb,
    getConfig: getConfig,
    set: set
  };
};

@@ -122,14 +122,26 @@
 ce: 
-'eth0'
+null,%0A  config: %7B%7D
 %0A%7D;%0A
@@ -2418,138 +2418,61 @@
 %0A// 
---dumpdb%0Afunction dumpdb (iface, callback) %7B%0A  if (typeof iface === 'function') %7B%0A    callback = iface;%0A    iface = set.iface;%0A  %7D
+Get database%0Afunction getDatabase (iface, callback) %7B
 %0A  e
@@ -3478,17 +3478,440 @@
 %0A  %7D);%0A%7D
-;
+%0A%0A// --dumpdb%0Afunction dumpdb (iface, callback) %7B%0A  if (typeof iface === 'function') %7B%0A    callback = iface;%0A    iface = set.iface;%0A  %7D%0A%0A  iface = iface %7C%7C set.config.Interface %7C%7C null;%0A%0A  if (!iface) %7B%0A    getConfig (function (err, data) %7B%0A      if (!err) %7B%0A        set.config = data;%0A        iface = data.Interface;%0A        getDatabase (iface, callback);%0A      %7D%0A    %7D);%0A  %7D else %7B%0A    getDatabase (iface, callback);%0A  %7D%0A%7D
 %0A%0A// Set

Check iface setting or load from config