function [m,ok] = loadmesh_anyfile( m, filename, staticdata, interactive )
%m = loadmesh_anyfile( m, filename, staticdata, interactive )
%   Load a leaf from a file.
%   The expected format depends on the extension of the filename:
%       .OBJ    Contains only nodes and triangles, in OBJ format.  All
%               other properties of the mesh will be set to their default
%               values.
%       .MAT    The leaf is contained in the file as a Matlab object called
%               m.  If staticdata is supplied, data from these overwrites
%               data loaded from filename.  If staticdata is a string, it
%               will be assumed to be a MAT-file containing the static
%               data.
%       .M      The file contains Matlab commands to create or modify a
%               leaf.  These commands will be executed.
%   All of these formats can be generated by leaf_save.
%   In the case of .OBJ and .MAT files, the existing leaf will be
%   discarded.  A .M file will discard the current leaf only if it contains
%   a command to create a new leaf.

    if nargin < 4
        interactive = false;
    end
    objext = '.obj';
    matext = '.mat';
    mfileext = '.m';
    
    ok = true;
    
    [modeldir,modelname,modelext] = fileparts( filename );
    [projectdir,modeldirname] = fileparts( modeldir );
    if ~strcmp( modeldirname, modelname )
    %   warning( ['GFtbox:' mfilename()], ...
    %       '%s: model directory %s and model file %s%s have different names.\n', ...
    %       mfilename(), modeldirname, modelname, modelext );
    end
    modelnamewithext = [modelname,modelext];
    fullname = fullfile( modeldir, modelnamewithext );

    if isempty(modeldir)
        filesource = modelnamewithext;
    else
        filesource = [ modelnamewithext ' in ' modeldir ];
    end
    
    switch modelext
        case objext
            fprintf( 1, '%s: Loading OBJ file %s.\n', ...
                mfilename(), filesource );
            m = readmesh( modeldir, modelnamewithext );
            if isempty(m)
                ok = false;
            else
                m.globalProps.projectdir = projectdir;
                m.globalProps.modelname = modeldirname;
                m.scripthistory = {};
                m = upgrademesh( m );
            end
        case matext
            fprintf( 1, '%s: Loading MAT file %s.\n', ...
                mfilename(), filesource );
            z = [];
            if ~exist( fullname, 'file' )
                GFtboxAlert( interactive, 'No file %s.', fullname )
                ok = false;
                return;
            else
                try
                    z = load( fullname );
                catch
                    GFtboxAlert( interactive, 'Cannot load %s.', fullname )
                    ok = false;
                    return;
                end
            end
            if ~isfield(z,'m') || isempty(z.m)
                GFtboxAlert( interactive, ...
                    'Project invalid: MAT file %s does not contain a mesh object called m.', ...
                    mfilename(), filesource );
                ok = false;
                return;
            end
            m = z.m;
            clear z;
            m.globalProps.projectdir = projectdir;
            m = makeModelNamesConsistent( m, fullfile( projectdir, modeldirname ) );
            m = upgrademesh( m );
            m.plotdata = struct([]);
            if (nargin >= 3) && ~isempty(staticdata)
                if isstruct( staticdata )
                    m = addStaticData( m, staticdata );
                elseif exist( staticdata, 'file' )
                    try
                        fprintf( 1, '%s: Loading static MAT file %s.\n', ...
                            mfilename(), staticdata );
                        mstatic = load( staticdata );
                        m = addStaticData( m, mstatic );
                    catch
                        le = lasterror();
                        warning(le.identifier, '%s', le.message);
                        GFtboxAlert( interactive, 'Warning: Could not read static file %s.', ...
                            mfilename, staticdata );
                    end
                else
                    fprintf( 1, '%s: Static file not found: %s\n', ...
                        mfilename, staticdata );
                end
            end
            % Some data are not valid when loaded from a file and must be
            % reconstituted or deleted.
            
            % The raw plot data is likely to be obsolete when a mesh is
            % loaded.
            m.plotdefaults = deleteRawPlotData( m.plotdefaults );
            % The projectdir and modelname are defined by where we loaded
            % the file from.
            m.globalProps.projectdir = projectdir;
            m.globalProps.modelname = modeldirname;
            m.scripthistory = {};
            m.globalProps.allowsave = 1;
            % Movie and handle data are necessarily invalid for a newly
            % loaded mesh.
            m.globalProps.mov = [];
            m.globalProps.makemovie = 0;
            m.globalProps.moviefile = '';
            m.globalProps.allowsave = 1;
            m.pictures = [];
            m.plothandles = struct();
        case mfileext
            fprintf( 1, '%s: Executing commands from %s.\n', ...
                mfilename(), filesource );
            if ~isempty(modeldir)
                prevdir = cd(modeldir);
            end
            savedhistory = m.scripthistory;
            m.scripthistory = {};
            m = docommands( m, modelnamewithext, 'nostop' );
            m.scripthistory = savedhistory;
            if ~isempty(modeldir)
                cd(prevdir);
            end
        otherwise
            GFtboxAlert( interactive, 'Unknown file format: %s.  Leaf not loaded.\n', ...
                filename );
    end
end

function po = deleteRawPlotData( po )
    rawdatafields = { 'pervertex', ...
        'perelement', ...
        'tensor', ...
        'morphogen', ...
        'outputquantity', ...
        'blank', ...
        'outputaxes', ...
        'perelementaxes', ...
        'perelementcomponents', ...
        'axesquantity', ...
        'axesdrawn', ...
        'defaultmultiplo' };
    for i=1:length(rawdatafields)
        fn = rawdatafields{i};
        po.(fn) = [];
        po.([fn 'A']) = [];
        po.([fn 'B']) = [];
    end
end

