function [ outfname ] = processLargeMAT_LRAUV( vehicle, searchterm, outmatfolder, varargin )

% This function extracts specific data fields (deignated in cell array
% varfields.mat) from large mat files located on smb://atlas.shore.mbari.org/LRAUV/.
% It interpolates variables to a fixed time grid and saves parameters of
% interest to separate mat file.
%
% INPUTS:
% vehicle: 'Tethys', 'Daphne', 'Makai'
% 
% searchterm:   string containing mission, log or file name (e.g., '20130920_20131007')
%               input searchterm=[] if no search term is desired (will process
%               all mat files for vehicle and year).
%
% outmatfolder: path for saving processed datasets
%               (e.g., [ '~/MABARI/LRAUV/matfiles/' ])
% 
% OPTIONS:
% 'All': answer yes to all user prompts
% 
% EXAMPLES:
% vehicle     = 'Tethys';
% searchterm  = '20130920_20131007';     % <- this is a mission folder name
% searchterm  = '201309121813_201309140344'; % <- this is a log folder name
% searchterm  = []; % <- no search term
%
% OUTPUT:
% outfname: cell arrey of new datasets paths
%
% Calls findmat_LRAUV.m and fixTimeseries.m
% Last modified Jan 02, 2015
% Ben Raanan
%--------------------------------------------------------------------------


% Check options
%--------------------------------------------------------------------------
if any(strcmpi(varargin,'All')) % skip user prompts 
    yes2all = true;
else
    yes2all = false;
end

% use user specified path to mat file
if any(strcmpi(varargin,'path')) 
    list = varargin{find(strcmpi(varargin,'path'))+1};
    [~,listf,ext] = fileparts(list{:});
    listf = {[listf ext]};
    findmat = false;
else
    findmat = true;
end


% Load .mat file names and paths
%--------------------------------------------------------------------------
if findmat
    [list,listf]  = findmat_LRAUV( vehicle, searchterm );
end

% c=load(list{:});

% load field list
%--------------------------------------------------------------------------
load('varfields.mat', 'varfields')

% to change var list edit varfields and save
% save('~/MATLAB/MBARI/LoadAndFix/ServerMatFiles/mat/varfields.mat', 'varfields', 'varfields_cmd')


% Extract specified varfields from .mat files and interp to fixed time-grid
%--------------------------------------------------------------------------
outfname = cell(size(list));
for k = 1:length(list)
    % index file
    fileIndex = k;
    
    % check if already exists in outmatfolder
    %----------------------------------------------------------------
    d = dir(outmatfolder);
    isub = [d(:).isdir];
    if ~any(~cellfun('isempty',regexp({d(~isub).name}, listf{fileIndex})))
        
        % prompt user if file size is over 250MB
        %------------------------------------------------------------
        if ~yes2all
            clear d
            d = dir(list{fileIndex});
            fsize = d.bytes/10^6;
            if fsize>=1000
                str='';
                prompt = [listf{fileIndex} ' file size is ' num2str(fsize,4) 'MB. Proceed? YES/NO [YES]: '];
                while ~strcmpi(str,'NO') && ~strcmpi(str,'YES')
                    str = input(prompt,'s');
                    if isempty(str)
                        str = 'YES';
                    end
                end
                if strcmpi(str,'NO')
                    warning([ listf{fileIndex} ' processing aborted...'])
                    continue
                end
            end
        end
        % gather info of mat file contents
        %------------------------------------------------------------
        varlist = whos('-file',list{fileIndex});
        varlistf = struct2cell(varlist); varlistf = varlistf(1,:)';
        
        
        % construct a variable index list for vars defiened in varfields
        %------------------------------------------------------------
        varInt = zeros(size(varfields));
        for c=1:length(varfields)
            if any(strcmp((varfields{c}),varlistf))
                
                varInt(c) = find(strcmp((varfields{c}),varlistf));
            else
                continue
            end
        end; clear c
        varInt(varInt==0)=[];
        
        
        % load to struct
        if ~isempty(varInt)
            display(['Processing ' list{fileIndex} '...'])
            vars=load(list{fileIndex},varlist(varInt).name);
        else
            continue
        end
        
        % extract cycle time-stamps and elevator servo offset angle
        %------------------------------------------------------------
        if isfield(vars,'SpeedControl')
            vars.VerticalControl.speedCmd = vars.SpeedControl.speedCmd;
            vars.VerticalControl.propOmegaAction = vars.SpeedControl.propOmegaAction;
        end
        
        if isfield(vars,'DropWeight')
            if isfield(vars.DropWeight,'dropWeightState')
                vars.VerticalControl.dropWeight = vars.DropWeight.dropWeightState;
            end
        end
        
        if isfield(vars.ElevatorServo,'offsetAngle')
            vars.ElevatorOffsetAngle = vars.ElevatorServo.offsetAngle;
        end
        
        if isfield(vars,'CycleStarter')
            vars.CycleStarter = vars.CycleStarter;
        end
        
        if isfield(vars,'ThrusterServo')
            vars.VerticalControl.ThrusterServo_current = vars.ThrusterServo.component_current;
            vars.VerticalControl.ThrusterServo_voltage = vars.ThrusterServo.component_voltage;
        end
        
        if isfield(vars,'BuoyancyServo')
            vars.VerticalControl.BuoyancyServo_current = vars.BuoyancyServo.component_current;
            vars.VerticalControl.BuoyancyServo_voltage = vars.BuoyancyServo.component_voltage;
        end
        
        
        % extract config variables of intrest
        Cfg.buoyancyNeutral      = vars.VerticalControl.buoyancyNeutral;
        Cfg.massDefault          = vars.VerticalControl.massDefault;
        Cfg.massPositionLimitAft = vars.VerticalControl.massPositionLimitAft;
        Cfg.massPositionLimitFwd = vars.VerticalControl.massPositionLimitFwd;
        
        vars = rmfield(vars,{'ElevatorServo','CycleStarter','SpeedControl','ThrusterServo','DropWeight'});
        
        
        % get parameters on same time grid:
        %------------------------------------------------------------
        tRes = 1/2.5; % sec, new time grid sampling rate (for interp)
        % tRes = 1/10; % sec, new time grid sampling rate (for interp)
        % create new time grid
        t1 = round2(min(vars.depth.time),tRes/(3600*24)); % first time
        t2 = max(vars.depth.time); % last time
        time=t1:tRes/(3600*24):t2; % new 0.4 sec grid
        
        % cut time vector for reshape bin avging (~5 sec bins)
        %{
        int = round(5/tRes); rsInd=0;
        while mod(length(time),int)~=0 && rsInd<200
            rsInd=rsInd+1;
            time(end) = [];
        end;
        %}
        
        % prompt user if log time span is under 30 minutes
        if ~yes2all
            tspan=24*60*(time(end)-time(1));
            if tspan<30
                str='';
                prompt = [listf{fileIndex} ': log time span is only ' num2str(tspan,3) ' min long. Proceed? YES/NO [YES]: '];
                while ~strcmpi(str,'NO') && ~strcmpi(str,'YES')
                    str = input(prompt,'s');
                    if isempty(str)
                        str = 'YES';
                    end
                end
                if strcmpi(str,'NO')
                    error([ listf{fileIndex} ' process aborted.'])
                    continue
                end
            end
        end
        
        % list new variable names
        fixVars = vars; % make copy
        fields = fieldnames(fixVars);
        
        % in some datasets time grids vectors are not strictly monotonic increasing
        % this loop fixes time vectoer and intrepolates data to a new time grid
        % with sampling intervals specifies by tRes
        for c = 1:numel(fields)
            
            % case VerticalControl struct (to get Cmd info)
            if strcmp('VerticalControl', fields{c})
                
                interpVars.Cmd = ineterpCmd(fixVars.(fields{c}), time);
                
            elseif strcmp('Cfg', fields{c}) % case Cfg struct (to get config info)
                
                interpVars.Cfg = ineterpCfg(fixVars.(fields{c}), time);
                
            else
                temp = fixVars.(fields{c}); % extract
                % fix time and interpolate to new time grid
                if length(temp.value)>1
                    [temp.time, temp.value] = fixTimeseries(temp.time, temp.value);
                    interpVars.(fields{c}) = interp1(temp.time, temp.value, time,'previous');
                    
                else
                    warning(['Log ' listf{fileIndex} ': ' fields{c} ' record missing!'])
                end
            end
        end; clear c temp
        
        vars.Cfg = Cfg;
        
        % save
        %------------------------------------------------------------
        %
        outfname{k} = [ outmatfolder 'LRAUV_SIM_' listf{fileIndex} ];
        save(outfname{k},'vars','fixVars','interpVars','time');
        % uisave({'vars','fixVars','interpVars','time'},outfname{k});
        clear vars fixVars interpVars time
        %}
    else
        outfname{k} = [outmatfolder 'LRAUV_SIM_' listf{fileIndex} ];
        display(['Found ' listf{fileIndex} ' in ' outmatfolder '.'])
    end
end
end


% ineterpCmd: extract and interp commanded variables
%--------------------------------------------------------------------------
function [Cmd] = ineterpCmd(VerticalControl, newTimeGrid)

load('varfields.mat', 'varfields_cmd')
%{
cmdf = {'elevatorAngleCmd','massPositionCmd','depthCmd','depthRateCmd',...
    'pitchCmd','pitchRateCmd','buoyancyCmd','speedCmd','elevatorAngleCmd',...
    'verticalMode','dropWeight','ThrusterServo_current','ThrusterServo_voltage',...
    'elevatorAngleAction','massPositionAction','buoyancyAction','propOmegaAction'};
%}

for k=1:numel(varfields_cmd)
    if isfield(VerticalControl,varfields_cmd{k})
        temp = VerticalControl.(varfields_cmd{k}); % extract fixVars.
        temp.value = double(temp.value);  % prep data class for interp
        
        if length(temp.value)>1
            % fix time and interpolate to new time grid
            [temp.time, temp.value] = fixTimeseries(temp.time, temp.value);
            Cmd.(varfields_cmd{k}) = interp1(temp.time, temp.value, newTimeGrid,'previous'); % <--!!!
        else
            warning(['VerticalControl.' varfields_cmd{k} ': Record missing!'])
        end
    else
        warning(['VerticalControl.' varfields_cmd{k} ': Record missing!'])
    end
end

end


% ineterpCfg: extract and interp config variables
%--------------------------------------------------------------------------
function [Cfg] = ineterpCfg(Cfg, newTimeGrid)

cfgnames = fieldnames(Cfg);

for k=1:numel(cfgnames)
    
    temp = Cfg.(cfgnames{k}); % extract fixVars.
    temp.value = double(temp.value);  % assert type double for interp
    
    if length(temp.value)>1
        % fix time and interpolate to new time grid
        [temp.time, temp.value] = fixTimeseries(temp.time, temp.value);
        
        Cfg.(cfgnames{k}) = interp1(temp.time, temp.value, newTimeGrid,'previous','extrap'); % <--!!!
        
    elseif length(temp.value)==1
        Cfg.(cfgnames{k}) = repmat(temp.value, size(newTimeGrid));
        
    elseif numel(temp.value)==0
        Cfg.(cfgnames{k}) = NaN(size(newTimeGrid));
        
    else
        warning(['Cfg.' cfgnames{k} ': Record empty!'])
    end
end

end
