function [index,test_X,train_X,test_y,train_y] = CrossValidation_splits(X,y,method_cv,shuffle,fold,division)
%
%   Function designated to separate samples into calibration and validation datasets 
%   for different method_cv methods
%   Function:
%   [index,test_X,train_X,test_y,train_y] = CrossValidation_splits(X,y,method_cv,shuffle,fold,division);
%   --------------------------------INPUT-------------------------------------------------
%   X - Matrix (n,p), predictor matrix (assumed to be center)
%   y - Matrix (n,m), predictand (assumed to be center)
%   method_cv - Cross-Validation methods. 
%       1 (K-fold)
%       2 (Leave-One-Out)
%       3 (Contiguous Block)
%       4 (Monte Carlo)               
%   shuffle - permutade de orther of samples (recommended)
%       0 don't use shuffle
%       1 use shuffle
%   fold - number of folds to divide the dataset 
%   division - percentage of samples in the calibration dataset (used in the Monte Carlo method)
%   --------------------------------OUTPUT------------------------------------------------
%   index   - original index of the samples divided in multiple folds
%   test_X  - samples separeted in the validation set
%   train_X - samples separeted in the calibration set
%   test_y  - samples of the class array separeted in the validation set
%   train_y - samples of the class array separeted in the calibration set
%   --------------------------------Example---------------------------------------------
%   [index,test_X,train_X,test_y,train_y] = CrossValidation_splits(X,y,2,1,10)
%   [index,test_X,train_X,test_y,train_y] = CrossValidation_splits(X,y,4,0,10,70)
%
%   This is a part of the GNAT
%   Copyright  2021  <Mathias Nilsson>%
%   This program is free software; you can redistribute it and/or modify
%   it under the terms of the GNU General Public License as published by
%   the Free Software Foundation; either version 2 of the License, or
%   (at your option) any later version.
%
%   This program is distributed in the hope that it will be useful,
%   but WITHOUT ANY WARRANTY; without even the implied warranty of
%   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
%   GNU General Public License for more details.
%
%   You should have received a copy of the GNU General Public License along
%   with this program; if not, write to the Free Software Foundation, Inc.,
%   51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
%
%   Dr. Mathias Nilsson
%   School of Chemistry, University of Manchester,
%   Oxford Road, Manchester M13 9PL, UK
%   Telephone: +44 (0) 161 306 4465
%   Fax: +44 (0)161 275 4598
%
%   Hugo da Silva Rocha, PhD Student
%   School of Chemistry, University of Manchester,
%   hugo.rocha@postgrad.manchester.ac.uk

sort_array = (1:size(X,1))';
if shuffle == 1    
    sort_array = randperm(size(X,1))';
end
% Dividing samples according to methods
switch method_cv
    case 1 %'K-fold' 
        % code to divide the dataset int k-sub data sets.
        N = size(X,1);
        split_size = fix(N/fold);

        % index
        test(:,1) = [1;split_size];
        for n = 2:fold
          test(:,n) = [(n-1)*split_size+1;(n)*split_size];
        end

        if (mod(N,fold) ~= 0)         
            for i = 1:mod(N, fold)
                test(2,i) = test(2,i) + 1;
                test(1,i+1:end) = test(1,i+1:end) + 1;
                test(2,i+1:end) = test(2,i+1:end) + 1;
            end
        end
        
        index.train = repmat({sort_array},1,fold);

        for n = 1:fold
            index.test{n} = sort_array((test(1,n):test(2,n))');
            index.train{1,n}((test(1,n):test(2,n))') = [];       

            test_X{n} = X(index.test{n},:); train_X{n} = X(index.train{n},:);
            test_y{n} = y(index.test{n},:); train_y{n} = y(index.train{n},:);                        
        end        
    
    case 2 %'Leave-One-Out'
        N = size(X,1);
        split_size = fix(N/fold);

        % index
        test(:,1) = [1;split_size];
        for n = 2:fold
          test(:,n) = [(n-1)*split_size+1;(n)*split_size];
        end

        if (mod(N,fold) ~= 0)         
            for i = 1:mod(N, fold)
                test(2,i) = test(2,i) + 1;
                test(1,i+1:end) = test(1,i+1:end) + 1;
                test(2,i+1:end) = test(2,i+1:end) + 1;
            end
        end
        
        index.train = repmat({sort_array},1,fold);

        for n = 1:fold
            index.test{n} = sort_array((test(1,n):test(2,n))');
            index.train{1,n}((test(1,n):test(2,n))') = [];       

            test_X{n} = X(index.test{n},:);
            test_y{n} = y(index.test{n},:);

            train_X{n} = X(index.train{n},:);
            train_y{n} = y(index.train{n},:);            
        end
    case 3 %'Contiguous Block'

        % I will do this in the future 

    case 4 %'Monte Carlo'

        % I will do this in the future 

    otherwise
        % Do nothing        
end