function [outfun] = SingClassFusion(inStructGenFus)
% % function [outfun] = SingClassFusion(inStructGenFus)

% FUNCTION 2
% This is the second function (2 out of 3) for one-class classification that
% runs the Sum of Ranking Differences (SRD) on each sample from the output 
% generated by SingClassLMOCVfusIn.m (FUNCTION 1).

%|~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~|
%| NOTE: Use SingClassROC.m next in sequence                                      | 
%|~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~|

%{
Inputs:
    inStructGenFus: struct file generated from the output of
                    SingClassLMOCVfusIn.m

Other Main Functions Used: 
    struct2var.m: This function pulls out the variables from the struct file
    srdPack.m: This is the functions that starts to run SRD;
                Calls: srdMaster.m, srdMatrix.m, srdPack.m, and srdRepack.m

Outputs:
    input: the inputs used to run one-class classfication (see
           SingClassfusIn.m for more)
    fusOutSing: A cell array (nCV by nClasses)containing the SRD results
                for each validation split for all classes
                   Contains: Struct (nValidation by max tuning parameter)
                    that has the SRD output at each tuning parameter window
                     See SRDreadme.m section [3]
    tuneMax: The maximum tuning parameter window that is used (it could
             have changed from the original max window because one of the 
             outliers had NaN at the later windows)

/// Created by Brett Brownfield & Tony Lemos August 1, 2018 (Last edited on 7/10/19)
/// Department of Chemistry, Idaho State University, Pocatello, Idaho 83209 USA
%}


%Obtaining info from inputStruct
inputStruct=inStructGenFus.input;
struct2var(inputStruct);
nsamp=[inStructGenFus.input.nOutPure, inStructGenFus.input.nInNonPure];

% Checking if there is more than 2 classes (which shouldn't happen)
if size(Xin,2) > length(nsamp)
    extra  =  (size(Xin,2) - length(nsamp));
    nsamp = [nsamp repmat(nsamp(end),1,extra)];
end


% This determines the actual maximum tuning parameter (since NaN's occurs
% at higher eigenvectors)
 
 nCV = size(inStructGenFus.fusInSing,3);
 nC = size(inStructGenFus.fusInSing,2);
 nInst = size(inStructGenFus.fusInSing,1);
 
 [tuneMax] = LVCheck(inStructGenFus.fusInSing,nCV,nC,nInst,inputStruct,nsamp);

 inputStruct.tuneMax = tuneMax;


% Sum of Ranking Differences
[fusOutSing]=classSingOut(inStructGenFus.fusInSing, tuneMax , nsamp, inStructGenFus.input.merit);





% Saving outputs
outfun.input=inputStruct;
outfun.fusOutSing=fusOutSing;
outfun.tuneMax = tuneMax;
end


function [tuneMax] = LVCheck(fusInSing,nCV,nC,nInst,inputStruct,nsamp)

u = 1; % For indexing
AllTuneMax = nan(1,1);

for i = nCV % nCrossVals
    fusInSing1 = fusInSing(:,:,i);
    for ii = 1:nC %nClass
        
        for iii = 1:nInst % nInstruments
            
            for j = 1:nsamp(ii)
                fusInSing3 = fusInSing1{iii,ii}(j).srdin;
                
                for jj = 2:size(fusInSing3,1)
                    LVsize = size(fusInSing3{jj,1},1);
                    AllTuneMax(u,1) = LVsize;
                    u = u+1;
                    
                end
            end
        end
    
    end
end

   AllTuneMax1 = unique(AllTuneMax);
 tuneMax =repmat(min(AllTuneMax1), length(inputStruct.tuneMax),size(fusInSing,1));
 
end


function [fusOutSing, valClass, yTrue]=classSingOut(fusInSing, tuneMax, nsamp, merit)
% This fuction performs Sum of Ranking Differences on a increasing 
% range of tuning parameters

[nInst, nC, nCV]=size(fusInSing);

% Preallocation Level 1
fusOutSing=cell(nCV,nC);
valClass=cell(nCV,nC);
srdinTR=cell(nCV,nC);
yTrue = nan(1,nC);
for i=1:nCV
    disp(['CV #', num2str(i)])
    for ii=1:nC
        %Ytrue
        if ii==1
            yTrue(ii)=true;
        else
            yTrue(ii)=false;
        end
        srdinTR{i,ii}=repmat({{}}, nsamp(ii), unique(max(tuneMax)));
        % Calculating SRD, valClass
        for j=1:nsamp(ii)
            ctdisp(j)
            %Reorganizing Input Mat/Cell
            for instNum=1:nInst
                for k=1:tuneMax(instNum)
                    
                    srdinTR{i, ii}{j, k}=[srdinTR{i, ii}{j, k};srdInTuneRed(fusInSing{instNum,ii, i}(j), k, merit)];
                end
            end
            
            %RUNNING SRD
            for k=1:max(tuneMax)
                fusOutSing{i,ii}(j,k)=srdPack(srdinTR{i, ii}{j, k},'max', 'srd', 'none');
                
            end
        end % nsamp
    end % nC
end
end %

function srdinTR=srdInTuneRed(srdStruct, tune, merit)
% This fuction reduces the fusion input matrix to 1:tune
srdin=srdStruct.srdin;
nMerits=size(srdin,1);
srdinTR=cell(nMerits, 1);
if  sum(strcmpi(merit, 'vm'))
	for i=1:nMerits
		if i==1
			srdinTR{i}=srdin{i};
		else
			srdinTR{i}=srdin{i}(1:tune, :);
		end % if
	end % for nMerits
	
else
	
end 



end % function