 function ClassInfo = ClassGUI(Classes,SequenceTable,Arraydim,LabelArray,OldData)
%% ClassInfo; An interactive graphical user interface to visualization of the Classes constructed in GNAT
%
%   function ClassInfo = ClassGUI(Classes,SequenceTable,Prune)
%   --------------------------------INPUT-------------------------------------------------
%   Classes       =   Vector with chemical shifts in ppm;
%   SequenceTable =   Matrix with row-vectors relatives to each NMR spectrum of each sample;
%   Prune         =   See PrepareAnalyzeData in GNAT to more information.
%   Arraydim      =   Numer of samples loaded in GNAT
%   LabelArray    =   (optional input) Label created for each class
%   OldData       =   Sequence table for classes from GNAT
%
%   --------------------------------OUTPUT------------------------------------------------
%   ClassInfo = A model containing the class created and their respective labels
%
%   --------------------------------REFERENCE---------------------------------------------
%
%   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, Undergrad Studant
%   Institute of Chemistry, Univeristy of Brasilia,
%   POBOX 70910-900, Asa Norte - Brasília (DF), Brazil
%   rocha.hugo@aluno.unb.br
%
%   HSR 29    Oct 2021    Lattest updated   
%   HSR 21    Jun 2022    Minor corrections  
%   HSR 03    Jul 2022    Minor corrections  
%   HSR 29    Jul 2022    Corrections in labels of classes deleted 
%% Setup the GUI CONTROLS
ClassInfo.version='Class Construction GUI';
hClassFigure = figure(...
    'Units','normalized',...
    'MenuBar','none',...
    'Name',ClassInfo.version,... 
    'NumberTitle','Off',...Ffind
    'Toolbar','Figure',...
    'OuterPosition',[0.0 0.0 0.252 0.54],...
    'Resize','on',...
    'Tag','ClassGUI',...
    'Visible','off');
movegui(hClassFigure,'center')

if ~exist('LabelArray','var')
    LabelArray = '';   
end

if ~exist('OldData','var')
    OldData = '';   
end

%Clean up the Toolbar, removing things we don't need
    tmp = findall(hClassFigure,'ToolTipString','New Figure');
    set(tmp,'Visible','Off')
    tmp = findall(hClassFigure,'ToolTipString','Open File');
    set(tmp,'Visible','Off')
    tmp = findall(hClassFigure,'ToolTipString','Link Plot');
    set(tmp,'Visible','Off')
    tmp = findall(hClassFigure,'ToolTipString','Insert Legend');
    set(tmp,'Visible','Off')
    tmp = findall(hClassFigure,'ToolTipString','Rotate 3D');
    set(tmp,'Visible','Off')
    tmp = findall(hClassFigure,'ToolTipString','Brush/Select Data');
    set(tmp,'Visible','Off')
    tmp = findall(hClassFigure,'ToolTipString','Insert Colorbar');
    set(tmp,'Visible','Off')
guidata(hClassFigure,ClassInfo);
%% ------Setup the Class Main Painels
hLabelPanel=uipanel(...
    'Parent',hClassFigure,...
    'TitlePosition','centertop',...
    'Units','Normalized',...
    'FontWeight','bold',...
    'Position',[0.0 0.75 1.0 0.25]);
hClassTablePanel=uipanel(...
    'Parent',hClassFigure,...
    'TitlePosition','centertop',...
    'Units','Normalized',...
    'FontWeight','bold',...
    'Position',[0.0 0.0 1.0 0.75]);
%% ------Class Table Structure
hClassInfoTable = uitable(...
    'parent',hClassTablePanel,... 
    'units','normalized',...
    'columneditable',true,...
    'columnname',{'Sample','Class','Included','Label'},...
    'columnwidth',{'auto'},...
    'rowname',{},...
    'ColumnFormat',{[],{'class'},[],[]}, ...
    'Enable','on',...     
    'CellEditCallback',@Outlier_Callback,...
    'position',[0.01 0.01 0.985 0.95]);
%% ------Class Label Structure
hAddLabel = uicontrol(...
    'parent',hLabelPanel,...
    'style','PushButton',...
    'String','Add Label',...
    'Units','Normalized',...
    'TooltipString','Export data of pca analysis to a .txt file',...
    'Position',[0.67 0.675 0.20 0.3],...
    'Callback',{@AddLabel_Callback});    
hDeletLabel = uicontrol(...
    'parent',hLabelPanel,...
    'style','PushButton',...
    'String','Delete Label',...
    'Units','Normalized',...
    'TooltipString','Export curent figures',...
    'Position',[0.67 0.35 0.20 0.3],...
    'Callback',{@DeletLabel_Callback}); 
hYesSample = uicontrol(...
    'parent',hLabelPanel,...
    'style','PushButton',...
    'String','Yes',...
    'Units','Normalized',...
    'TooltipString','Export curent figures',...
    'Position',[0.67 0.025 0.1 0.3],...
    'Callback',{@YesSamples_Callback}); 
hNoSample = uicontrol(...
    'parent',hLabelPanel,...
    'style','PushButton',...
    'String','No',...
    'Units','Normalized',...
    'TooltipString','Export curent figures',...
    'Position',[0.77 0.025 0.1 0.3],...
    'Callback',{@NoSamples_Callback}); 
%hClasses=
uicontrol(...
    'Parent',hLabelPanel,...
    'Style','text',...
    'String','Class',...
    'Units','Normalized',...
    'FontWeight','bold',...
    'horizontalalignment','l',...
    'Position',[0.073 0.60 0.14 0.19]);  
hClassCreated = uicontrol(...
    'Parent',hLabelPanel,...
    'Style','popupmenu',...
    'Units','Normalized',...
    'TooltipString','Selects the method for Cross-Validation',...
    'FontWeight','normal',...
    'FontSize',8.3,...
    'HorizontalAlignment','center',...
    'String',...
    '',...
    'Position',[0.017 0.20 0.26 0.32]);
%hLabels=
uicontrol(...
    'Parent',hLabelPanel,...
    'Style','text',...
    'String','Label',...
    'Units','Normalized',...
    'FontWeight','bold',...
    'horizontalalignment','l',...
    'Position',[0.40 0.60 0.14 0.19]);  
hEditLabel=uicontrol(...
    'Parent',hLabelPanel,...
    'Style','edit',...
    'BackgroundColor','w',...
    'TooltipString','Space between spectra',...
    'String','',...
    'Units','Normalized',...
    'Position',[0.33 0.32 0.26 0.22]); 
%% ------Plot Initialization  
   set(hClassFigure,'WindowKeyPressFcn',@keyPressCallback);
   ConstructTable_Callback()   
   ClassInfo.NClasses = num2cell(unique(Classes));
   ClassInfo.NClasses{end+1,1} = 'all';
   set(hClassCreated,'string',ClassInfo.NClasses);   
   set(hClassFigure,'Visible','on');  
%% ------Callbacks
     function AddLabel_Callback(source,eventdata)
         ClassInfo = guidata(hClassFigure);
         
         Labels = get(hEditLabel,'String');
         Class = get(hClassCreated,'value');   
         try
            row = find(ClassInfo.Classes==ClassInfo.NClasses(Class,:)); 
         catch ME
             return
         end                         
         hClassInfoTable.Data(row,4) = cellstr(Labels);                
         ClassInfo.UserData = get(hClassInfoTable, 'data');
         ClassInfo.Modified = get(hClassInfoTable, 'data');
         
         guidata(hClassFigure,ClassInfo);
     end
     
     function DeletLabel_Callback(source,eventdata)
         ClassInfo = guidata(hClassFigure);
         
         Labels = '';
         Class = get(hClassCreated,'value');   
         try
            row = find(ClassInfo.Classes==ClassInfo.NClasses(Class,:)); 
         catch ME
             return
         end   
         hClassInfoTable.Data(row,4) = cellstr(Labels);                
         ClassInfo.UserData = get(hClassInfoTable, 'data');
         ClassInfo.Modified = get(hClassInfoTable, 'data');

         guidata(hClassFigure,ClassInfo);
     end

     function YesSamples_Callback(source,eventdata)
         ClassInfo = guidata(hClassFigure);

         % If statment for a shortcut (eventdata) to turn all samples into
         % yes independently of their classes
         if ~isempty(eventdata) && isnumeric(eventdata)
             Class = eventdata;
         else
             Class = get(hClassCreated,'value');
         end

         try
            if Class > size(unique(ClassInfo.Classes),1)
                ClassInfo.row = 1:size(ClassInfo.Classes,1);
            else         
                ClassInfo.row = find(ClassInfo.Classes==ClassInfo.NClasses(Class,:)); 
            end            
            ClassInfo.incl = 'yes';
         catch ME
             return
         end  

         guidata(hClassFigure,ClassInfo);
         Outlier_Callback()

         guidata(hClassFigure,ClassInfo);
     end

     function NoSamples_Callback(source,eventdata)
         ClassInfo = guidata(hClassFigure);

         Class = get(hClassCreated,'value');   
         Labels = get(hEditLabel,'String');
         
        if strcmpi(Labels,'import') % Remove the imported file                
            Outliers = evalin('base','Outliers');
            for n = 1:size(Outliers,1)
                B = Outliers(n,2);
                E = Outliers(n,3);
                samples = size(Outliers(n,2):1:Outliers(n,3),1);
                for i = B:E
                    C(B:E,1) = repmat(Classes(n,1), samples, 1);
                end
            end
            row_indices = find(all(C,2));
            ClassInfo.row = row_indices;
            ClassInfo.incl = 'no';
%             ClassInfo.row = find(ClassInfo.Classes==ClassInfo.NClasses(Class,:)); 
%             % Checking if other classes were removed before
%             out_samples = find(ClassInfo.Classes~=ClassInfo.NClasses(Class,:)); 
%             if strcmp(unique(hClassInfoTable.Data(out_samples,3)),'no') % if all other samples were removed
%                 warndlg('All samples can not be removed','Warning'); 
%                 return
%             end
        else % Remove the selected samples Class
         
             try
                if Class > size(unique(ClassInfo.Classes),1)
                    warndlg('All samples can not be removed','Warning'); 
                    return
                else   
                    ClassInfo.row = find(ClassInfo.Classes==ClassInfo.NClasses(Class,:)); 
                    % Checking if other classes were removed before
                    out_samples = find(ClassInfo.Classes~=ClassInfo.NClasses(Class,:)); 
                    if strcmp(unique(hClassInfoTable.Data(out_samples,3)),'no') % if all other samples were removed
                        warndlg('All samples can not be removed','Warning'); 
                        return
                    end
                end            
                ClassInfo.incl = 'no';
             catch ME
                 return
             end       
        end
        
         guidata(hClassFigure,ClassInfo);
         Outlier_Callback()

         guidata(hClassFigure,ClassInfo);
     end

     function Outlier_Callback (source,eventdata)
         ClassInfo = guidata(hClassFigure);
        
         if ~exist('eventdata', 'var')
             idx = ClassInfo.row;
             incl = ClassInfo.incl;
             smp = char(ClassInfo.Original(idx,1));
         else
             idx = eventdata.Indices(1);
             incl = eventdata.NewData;
             smp = char(ClassInfo.Original(idx,1));
         end

         colergen = @(cor,text) ['<html><table border=0 width=75 bgcolor=',cor,'><TR><TD>',text,'</TD></TR> </table><html>'];

         for m = 1:size(smp,1)                  
             NewData(m) = cellstr(colergen('#FF0000',smp(m,:)));
         end

         newvar = "<html><tr><td width=9999 align=center>"  + NewData;

         if strcmpi(incl,'no')
             hClassInfoTable.Data(idx,1) = cellstr(newvar);
             hClassInfoTable.Data(idx,3) = cellstr("no");
         else
             hClassInfoTable.Data(idx,1) = cellstr(smp);
             hClassInfoTable.Data(idx,3) = cellstr("yes");
         end

         ClassInfo.UserData = get(hClassInfoTable, 'data');
         ClassInfo.Modified = get(hClassInfoTable, 'data');

         guidata(hClassFigure,ClassInfo);
     end
     
     function ConstructTable_Callback(source,eventdata)
        ClassInfo = guidata(hClassFigure);   
        
        ClassInfo.NClasses = unique(Classes);
        set(hClassCreated,'string',ClassInfo.NClasses);
             
        colergen = @(cor,text) ['<html><table border=0 width=20 bgcolor=',cor,'><TR><TD>',text,'</TD></TR> </table><html>'];
        colors = ['#FF0000';'#00FF00';'#0000FF';'#FF00FF';'#00FFFF';'#FFFF00'];
        
        if size(ClassInfo.NClasses,1) > size(colors,1)
            k = ceil(size(ClassInfo.NClasses,1)./size(colors,1));
            c = repmat(colors,k+1,1);
            Clr = c(1:size(ClassInfo.NClasses,1)+1,1:end); 
        else
            c = repmat(colors,2,1);
            Clr = c(1:size(ClassInfo.NClasses,1)+1,1:end);
        end
        
        C = zeros(Arraydim,1);
        for n = 1:size(SequenceTable,1)            
            B = SequenceTable(n,2);
            E = SequenceTable(n,3); 
            samples = size(SequenceTable(n,2):1:SequenceTable(n,3),1);
            for i = B:E
                C(B:E,1) = repmat(Classes(n,1), samples, 1);
            end
        end    
        
        ClassInfo.Classes = C;
       
        class = unique(SequenceTable(:,1));
        class = [0; class];
        num_class = length(class);
        for n = 1:num_class
            x = class(n);
            a = ismember(C(:,1),x);
            [aa] = find(a); aa = aa';
            num_aa = length(aa);
            if isempty(aa)
                continue
            elseif ~isempty(aa)
                for m = 1:num_aa                  
                    k = aa(m);
                    S{k,1} = colergen(Clr(n,1:end),num2str(C(k,1)));                              
                end                
            end
        end        

        S_char = char(S);
        
        Samples = "Sample_" + string(1:size(C, 1));
        Samples = char(Samples');
        
        L = 1:length(C);
        Log = logical(L)';
        spls = ones(size(Samples,1),1);
       
        set(hClassInfoTable,'Data',[cellstr(Samples),cellstr(S_char)]);

        for i=1:size(S,1)
            hClassInfoTable.Data{i,2} = ['<html><tr><td width=9999 align=center>',hClassInfoTable.Data{i,2}];
        end

        set(hClassInfoTable,'ColumnFormat',{[],[],{'yes','no'},[]});    
        for i=1:size(S,1)
            hClassInfoTable.Data{i,3} = 'yes';
        end

        if ~isempty (LabelArray)
            clr = find(any(~ClassInfo.Classes,2));
            LabelArray(clr) = cellstr('');
            ClassInfo.LabelArray = LabelArray;
            hClassInfoTable.Data(:,4) = LabelArray;                      
        end
        
        set(hClassInfoTable,'ColumnEditable',[false,false,true,false]);
        ClassInfo.UserData = get(hClassInfoTable, 'data');
        ClassInfo.Original = get(hClassInfoTable, 'data');
        
        % Auto recize table
        jscroll = findjobj(hClassInfoTable);
        jTable = jscroll.getViewport.getView;
        jTable.setAutoResizeMode(jTable.AUTO_RESIZE_SUBSEQUENT_COLUMNS)

        if ~isempty (OldData)
            hClassInfoTable.Data = OldData; 
            ClassInfo.UserData = OldData;
            ClassInfo.Modified = OldData;
        end

        % Resizing all components of the GUI for all types of monitors
        txtHand = findall(hClassFigure, '-property', 'FontUnits');
        set(txtHand, 'FontUnits', 'normalized')

        guidata(hClassFigure,ClassInfo);
     end
     
     function keyPressCallback(source,eventdata)
         ClassInfo = guidata(hClassFigure);
         % determine the key that was pressed
         keyPressed = eventdata.Key;
         modifier = eventdata.Modifier;
         if isempty(modifier)
             modifier = '';
         elseif strcmpi(keyPressed,'y') && strcmpi(modifier,'Control')
              uicontrol(hYesSample);
              % invoke the callback for the plot button
              YesSamples_Callback(hYesSample,1+size(unique(ClassInfo.Classes),1));   
         end
         guidata(hClassFigure,ClassInfo);
     end
 waitfor(hClassFigure);
 end