/*
** Module dependencies
*/
var libxml = require('libxmljs');
var _ = require('lodash');
var ns = require('./namespaces');


/*
** Helpers
*/
function ensureXml(xmlDoc) {
    if (_.isString(xmlDoc)) {
        xmlDoc = libxml.parseXmlString(xmlDoc, { noblanks: true });
    }
    return xmlDoc;
}

function mapFields(scheme, xmlDoc, dest) {
    _.forEach(scheme, function(fieldName, xpath) {
        var node = xmlDoc.get(xpath, ns), value;
        if (!node) return;
        if (node.type() === 'attribute') value = node.value();
        if (node.type() === 'element') value = node.text();
        if (value.length > 0) dest[fieldName] = value;
    });
}

function mapKeywords(xmlDoc, dest) {
    var nodes = xmlDoc.find('.//gmd:identificationInfo//gmd:keyword', ns);
    if (nodes && nodes.length) {
        dest.keywords = [];
        _.forEach(nodes, function(node) {
            var keyword = node.text();
            if (keyword && keyword.length) dest.keywords.push(keyword);
        });
    }
}

function mapOnlineResources(xmlDoc, dest) {
    var nodes = xmlDoc.find('.//gmd:distributionInfo//gmd:transferOptions//gmd:onLine', ns);
    if (nodes && nodes.length) {
        dest.onlineResources = [];
        _.forEach(nodes, function(node) {
            var obj = {};
            mapFields(onlineResourceMapping, node, obj);
            if (obj.link) dest.onlineResources.push(obj);
        });
    }
}

/*
** Mappings
*/
var commonMapping = {
    './/gmd:identificationInfo//gmd:citation//gmd:title': 'title',
    './/gmd:identificationInfo//gmd:abstract': 'abstract',
    './/gmd:fileIdentifier': 'fileIdentifier',
    './/gmd:identificationInfo//gmd:identifier': 'identifier',
    './/gmd:identificationInfo//gmd:language': 'language',
    './/gmd:dataQualityInfo//gmd:lineage//gmd:statement': 'lineage',
    './/gmd:hierarchyLevel/gmd:MD_ScopeCode/@codeListValue': 'type',
    './/gmd:identificationInfo//gmd:MD_SpatialRepresentationTypeCode/@codeListValue': 'representationType'
};

var serviceMapping = {
    './/gmd:identificationInfo//srv:serviceType': 'serviceType'
};

var onlineResourceMapping = {
    './/gmd:linkage': 'link',
    './/gmd:protocol': 'protocol',
    './/gmd:description': 'description',
    './/gmd:name': 'name'
};

/*
** Methods
*/
function mapper(xmlDoc) {
    xmlDoc = ensureXml(xmlDoc);

    var resource = {};

    // Common
    mapFields(commonMapping, xmlDoc, resource);
    mapKeywords(xmlDoc, resource);
    mapOnlineResources(xmlDoc, resource);

    // Service
    if (resource.type && resource.type === 'service') {
        mapFields(serviceMapping, xmlDoc, resource);
    }

    /*
    ** TODO
    ** Resource locator (distributionInfo)
    ** Unique resource identifier ? identificationInfo/citation/identifier ! Attention code/codeSpace => merdique
    ** Coupled resources for services
    ** Topic category
    ** Service type
    ** BBOX
    */

    return resource;
}


/*
** Exports
*/
module.exports = mapper;

@@ -1406,16 +1406,562 @@
    %7D%0A%7D%0A%0A
+function buildResponsibleParty(node) %7B%0A    var rp = %7B%7D;%0A    mapFields(responsiblePartyMapping, node, rp);%0A    return rp;%0A%7D%0A%0Afunction mapMetadataContacts(xmlDoc, dest) %7B%0A    var nodes = xmlDoc.find('.//gmd:contact', ns);%0A    if (nodes && nodes.length) %7B%0A        dest._contacts = _.map(nodes, buildResponsibleParty);%0A    %7D%0A%7D%0A%0Afunction mapContacts(xmlDoc, dest) %7B%0A    var nodes = xmlDoc.find('.//gmd:identificationInfo//gmd:pointOfContact', ns);%0A    if (nodes && nodes.length) %7B%0A        dest.contacts = _.map(nodes, buildResponsibleParty);%0A    %7D%0A%7D%0A%0A
 /*%0A** Ma
@@ -2793,16 +2793,780 @@
 me'%0A%7D;%0A%0A
+var responsiblePartyMapping = %7B%0A    './/gmd:organisationName': 'organizationName',%0A    './/gmd:individualName': 'individualName',%0A    './/gmd:positionName': 'positionName',%0A    './/gmd:contactInfo//gmd:phone//gmd:voice': 'phone',%0A    './/gmd:contactInfo//gmd:phone//gmd:facsimile': 'fax',%0A    './/gmd:contactInfo//gmd:address//gmd:electronicMailAddress': 'email',%0A    './/gmd:contactInfo//gmd:address//gmd:deliveryPoint': 'deliveryPoint',%0A    './/gmd:contactInfo//gmd:address//gmd:city': 'city',%0A    './/gmd:contactInfo//gmd:address//gmd:postalCode': 'postalCode',%0A    './/gmd:contactInfo//gmd:address//gmd:country': 'country',%0A    './/gmd:contactInfo//gmd:address//gmd:electronicMailAddress': 'email',%0A    './/gmd:role/gmd:CI_RoleCode/@codeListValue': 'role'%0A%7D;%0A%0A
 /*%0A** Me
@@ -3750,24 +3750,24 @@
  resource);%0A
-
     mapOnlin
@@ -3795,16 +3795,94 @@
 source);
+%0A    mapMetadataContacts(xmlDoc, resource);%0A    mapContacts(xmlDoc, resource);
 %0A%0A    //

Add mapping for contacts