function a_dom = exportMorphML(a_mesh, props)

% exportMorphML - Export mesh to MorphML XML format.
%
% Usage:
% a_dom = exportMorphML(a_mesh, props)
%
% Parameters:
%   a_mesh: A mesh_amira object.
%   props: A structure with any optional properties.
%		
% Returns:
%   a_dom: A Matlab DomNode object.
%
% Description:
%
% Example:
% >> a_mesh = mesh_amira('my_amira.am', 'Neuron 1')
% >> xmlwrite('neuron.xml', exportMorphML(a_mesh))
%
% See also: 
%
% $Id$
%
% Author: Cengiz Gunay <cgunay@emory.edu>, 2012/02/03

% Copyright (c) 2012 Cengiz Gunay <cengique@users.sf.net>.
% This work is licensed under the Academic Free License ("AFL")
% v. 3.0. To view a copy of this license, please look at the COPYING
% file distributed with this software or visit
% http://opensource.org/licenses/afl-3.0.php.

% make a hash table for origin lookups
% (no need for a map, so info is duplicated in values)
  origins = ...
      containers.Map(num2cell(uint32(a_mesh.origins)), num2cell(a_mesh.origins));
  
% Create a MorphML XML document
% $$$   <morphml xmlns="http://morphml.org/morphml/schema"     
% $$$      xmlns:meta="http://morphml.org/metadata/schema"
% $$$      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
% $$$      xsi:schemaLocation="http://morphml.org/morphml/schema http://www.neuroml.org/NeuroMLValidator/NeuroMLFiles/Schemata/v1.8.1/Level1/MorphML_v1.8.1.xsd"
% $$$      length_units="micrometer">
  
  a_dom = com.mathworks.xml.XMLUtils.createDocument('morphml');
  docRootNode = a_dom.getDocumentElement;
  docRootNode.setAttribute('xmlns', 'http://morphml.org/morphml/schema');
  docRootNode.setAttribute('xmlns:meta', 'http://morphml.org/metadata/schema');
  docRootNode.setAttribute('xmlns:xsi', 'http://www.w3.org/2001/XMLSchema-instance');
  docRootNode.setAttribute('xsi:schemaLocation', 'http://morphml.org/morphml/schema http://www.neuroml.org/NeuroMLValidator/NeuroMLFiles/Schemata/v1.8.1/Level1/MorphML_v1.8.1.xsd');
  docRootNode.setAttribute('length_units', 'micrometer');
  
  % Start a cell description
  cells = a_dom.createElement('cells');
  docRootNode.appendChild(cells);
  
  cell = a_dom.createElement('cell');
  cell.setAttribute('name', a_mesh.origFilename);
  cells.appendChild(cell);

  note = a_dom.createElement('meta:notes');
  cell.appendChild(note);
  note.appendChild(a_dom.createTextNode(a_mesh.id));
  
  % skip meta:properties for now? TODO: Put Amira info.
  
  % Add segments as connected structures
  segments = a_dom.createElement('segments');
  cell.appendChild(segments);

  % keep track of vertices that already exist to appear as "parent"
  parents = containers.Map('KeyType', 'uint32', 'ValueType', 'uint32');
  
  % make first element
  create_soma();

  % loop over Vertices and follow their Edges
  edge_num = 0;
  output_num = 0;
  for vertex_num = 1:a_mesh.nVertices
    for neighbor_num = 1:a_mesh.neighborCount(vertex_num)
      % a segment from vertex to its neighbor (convert to Matlab numbering)
      to_vertex = a_mesh.neighborList(edge_num + neighbor_num) + 1;
      
      % skip backwards edges; Amira seem to create two edges between each
      % vertex
      
      % this is too simplistic:
% $$$       if to_vertex <= vertex_num
% $$$         continue;
% $$$       end
      
      % skip only if it exists as a parent
      if parents.isKey(uint32(to_vertex - 1))
        continue;
      end

      output_num = output_num + 1;
      
      % create segment
      segment = a_dom.createElement('segment');
      segment.setAttribute('id', num2str(to_vertex - 1)); % name with target
      segment.setAttribute('parent', num2str(vertex_num - 1)); % parent as vertex
      segment.setAttribute('name', [ 'SegFromVertex' num2str(vertex_num - 1) 'to' ...
                          num2str(to_vertex - 1) ]);

      % two types of "cables": Regular (1) and Origins (0)
      if origins.isKey(uint32(vertex_num - 1))
        segment.setAttribute('cable', '0');
      else
        segment.setAttribute('cable', '1');
      end
      segments.appendChild(segment);
      
      % proximal only for first edge
      dist = a_dom.createElement('distal');
      segment.appendChild(dist);

      dist.setAttribute('x', num2str(a_mesh.vertices(to_vertex, 1)));
      dist.setAttribute('y', num2str(a_mesh.vertices(to_vertex, 2)));
      dist.setAttribute('z', num2str(a_mesh.vertices(to_vertex, 3)));
      dist.setAttribute('diameter', num2str(2*a_mesh.radii(to_vertex)));

      % add segment as reprsenting vertex as a parent
      parents(uint32(to_vertex - 1)) = uint32(vertex_num - 1);
    end
    edge_num = edge_num + a_mesh.neighborCount(vertex_num); 
  end

  disp(['Exported ' num2str(output_num) ' segments to file.']);
  
  % finally insert a "cables" section describing the different sections
  cables = a_dom.createElement('cables');
  cell.appendChild(cables);
  
  cable = a_dom.createElement('cable');
  cables.appendChild(cable);
  
  cable.setAttribute('id', '0');
  cable.setAttribute('name', 'Origin');
  cable.appendChild(a_dom.createElement('meta:group').appendChild(a_dom.createTextNode('origin_group')));

  cable = a_dom.createElement('cable');
  cables.appendChild(cable);
  
  cable.setAttribute('id', '1');
  cable.setAttribute('name', 'Other');
  cable.appendChild(a_dom.createElement('meta:group').appendChild(a_dom.createTextNode('other_group')));
 
% $$$   a_dom.appendChild(a_dom.createComment('this is a comment'));

  function create_soma
  % make first segment as a sphere containing first vertex
    segment = a_dom.createElement('segment');
    segments.appendChild(segment);
    
    segment.setAttribute('id', '0'); % name with target
    segment.setAttribute('name', [ 'First' ]);
    
    if origins.isKey(uint32(0))
      segment.setAttribute('cable', '0');
    else
      segment.setAttribute('cable', '1');
    end
    
    prox = a_dom.createElement('proximal');
    segment.appendChild(prox);
    
    % prox=dist coordinates for sphere
    prox.setAttribute('x', num2str(a_mesh.vertices(1, 1)));
    prox.setAttribute('y', num2str(a_mesh.vertices(1, 2)));
    prox.setAttribute('z', num2str(a_mesh.vertices(1, 3)));
    prox.setAttribute('diameter', num2str(2*a_mesh.radii(1)));
    
    dist = a_dom.createElement('distal');
    segment.appendChild(dist);

    dist.setAttribute('x', num2str(a_mesh.vertices(1, 1)));
    dist.setAttribute('y', num2str(a_mesh.vertices(1, 2)));
    dist.setAttribute('z', num2str(a_mesh.vertices(1, 3)));
    dist.setAttribute('diameter', num2str(2*a_mesh.radii(1)));
  
    % add segment as representing vertex as a parent
    parents(uint32(0)) = uint32(0);
  end
  
end
