function patchHandleVector = viewCrystal(cdef, h, varargin)
% plot a crystal definition
%
% Syntax: viewCrystal(cdef)
%
% In the simplest form, the crystal is displayed with all facets being
%   present. The facets are colored according to their face groups. The plot also contains
%   a legend that annotates the facet colors. The required fields of the
%   struct cdef are: A and groupMappingMatrix (see obtainCrystal).
%
% h = viewCrystal returns the patch handles of the plotted crystal.
%
% viewCrystal(cdef, h) or viewCrystal(cdef, hC) uses the given h- or
%   hC-vector to plot the crystal.
%
% viewCrystal(.., 'optionName', optionValue) accepts a list of options to
%   adjust the behavior of this function:
%     colorbar - switches the colorbar legend on (1) and off (0). 
%                Default: 1
%     colormap - is either a string for the selected colormap or a matrix 
%                with predefined colors (see 'doc colormap'). Default:
%                'jet'
%     option - an option struct that is handed to viewPolytope (see
%              viewPolytop for details. Default: []
%     zerotol - zerotol is used to identify values that are close to zero 
%               by zero. Default: elkZerotol
%
% See also: obtainCrystal

% The elk-library: convex geometry applied to crystallization modeling.
%   Copyright (C) 2012 Alexander Reinhold
%
% This program is free software: you can redistribute it and/or modify it 
%   under the terms of the GNU General Public License as published by the 
%   Free Software Foundation, either version 3 of the License, or (at your 
%   option) any later version.
%
% This program is distributed in the hope that it will be useful, but 
%   WITHOUT ANY WARRANTY; without even the implied warranty of 
%   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU 
%   General Public License for more details.
%
% You should have received a copy of the GNU General Public License along 
%   with this program.  If not, see <http://www.gnu.org/licenses/>.

%% Input handling
if ~exist('h', 'var') || isempty(h)
    h = ones([size(cdef.A, 1), 1]);
end
if size(h,1) == 1, h = h';end
if length(h) == size(cdef.A, 1)
    % everything OK
elseif length(h) == size(cdef.groupMappingMatrix, 2)
    h = cdef.groupMappingMatrix * h;
else
    error('elk:crystal:wrongInput', ...
          'The input vector must either be an h- or an hC-vector');
end
nGroup = size(cdef.groupMappingMatrix, 2);

%% Options handling
[colorMap, f_colorbar, plotOptionStruct, zerotol, millerStringOption] = ...
    mapOption(varargin, ...
    'colormap', 'jet', ...
    'colorbar', 1, ...
    'option', struct([]), ...
    'zerotol', elkZerotol, ...
    'millerStringOption', {'{', 1});

%% plot crystal
hrep.A = cdef.A;
hrep.h = h;
patchHandleVector = viewPolytope(hrep, 'option', plotOptionStruct);

%% find facet numbers
patchIsFacet = zeros(1, length(patchHandleVector));
for iPatch = 1:length(patchHandleVector)
    % m vertices in an m times 3 matrix.
    vertices = [get(patchHandleVector(iPatch), 'XData'), ...
                get(patchHandleVector(iPatch), 'YData'), ...
                get(patchHandleVector(iPatch), 'ZData')]';
    filter = ones([size(cdef.A, 1), 1]);
    for i_vertex = 1:size(vertices, 2)
        filter = filter & isZero(cdef.A*vertices(:,i_vertex) - h, zerotol);
    end
    if sum(filter) == 1
        patchIsFacet(iPatch) = find(filter);
    else
        %error('facet of patch can not be identified: either not unique or not existing');
    end
end

%% annotation handling 
% switch annotation
%     case 'single'
%         for i_patch = 1:length(patch_facet)
%             if patch_facet(i_patch)==0, ann_str{i_patch} = '';continue;end;
%             ann_str{i_patch} = '(';
%             for j = 1:3
%                 ann_str{i_patch} = [ann_str{i_patch} num2str(cdef.mil_complete(patch_facet(i_patch), j))];
%                 if j < 3,ann_str{i_patch} = [ann_str{i_patch} ','];end;
%             end
%             ann_str{i_patch} = [ann_str{i_patch} ')'];
%         end
%     case 'groups'
%         for i_patch = 1:length(patch_facet)
%             if patch_facet(i_patch)==0, ann_str{i_patch} = '';continue;end;
%             group = find(cdef.groupMappingMatrix(patch_facet(i_patch), :));
%             ann_str{i_patch} = '\{';
%             for j = 1:3
%                 ann_str{i_patch} = [ann_str{i_patch} num2str(cdef.mil_defined(group, j))];
%                 if j < 3,ann_str{i_patch} = [ann_str{i_patch} ','];end;
%             end
%             ann_str{i_patch} = [ann_str{i_patch} '\}'];
%         end
%     case iscell(annotation)
%         switch length(annotation)
%             case size(G, 1)
%             case size(G, 2)
%             otherwise
%                 error('with strings given in annotation, the number of labels should match the number of facets or the number of facet groups');
%         end
%     otherwise
%         for i_patch = 1:length(patch_facet)
%             ann_str{i_patch} = '';
%         end
% end
% 
% % make annotation
% for i_patch = 1:length(patch_facet)
%     if patch_facet(i_patch)==0,continue;end;
%     %X = cdef.A(patch_facet(i_patch), :) * h(patch_facet(i_patch)) * 1.1;
%     vertices = [get(h_patches(i_patch), 'XData'), ...
%                 get(h_patches(i_patch), 'YData'), ...
%                 get(h_patches(i_patch), 'ZData')]';
%     X = mean(vertices, 2)' + cdef.A(patch_facet(i_patch), :) * max(...
%                 [get(gca, 'XLim'), get(gca, 'YLim'), get(gca, 'ZLim')]...
%                 ) / 10000;
%     h_tmp = text(X(1), X(2), X(3), ann_str{i_patch});
% end

%% apply colors
set(gca, 'Color', 'none');

% assign color-data to patches
for iPatch = 1:length(patchIsFacet)
    if patchIsFacet(iPatch)==0
        group = size(cdef.groupMappingMatrix, 2) + 1;
        set(patchHandleVector(iPatch), 'linestyle', 'none');
    else
        group = find(cdef.groupMappingMatrix(patchIsFacet(iPatch), :));
    end
    set(patchHandleVector(iPatch), 'CData', nGroup - group + 1, 'FaceColor', 'flat', ...
        'CDataMapping', 'direct');
end

% set limits of c-axis
set(gca, 'CLim', [0.5, size(cdef.groupMappingMatrix, 2) + 0.5]);

% determine colormap
if ischar(colorMap)
    eval(['colorMap = colormap(' colorMap '(size(cdef.groupMappingMatrix, 2)));']);
end
colorMap = colorMap(end:-1:1, :);

% apply colormap
colormap(colorMap);

% draw colorbar
if f_colorbar
    handleColorBar = colorbar;
    % label colorbar
    for j = 1:size(cdef.groupMappingMatrix, 2)
        if length(millerStringOption) == 2
        labelColorBar{nGroup - j + 1} = convertMillerToString(...
            cdef.millerDefined(j,:), millerStringOption{1}, millerStringOption{2});
        elseif length(millerStringOption) == 1 && ~iscell(millerStringOption{1})
        labelColorBar{nGroup - j + 1} = millerStringOption{1};
        elseif length(millerStringOption) == 1 && iscell(millerStringOption{1})
        labelColorBar{nGroup - j + 1} = millerStringOption{1}{j};
        end
    end
    set(handleColorBar, 'YTick', 1:size(cdef.groupMappingMatrix, 2), 'YTickLabel', labelColorBar);
end
       
if nargout == 0
    clear patchHandleVector
end