% HIST2DOT converts a history object to a 'DOT' file suitable for processing with graphviz
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% DESCRIPTION: HIST2DOT converts a history object to a 'DOT' file suitable for
%              processing with graphviz (www.graphviz.org).
%
% CALL:        hist2dot(h, 'foo.dot');
%
% INPUT:       h       - history object
%              foo.dot - file name to view the graphic with the programm
%                        graphviz
%
% VERSION:     $Id: hist2dot.m,v 1.16 2011/02/18 16:48:52 ingo Exp $
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

function varargout = hist2dot(varargin)
  
  %%% Set inputs
  h        = varargin{1};
  filename = varargin{2};
  pl = [];
  if nargin > 2
    if isa(varargin{3}, 'plist')
      pl = varargin{3};
    end
  end
  pl = combine(pl, getDefaultPlist);
  stop_option = find(pl, 'stop_option');
  
  %%% Write .dot file
  
  fd = fopen(filename, 'w+');
  
  %%% write header
  fprintf(fd, 'digraph G \n{\n');
  
  old = 0;
  
  if old
    
    [n,a, nodes] = getNodes(h, stop_option);
    nodesWritten = {};
    %%% Write block set
    fprintf(fd, 'end [label="END"];\n');
    for j=1:length(nodes)
      node = nodes(j);
      
      %     tag =
      
      if ~containsNodeArray(nodesWritten, node)
        
        % wrap label
        % Do some command substitution
        fcn = node.names;
        shape = 'rectangle';
        fsize  = 12;
        extras  = '';
        
        wstr = utils.prog.wrapstring([fcn char(node.params)], 25);
        ss = '';
        for s=wstr
          ss = [ss '\n' char(s)];
        end
        ss = ss(3:end);
        fprintf(fd, '%s [%s fontsize=%d shape=%s label="%s"];\n', nodeName(node), extras, fsize, shape, ss);
        nodesWritten = [nodesWritten {node.h.UUID}];
      end
    end
    
    %%% Write node list
    fprintf(fd, '\n');
    fprintf(fd, '\n');
    
    nodesConnected = [];
    for j=length(nodes):-1:1
      %   disp('----------------')
      node = nodes(j);
      %     node.h
      %     if ~arrayContainsElement(nodesConnected, node.pn)
      if node.pn > 0
        dst  = nodes(node.pn);
        fprintf(fd, '%s -> %s; # %d\n', nodeName(node), nodeName(dst), dst.pn);
        %       nodesConnected = [nodesConnected {node.h.UUID}];
      else
        fprintf(fd, '%s -> end;\n', nodeName(node));
      end
      nodesConnected = [nodesConnected node.pn];
      %     end
      %   disp('----------------')
    end
  else
    
    % Get unique history nodes
    [hists, links] = getHists(h, [], []);
    
    % Now write history blocks
    fprintf(fd, 'end [label="END"];\n');
    for ll=1:numel(hists)
      hist = hists(ll);
      
      % wrap label
      % Do some command substitution
      fcn = hist.methodInfo.mname;
      shape = 'rectangle';
      fsize  = 12;
      extras  = '';
      
      wstr = utils.prog.wrapstring([fcn char(hist.plistUsed)], 25);
      ss = '';
      for s=wstr
        ss = [ss '\n' char(s)];
      end
      ss = ss(3:end);
      fprintf(fd, '%s [%s fontsize=%d shape=%s label="%s"];\n', ...
        nodeName(hist), ...
        extras, fsize, shape, ss);
      
    end
    
    fprintf(fd, '\n');
    fprintf(fd, '\n');
    
    % Now write links
    for kk=1:numel(links)
      fprintf(fd, '%s', links{kk});
    end
    
    fprintf(fd, '%s -> end;\n', nodeName(h));
  end
  
  %%% close
  fprintf(fd, '}\n');
  
  %%% Close
  fclose(fd);
  
end


function [hists, links] = getHists(obj, links, hists)
  
  if isa(obj, 'history') && ~arrayContainsObjects(hists, obj)
    pl = obj.plistUsed;
    
    for kk=1:pl.nparams
      
      val = pl.params(kk).getVal();
      if isa(val, 'history')
        
        for jj=1:numel(val)
          if ~arrayContainsObjects(hists, val(jj))
            [hists, links] = getHists(val(jj), links, hists);
          end
          
          % write link
          l = sprintf('%s -> %s;\n', nodeName(val(jj)), nodeName(obj));
          links = [links {l}];
        end
        
        
        
      end
      
    end
    
    hists = [hists obj];
  end
  
  
  if isprop(obj, 'hist')
    if ~arrayContainsObjects(hists, obj.hist)
      [hists, links] = getHists(obj.hist, links, hists);
    end
  end
  
  if isprop(obj, 'inhists')
    for kk=1:numel(obj.inhists)
      if ~arrayContainsObjects(hists, obj.inhists(kk))
        [hists, links] = getHists(obj.inhists(kk), links, hists);
      end
      
      % write link
      l = sprintf('%s -> %s;\n', nodeName(obj.inhists(kk)), nodeName(obj));
      links = [links {l}];
    end
  end
  
  
end

function res = arrayContainsObjects(array, obj)
  res = false;
  for kk=1:numel(array)
    if strcmp(array(kk).UUID, obj.UUID)
      res = true;
      break;
    end
  end
end

function nn = nodeName(node)
  
  nn = ['node_' strrep(node.UUID, '-', '_')];
  
  
  
end

function res = arrayContainsElement(array, element)
  
  res = any(array == element);
  
%   res = false;
%   for kk=1:numel(array)
%     if strcmp(array(kk).UUID, element.UUID)
%       res = true;
%       break;
%     end
%   end
  
end

function res = containsNodeArray(nodes, node)
  
  x = @(c)(strcmp(c, node.h.UUID));
  res = any(cellfun(x, nodes));
  
%   res = cellfun('strcmp', nodes, node);
  
%   res = false;
%   for kk=1:numel(nodes)
%     if strcmp(nodes{kk}, node.h.UUID)
%       res = true;
%       break;
%     end
%   end
end

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                               Local Functions                               %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% FUNCTION:    getDefaultPlist
%
% DESCRIPTION: Get Default Plist
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

function plo = getDefaultPlist()
  plo = plist('stop_option', 'full');
end

