function cdef = editCrystalDefinition(cdef)
% text based tool to create a crystal definition
%
% Syntax: editCrystalDefinition
% 
% editCrystalDefinition guides you in creating the data to define a
%   crystal: symmetry, lattice parameters and Miller indices. From the
%   tool, you can print these information, view the crystal with all facets
%   and write it into the database folder.
%
% The above syntax starts with an empty crystal definition structure while
%   using editCrystalDefinition(cdef) starts with the structure in cdef or
%   when cdef is a string, it loads the case from the database (no generic
%   parameter is supported).
% cdef = editCrystalDefinition also returns the data structure to the
%   workspace. It has the fields:
%
% cdef = editCrystalDefinition(cdef) does return the defined crystal in a
% structure:
%    .sym           symmetry information
%    .sym.defined   just a number indexing the symmetry class
%    .sym.system    crystal family, like cubic or tetragonal
%    .lat           lattice parameters
%      .unit_angle     unit for angles {degree, radian}
%      .unit_length    unit for length scales {aengstroem}
%      .a / .b / .c    length of crystallographic unit vectors
%      .alpha / .beta / .gamma    angles between crystallographic axes
%    .millerDefined    explicitely defined forms of the crystal
%    .millerComplete   all facets of the crystal generated from
%                       millerDefined by given symmetry
%    .A             cartesian unit vectors of facets in an m by 3
%                       matrix. Please refere to H-representation in
%                       Elk-toolbox.
%    .groupMappingMatrix - group mapping from millerDefined to vectors
%                       in A.
%    .mapMillerToReal - coordinate transformation from crystal system to
%                   Cartesian system
%    .mapRealToMiller - the reverse transformation from above
%
% See also: obtainCrystal, viewCrystal, writeCdefToDatabase
 
% The elk-library: convex geometry applied to crystallization modeling.
%   Copyright (C) 2013 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/>.

%% Initialize
% handle input for crystal definition
if ~exist('cdef', 'var')
    cdef = struct();
end

if ischar(cdef)
    cdef = obtainCrystal(cdef);
elseif ~isstruct(cdef)
    error('elk:crystal:wrongInput', ['Input must be a crystal definition ' ...
        'structure or a string to be called with obtainCrystal']);
end


% load pointgroup informations
P = executeExternBorchertFunction('pointgroup');
P = reshape(struct2cell(P), [9,32]);
% 1-Schonflies Notation, 2-Hermann-Mauguin Notation, 3-Symmetry Elements,
%   4-Laue Class, 5-Crystal Family, 6-Number, 7-Trivialname, 8-, 9-Minv
%   replace crystal family names

% translate abbrevations in CF to full names and numbers to strings
for i = 1:size(P, 2)
    P{5, i} = abbreviateCrystalSystem(P{5, i});
    P{6, i} = num2str(P{6, i});
end

% set some control value
control = -1;

while control ~= 0
    %% Main Program Loop
    clc
    disp(' /----------------------------------\');
    disp('|   Interactive Crystal Definition   |');
    disp(' \----------------------------------/');
    disp(' ');
    disp('   During this setup, you will specify crystal symmetry, lattice ');
    disp('   parameters and Miller indices of faces. From these informations');
    disp('   the facet normals in cartesian space are calculated.');
    disp(' ');
    disp('Main Menu');
    list = {};
    % Symmetry
    if isfield(cdef, 'sym') && isfield(cdef.sym, 'defined')
        list{1} = 'Delete Crystal Symmetry';
    elseif isfield(cdef, 'sym') && (isfield(cdef.sym, 'system') || isfield(cdef.sym, 'LC'))
        list{1} = 'Extend Crystal Symmetry Information';
    else
        list{1} = 'Define Crystal Symmetry';
    end
    % Lattice Parameters
    if isfield(cdef, 'lat')
        list{2} = 'Delete Lattice Parameters';
    else
        list{2} = 'Define Lattice Parameters';
    end
    clist = [1 2];
    % Miller facets
    if isfield(cdef, 'sym') && isfield(cdef.sym, 'defined')
        list{end+1} = 'Edit Miller Indices';
        clist(end+1) = 3;
    end
    % display informations
    list{end+1} = 'Display Current Informations';
    clist(end+1) = 4;
    % show crystal
    if isfield(cdef, 'sym') && isfield(cdef.sym, 'defined') && isfield(cdef, 'lat')
        list{end+1} = 'Show Image of Crystal';
        clist(end+1) = 5;
    end
    % save crystal
    list{end+1} = 'Save to database and exit';
    clist(end+1) = 6;

    
    control = selectFromList(list, 'Exit');
    if control ~= 0
        control = clist(control);
    end
    
    switch control
        %% Symmetry handling
        case 1
            if isfield(cdef, 'sym') && isfield(cdef.sym, 'defined')
                % delete symmetry information
                cdef = rmfield(cdef, 'sym');
                % delete lattice informations
                if isfield(cdef, 'lat');
                    cdef = rmfield(cdef, 'lat');
                end
                % delete defined miller indices
                if isfield(cdef, 'millerDefined');
                    cdef = rmfield(cdef, 'millerDefined');
                end
                disp('..crystal definition deleted');
            elseif isfield(cdef, 'sym') && isfield(cdef.sym, 'system')
                % set symmetry (family already defined)...
                % prompt for selection of notation
                disp(' ');
                disp('Please choose a notation');
                list = {'Schonflies Notation', 'Hermann-Mauguin Notation',...
                        'Trivialname (German)', 'Number'};
                sel = selectFromList(list, 'Back');
                % back to main menu, if desired
                if sel == 0,control = -1;continue;end;
                % translate selcetion into proper row of P (space group
                % informations)
                list = [1, 2, 7, 6];
                sel = list(sel);
                % filter for valid elements of family
                sublistindices = [];
                for i = 1:size(P, 2)
                    if strcmp(P(5, i), cdef.sym.system)
                        sublistindices(end+1) = i;
                    end
                end
                % prompt for entering crystal family
                disp(' ');
                disp('Please specify the symmetry group');
                list = P(sel, sublistindices);
                sel = selectFromList(list, 'Back')
                % back to main menu, if desired
                if sel == 0,control = -1;continue;end;
                % translate to number of crystal definition
                cdef.sym.defined = sublistindices(sel);
            else
                % Select input type
                disp(' ');
                disp('Please choose a notation');
                list = {'Schonflies Notation', 'Hermann-Mauguin Notation',...
                        'Trivialname (German)', 'Number', ...
                        'Crystal Family'};
                sel = selectFromList(list, 'Back');
                % back to main menu, if desired
                if sel == 0,control = -1;continue;end;
                % translate to coloumn in P (pointgroups)
                list = [1, 2, 7, 6, 5];
                sel = list(sel);
                list = P(sel,:);
                % filter for unique entries, if crystal family was choosen
                if sel == 4 || sel == 5
                    list = unique(list);
                end
                % prompt for user input
                disp(' ');
                disp('Please specify the symmetry group');
                selt = selectFromList(list, 'Back');
                % back to main menu, if desired
                if selt == 0,control = -1;continue;end;
                % set symmetry informations
                if sel == 1 || sel == 2 || sel == 7 || sel == 6
                    cdef.sym.defined = selt;
                    cdef.sym.system = P{5, selt};
                elseif sel == 5
                    cdef.sym.system = list{selt};
                end
            end
        %% Lattice Parameters
        case 2
            if isfield(cdef, 'lat')
                % delete lattice informations
                cdef = rmfield(cdef, 'lat');
                disp('..lattice parameters deleted');
            else
                % create lattice informations
                [latspec cdef] = printLatticeSummary(cdef);
                disp(' ');
                disp('Please specify missing lattice parameters (lengths in aengstroem, angles in degree)');
                cdef.lat.unit_length = 'angstrom';
                cdef.lat.unit_angle = 'degree';
                cdef.lat.a = input('  a = ');
                if ~strcmp(latspec{2}, 'a')
                    cdef.lat.b = input('  b = ');
                else
                    cdef.lat.b = cdef.lat.a;
                end
                if ~strcmp(latspec{3}, 'a')
                    cdef.lat.c = input('  c = ');
                else
                    cdef.lat.c = cdef.lat.a;
                end
                if ~isfield(cdef.lat, 'alpha')
                    cdef.lat.alpha = input('  alpha = ');
                end
                if ~isfield(cdef.lat, 'beta')
                    cdef.lat.beta = input('  beta = ');
                end
                if ~isfield(cdef.lat, 'gamma')
                    cdef.lat.gamma = input('  gamma = ');
                end
            end
        %% Defining Faces
        case 3
            cdef = editMiller(cdef, P);

        %% summary
        case 4
            disp(' ');
            printSymmetrySummary(cdef, P);
            
            disp(' ');
            printLatticeSummary(cdef);
            
            disp(' ');
            printMillerSummary(cdef, P);
            pause
        
        %% show crystal
        case 5
            try
                figure
                cdef_tmp = extendCdef(cdef);
                viewCrystal(cdef_tmp);
            catch thisError
                warning(thisError.message)
                warning('Could not display crystal shape');
            end           
            pause
        case 6
            % request name
            disp(' ')
            fileName = input('File name (e.g. my_crystal): ', 's');
            
            disp(' ')
            disp('Proceed with file operation?');
            list = {['Save as elk' filesep 'crystal' ...
                    filesep 'database' filesep fileName '.m']};
            sel = selectFromList(list, 'Do not safe file.');
            if sel==1
                writeCdefToDatabase(fileName, cdef);
                control = 0;
            end
        otherwise
            if control ~= 0
                disp('Choice was invalid');
            end
    end
end

% exitting program, try to give cartesian, if description is complete
if nargout == 1;
    try
        cdef = extendCdef(cdef);
    end
else
    clear cdef
end


end



