classdef AC9 < Instrument
  %AC9 Summary of this class goes here
  %   Detailed explanation goes here
  
  properties
    device_file = '';
    lambda_ref = [];
    lambda_c = [];
    lambda_a = [];
    cal_param = [];
    modelG50 = [];
    modelmphi = [];
  end
  
  methods
    function obj = AC9(cfg)
      %AC9 Construct an instance of this class
      
      % Object Initilization
      obj = obj@Instrument(cfg);
      
      % Change default processing method
      obj.bin_method = 'SB_IN_PRCTL';
      
      % Post initialization
%       if isfield(cfg, 'device_file'); obj.device_file = cfg.device_file;
%       else; error('Missing field device_file.'); end
%       % Set lambda reference to c by default
%       if isfield(cfg, 'lambda_reference'); obj.lambda_ref = cfg.lambda_reference; end
      % DEPRECATED AS will be read in device file now
%       if isfield(cfg, 'lambda_a'); obj.lambda_a = cfg.lambda_a;
%       else; error('Missing field lambda_a.'); end
%       if isfield(cfg, 'lambda_c'); obj.lambda_c = cfg.lambda_c;
%       else; error('Missing field lambda_c.'); end

      if isempty(obj.logger) 
        fprintf('WARNING: Logger set to WetView.\n');
        obj.logger = 'WetView';
      end
    end    
    
%     function ReadDeviceFile(obj)
%         % Read Device file to set wavelength
%       [obj.lambda_c, obj.lambda_a] = importAC9DeviceFile(obj.device_file);
%       if isempty(obj.lambda_ref); obj.lambda_ref = obj.lambda_c; end
%     end
    function ReadDeviceFile(obj)
        % Read Device file to set wavelength
      obj.lambda_ref = [412 440 488 510 532 555 650 676 715];
      obj.lambda_a = [412 440 488 510 532 555 650 676 715];
      obj.lambda_c = [412 440 488 510 532 555 650 676 715];
      obj.T_cal = [];
      obj.n_tbin_cal = [];
%       if isempty(obj.lambda_ref); obj.lambda_ref = obj.lambda_c; end
    end
    
    function obj = load_HTJSetal2021_model(obj)
      % Load model from Haëntjens et al. 2021v22 to estimate cross-sectional
      % area (G50) and slope of phytoplankton size distribution (in abundance) (mphi):
      load('HTJS20_LinearRegression_5features.mat', 'model_G50');
      load('HTJS20_LinearRegression_5P-mphi.mat', 'model_mphi');
      obj.modelG50 = model_G50;
      obj.modelmphi = model_mphi;
    end
    
    function ReadRaw(obj, days2run, force_import, write)
      % Get wavelengths from device file
      obj.ReadDeviceFile()
      % Read raw data
      switch obj.logger
        case 'WetView'
          obj.data = iRead(@importAC9wetview, obj.path.raw, obj.path.wk, ['ac9_' obj.sn '_'],...
                         days2run, 'WetView', force_import, ~write, true);
        otherwise
          error('AC9: Unknown logger.');
      end
    end
    
    function ReadRawDI(obj, days2run, force_import, write)
      % Set default parameters
      if isempty(obj.path.di)
        fprintf('WARNING: DI Path is same as raw.\n');
        obj.path.di = obj.path.raw;
      end
      if isempty(obj.di_cfg.logger) 
        fprintf('WARNING: DI Logger set to WetView.\n');
        obj.di_cfg.logger = 'WetView';
      end
      if isempty(obj.di_cfg.postfix) 
        fprintf('WARNING: DI Postfix set to "_DI" \n');
        obj.di_cfg.postfix = '_DI';
      end
      switch obj.di_cfg.logger
        case 'WetView'
          if isempty(obj.di_cfg.prefix); obj.di_cfg.prefix = ['ac9' obj.sn '_']; end
          obj.raw.diw = iRead(@importAC9wetview, obj.path.di, obj.path.wk, obj.di_cfg.prefix,...
                         days2run, 'WetView', force_import, ~write, true, false, obj.di_cfg.postfix);
        otherwise
          error('AC9: Unknown logger.');
      end
    end
    
    function Calibrate(obj, days2run, compute_dissolved, interpolation_method, CDOM, SWT, di_method, ...
        scattering_corr, compute_ad_aphi, TSG, min_nb_pts_per_cluster) % , time_weight_for_cluster
      lambda = struct('ref', obj.lambda_ref, 'a', obj.lambda_ref, 'c', obj.lambda_ref);
      SWT_constants = struct('SWITCH_FILTERED', SWT.SWITCH_FILTERED, 'SWITCH_TOTAL', SWT.SWITCH_TOTAL);
      % Load model from Haëntjens et al. 2021v22 to estimate cross-sectional
      % area (G50) and slope of phytoplankton size distribution (in abundance) (mphi):
      obj.load_HTJSetal2021_model();
      switch interpolation_method
        case 'linear'
          if compute_dissolved
            [obj.prod.p, obj.prod.g, obj.prod.QCfailed, ~, DIW_biofouling_correction_new] = processACS(lambda, ...
              obj.qc.tsw, obj.qc.fsw, [], obj.modelG50, obj.modelmphi, obj.bin.diw, ...
              [], SWT, SWT_constants, interpolation_method, di_method, scattering_corr, ...
              compute_ad_aphi, TSG, days2run);
          else
            [obj.prod.p, ~, obj.prod.QCfailed] = processACS(lambda, ...
              obj.qc.tsw, obj.qc.fsw, [], obj.modelG50, obj.modelmphi, [], ...
              [], SWT, SWT_constants, interpolation_method, [], scattering_corr, ...
              compute_ad_aphi, TSG, days2run);
          end
        case 'CDOM'
          if ~isfield(CDOM.prod, 'pd') && isempty(CDOM.qc.tsw)
            error('No CDOM data loaded: required for CDOM interpolation');
          end
          obj.cal_param.min_nb_pts_per_cluster = min_nb_pts_per_cluster;
          % obj.cal_param.time_weight_for_cluster = time_weight_for_cluster;
          if compute_dissolved
            [obj.prod.p, obj.prod.g, obj.prod.QCfailed, ~, DIW_biofouling_correction_new] = processACS(lambda, ...
              obj.qc.tsw, obj.qc.fsw, obj.cal_param, obj.modelG50, obj.modelmphi, obj.bin.diw, ...
              CDOM, SWT, SWT_constants, interpolation_method, di_method, scattering_corr, ...
              compute_ad_aphi, TSG, days2run);
          else
            [obj.prod.p, ~, obj.prod.QCfailed] = processACS(lambda, ...
              obj.qc.tsw, obj.qc.fsw, obj.cal_param, obj.modelG50, obj.modelmphi, [], ...
              CDOM, SWT, SWT_constants, interpolation_method, [], scattering_corr, ...
              compute_ad_aphi, TSG, days2run);
          end
        otherwise
          error('Method not supported.');
      end
      if compute_dissolved
        filename = fullfile(ila.instrument.ACS91.path.ui, [obj.model obj.sn '_QCDI_BiofoulingCorrection.mat']);
        if isfile(filename)
          load(filename, 'DIW_biofouling_correction')
          % % Remove old correction for the same period
          % DIW_biofouling_correction(DIW_biofouling_correction.cleaning_dt > min(days2run) & ...
          %   DIW_biofouling_correction.cleaning_dt < min(days2run)+1, :) = [];
          % add missing variable in old table to merge with new
          missing_var_old = find(~ismember(DIW_biofouling_correction_new.Properties.VariableNames, ...
            DIW_biofouling_correction.Properties.VariableNames));
          if ~isempty(missing_var_old)
            for i = 1:size(missing_var_old, 2)
              DIW_biofouling_correction = addvars(DIW_biofouling_correction, NaT(size(DIW_biofouling_correction,1), 2), ...
                'NewVariableNames', DIW_biofouling_correction_new.Properties.VariableNames(missing_var_old(i)), ...
                'Before', DIW_biofouling_correction.Properties.VariableNames{missing_var_old(i)});
            end
          end
          % add missing variable in new table to merge with old
          missing_var_new = find(~ismember(DIW_biofouling_correction.Properties.VariableNames, ...
            DIW_biofouling_correction_new.Properties.VariableNames));
          if ~isempty(missing_var_new)
            for i = 1:size(missing_var_new, 2)
              DIW_biofouling_correction_new = addvars(DIW_biofouling_correction_new, NaT(size(DIW_biofouling_correction_new,1), 2), ...
                'NewVariableNames', DIW_biofouling_correction.Properties.VariableNames(missing_var_new(i)), ...
                'Before', DIW_biofouling_correction_new.Properties.VariableNames{missing_var_new(i)});
            end
          end
          % merge tables
          DIW_biofouling_correction = [DIW_biofouling_correction; DIW_biofouling_correction_new];
        end
        save(filename, 'DIW_biofouling_correction')
      end
    end
  end
end