function [corrHud] = CheckHud( inputHud, varargin )
% ----------------------------------------------------------
% [corrHud] = CheckHud( inputHud )
% ----------------------------------------------------------
% SAMPLE SYNTAX
%
% [corrHud] = CheckHud( inputHud )
%
% DESCRIPTION
% ==========================================================
% Checks the input hud struct for potential and known issues
% and returns a 'corrected' hud struct
%
% INPUT PARAMETERS
% ==========================================================
%    inputHud: Input hud struct that needs to be checked
%
% OPTIONAL VARARGIN PARAMETERS
% ==========================================================
%    'trahud': boolean to indicate that the function is 
%              called by ReadFile2TraHud.m
%
% OUTPUT
% ==========================================================
%     corrHud:  [1x1]  [struct] Struct holding three fields:
%
%                 .h    [cx1]  [cell] Data headers
%                 .u    [cx1]  [cell] Data unit
%                 .d    [nxc]  [dbl]  Data matrix
%
% ==========================================================
% COPYRIGHT © Trimble Terrasat GmbH
% ==========================================================

%% Handle the optional input arguments

% Initialize the input parser
p = inputParser;

% check optional 'name-value' argument colorfixtype
defaultCheckTraHud = false;
validateCheckTraHud = @(x)validateattributes(x,{'logical'},{'nonempty'});
addParameter(p,'trahud',defaultCheckTraHud,validateCheckTraHud);

% Parse the input arguments
parse(p,varargin{:});

%% Explicit Errors

if any(~isfield(inputHud,{'h','u','d'}))
    error('CheckHud:InvalidHUD','The hud struct is invalid');
end

% Check the columns for header and unit
if size(inputHud.h,2) > 1 || size(inputHud.u,2) > 1
    error('CheckHud:InvalidHUD','Header || Unit cannot have more than 1 column');
end

% Check if header, unit and data have same columns (header and unit are row vectors)
if ~(size(inputHud.h,1) == size(inputHud.u,1) && size(inputHud.u,1)  == size(inputHud.d,2))
    error('CheckHud:InvalidHUD','The fields need to have same number of columns');
end

%% If trahud is true

if p.Results.trahud
    % Check if GNSS Week is provided, if not then throw an error
    gnssCycleIdx = find(~cellfun(@isempty, strfind(inputHud.h, '_Cycle')));
    
    % Check if there are any reset cycles in the file
    resetCycleIdx = find(~cellfun(@isempty, strfind(inputHud.h,'_Cycle_Rst')));
    
    if isempty(gnssCycleIdx)
        error('CheckHud:ReadFile2TraHud','GNSS Week info not available or provided. Check ReadFile2TraHud.m');
    end 
    
    % Return Error if more than one field matching '*_Cycle' is found
    if  length(gnssCycleIdx) - length(resetCycleIdx) > 1   
        error('CheckHud:ReadFile2TraHud', 'Detected more than one filed holding GNSS week information.');
    end
end

%% Explicit Warnings

if size(inputHud.d,1) <= 1
    warning('CheckHud:Data','hud struct has only one data entry');
end

strHashIdx = strfind(inputHud.h,'#');
strDashIdx = strfind(inputHud.h,'-');

if any(~cellfun(@isempty,strHashIdx)) || any(~cellfun(@isempty,strDashIdx))
    warning('CheckHud:FieldChar',...
        'Header contains non-permissible char {#,-} replacing with {n,_}');
    inputHud.h = strrep(inputHud.h,'#','n');
    inputHud.h = strrep(inputHud.h,'-','_');
end

%% Check the SolutionType field

solTypeIdx = find(~cellfun(@isempty, strfind(inputHud.h, 'SolutionType')));

if ~isempty(solTypeIdx)
    solTypeData = inputHud.d(:,solTypeIdx);
    
    % If any epoch has solution type as NaN throw a warning 
    if any(isnan(solTypeData))
        % exchange nans with -1s which is later on
        % mapped to SolutionType 'N/A'
        
        inputHud.d(isnan(inputHud.d(:,solTypeIdx)),solTypeIdx) = 127;
    end
end

%% Check the InsAlignmentStatus field

alignTypeIdx = find(~cellfun(@isempty, strfind(inputHud.h, 'InsAlignStatus')));

if ~isempty(alignTypeIdx)
    alignStatusData = inputHud.d(:,alignTypeIdx);
    
    % If any epoch has alignment status as NaN, replace it with -1 
    if any(isnan(alignStatusData))
        % exchange nans with -1s which is later on mapped to AlignmentType
        % 'N/A'
        inputHud.d(isnan(inputHud.d(:,alignTypeIdx)),alignTypeIdx) = 127;

    end
end

%% Return the corrected Hud struct

corrHud = inputHud;

end
