function AtomWriter(mapSettings) {
   var _self = this;

   _self.collection = mapSettings.collection; // collection name, according to KnowMax specification.
   _self.querystring = mapSettings.querystring; // optional querystring option, according to KnowMax specification.
   _self.itemTemplate = mapSettings.itemTemplate; // Html template with @fields that match the returned data tagnames
   _self.rootElement = mapSettings.rootElement; //the element into which to dump the output HTML
   _self.preFormat = mapSettings.preFormat; //optional function to perform custom preformatting of an item's contents. Takes an item and must return that item.
   _self.items = null;

   function main() {
      if (!_self.collection) {
         console.log('No collection specified.');
         return;
      }
      if (!_self.itemTemplate) {
         console.log('No item template specified.');
         return;
      }
      if (!_self.rootElement) {
         console.log('No target root element specified.');
         return;
      }

      getAtomArrayOfMaps();
   }

   _self.write = function () {
      var _html = '', _itemhtml, _key;
      var replaceTags = _self.itemTemplate.match(/@[a-z]+/g);

      if (replaceTags) {
         for (var i=0; i < _self.items.length; i++) {
            _itemhtml = _self.itemTemplate;
            if (_self.preFormat) {
               _self.items[i] = _self.preFormat(_self.items[i]);
            }

            for (var j=0; j < replaceTags.length; j++) {
               _key = replaceTags[j].replace('@','');
               _value = _self.items[i][ _key ].replace(/^@+/,'');
               _itemhtml = _itemhtml.replace(new RegExp(replaceTags[j],'g'), _value);
            }

            _html += _itemhtml;
         }
      }

      //console.log(_self.rootElement);
      //console.log(_html);

      _self.rootElement.html(_html);
   };

   function getAtomArrayOfMaps(strCollection, strOptions) {
      //according to the docs of datajs 0.0.3, handler is optional. Except it's not. The docs are a lie.
      //So here's dummy code to makes sure it doesn't throw an error.
      var dummyHandler = { read: function (response) {} };

      OData.read(
         '/templates/snippets/odata_js_middleman.asp?collectionpath='+ _self.collection +'&options='+ escape(_self.querystring),
         function success(data, response) {
            var responseDOM = $(response.body);
            var arrEntries = [];

            responseDOM.filter('feed').children().each(function () {
               if (this.nodeName.toLowerCase() == 'entry') {
                  arrEntries.push(this);
               }
            });

            var aomItems = new Array();
            var mapItem;

            /// On completion of the request, format all relevant data into a standard ArrayOfMaps
            /// and place that into _self.items for further usage.
            for (var i=0; i < arrEntries.length; i++) {
               mapItem = {};
               // The actual data is buried quite deep in what seems to be a completely pointless set of Atom tags with
               // a custom data extension; hence the weird long children.children[0].children.cousins[15].grandchildren.descendants.dnaevolution.etcetera structure.
               $(arrEntries[i]).children('content').children().eq(0).children().each(function () {
                  mapItem[ this.tagName.replace('D:','').toLowerCase() ] = this.innerHTML;
               });
               aomItems.push(mapItem);
            };

            _self.items = aomItems;
            _self.write();
         },
         function error(err) {
            try {
               console.log('ERROR OData.read()');
               console.log('Message:', err.message);
               console.log('err obj', err);
            }
            catch (err) {
               //TODO: find out why OData fails inside mercury/IE7
               // until then, swallow the error.
            }
         },
         dummyHandler
      );
   }

   main();
}

function formatDateFromUTC(strDate) {
   // Input format from Atom: 2011-02-01T00:00:00

   var dtInput, formattedDate;
   var dateTime = strDate.split('T');

   dateTime.date = dateTime[0].split('-');
   dateTime.time = dateTime[1].split(':');

   formattedDate = ''
      + dateTime.date[2]
      + '-'
      + dateTime.date[1]
      + '-'
      + dateTime.date[0]

   // Date toString:
   // IE  Wed Mar 2 00:00:00 UTC+0100 2011
   // FFX Wed Mar 02 2011 00:00:00 GMT+0100
   // CHR Wed Mar 02 2011 00:00:00 GMT+0100 (West-Europa (standaardtijd))
   // SAF Wed Mar 02 2011 00:00:00 GMT+0100 (West-Europa (standaardtijd))
   // OP  Wed Mar 02 2011 00:00:00 GMT+0100
   // :(((((((((

   return formattedDate;
}
