function con = spm_dcm_connectivity_ui(DCM,D,title_text,defaults,enabled)
% GUI for manually specifying connection values in a DCM
% FORMAT con = spm_dcm_connectivity_ui(DCM,D,title_text,defaults,enabled)
%
% DCM        - DCM structure
% D          - 'A','B' or 'C' i.e. connectivity matrix of interest
% title_text - Text to display above the matrix, e.g. 'Enter contrast for '
% defaults   - (optional) structure of default values containing
%              defaults.A, defaults.B and defaults.C
% enabled    - (optional) structure of inputs to enable with binary 
%              matrices enabled.A, enabled.B and enabled.C
% 
% Returns:
% con        - structure with con.A, con.B and con.C of user-entered values
%__________________________________________________________________________

% Will Penny & Peter Zeidman
% Copyright (C) 2014-2016 Wellcome Centre for Human Neuroimaging


% Set-up data
%--------------------------------------------------------------------------
n       = DCM.n;              % number of regions
m       = length(DCM.U.name); % number of inputs

region_names = DCM.Y.name;
input_names  = DCM.U.name;

try, A = defaults.A; catch, A = zeros(n,n); end
try, B = defaults.B; catch, B = zeros(n,n,m); end
try, C = defaults.C; catch, C = zeros(n,m); end

if nargin < 5
    enabled = struct('A',ones(size(A)),'B',ones(size(B)),'C',ones(size(C)));
end

% Set-up GUI
%--------------------------------------------------------------------------
Finter  = spm_figure('GetWin','Interactive');
header  = get(Finter,'Name');
set(Finter,'Name','Dynamic Causal Modelling')
WS      = spm('WinScale');
 
% prompt for contrast if necessary
%--------------------------------------------------------------------------
if (nargin < 2) || isempty(D)
    str = 'contrast for';
    D   = spm_input(str,1,'b',{'A','B','C'});
end
 
% set object sizes
%--------------------------------------------------------------------------
dx    = 35;
wx    = 30;
wy    = 20;
uic   = uicontrol(Finter,'String','done','Position',[300 50 060 020].*WS,...
        'Callback', 'uiresume(gcbf)');
 
% Define left edge dialogue
% itext_left = 080;
% inum_left  = 180;
%--------------------------------------------------------------------------
BackgroundColor = get(get(uic,'Parent'),'Color');
itext_left  = 030;
inum_left   = 80;
name_length = 8; % number of characters in short names
for i=1:n
    if length(region_names{i}) > name_length
        short_name(i).str = region_names{i}(1:name_length);
    else
        short_name(i).str = region_names{i};
    end
end
text_top = 336;

switch D
 
    % Get contrast weights
    %======================================================================
    case 'A' % intrinsic
 
        str   = sprintf('%s A: ',title_text);
        spm_input(str,1,'d');
        
        % Warn if no matrix elements enabled
        any_enabled = any(enabled.A(:));
        if any_enabled
            h0 = [];
        else
            h0 = add_none_enabled_warning();
        end        
 
        % Print names and numbers of regions
        %------------------------------------------------------------------
        for i = 1:n
            str    = sprintf('%s   %i',short_name(i).str,i);
            
            h1(i) = add_text([itext_left text_top-dx*i 080 020].*WS,...
                        str, any_enabled, 'right');
                    
            h2(i) = add_text([inum_left+dx*i text_top 020 020].*WS,...
                        sprintf('%i',i), any_enabled);
        end
 
        % Set contrast values and display
        %------------------------------------------------------------------
        for i = 1:n
            for j = 1:n
                cc=ceil([inum_left+dx*j text_top+4-dx*i wx wy].*WS);                          
                h3(i,j) = add_matrix_input(cc, num2str(A(i,j)), enabled.A(i,j)==1);
            end
        end
        drawnow
 
        % wait for 'done'
        %------------------------------------------------------------------
        uiwait(Finter);        
        for i = 1:n
            for j = 1:n
                A(i,j) = get_matrix_input(h3(i,j));
            end
        end
        
        % clean up
        %------------------------------------------------------------------        
        delete([h0; h1(:); h2(:); h3(:)]);
        spm_input(' ',1,'d');
         
    case 'B' % modulatory
        %------------------------------------------------------------------
        for k = 1:m
            str   = sprintf(...
                '%s B: effects of input  %-12s',...
                title_text, input_names{k});
            spm_input(str,1,'d')
 
            % Warn if no matrix elements enabled
            any_enabled = any(any(enabled.B(:,:,k)));
            if any_enabled
                h0 = [];
            else
                h0 = add_none_enabled_warning();
            end
            
            % Print names and numbers of regions
            %--------------------------------------------------------------
            for i = 1:n
                str    = sprintf('%s   %i',short_name(i).str,i);
       
                h1(i) = add_text([itext_left text_top-dx*i 080 020].*WS,...
                        str, any_enabled);                
                    
                h2(i) = add_text([inum_left+dx*i text_top 020 020].*WS,...
                        sprintf('%i',i), any_enabled);                       
            end
            
            % Set contrast values and display
            %--------------------------------------------------------------
            for i = 1:n
                for j = 1:n
                    cc=ceil([inum_left+dx*j text_top+4-dx*i wx wy].*WS);
                    h3(i,j) = add_matrix_input(cc, num2str(B(i,j,k)), enabled.B(i,j,k)==1);                  
                end
            end
            drawnow
 
            % wait for 'done'
            %--------------------------------------------------------------
            set(gcf,'CurrentObject',h3(1));
            uiwait(Finter);   
            for i = 1:n
                for j = 1:n
                    B(i,j,k) = get_matrix_input(h3(i,j));
                end
            end
            
            % clean up
            %--------------------------------------------------------------
            delete([h0; h1(:); h2(:); h3(:)]);
            spm_input(' ',1,'d');
 
        end
 
    case 'C' % input
        %------------------------------------------------------------------
        for k = 1:m
            str   = sprintf(...
                '%s C: Effects of input %-12s',...
                title_text, input_names{k});
            spm_input(str,1,'d');
            
            % Warn if no matrix elements enabled
            any_enabled = any(enabled.C(:,k));
            if any_enabled
                h0 = [];
            else
                h0 = add_none_enabled_warning();
            end                                   
            
            % Print names and numbers of regions
            %--------------------------------------------------------------
            for i = 1:n
                str    = sprintf('%s   %i',short_name(i).str,i);

                h1(i) = add_text([itext_left text_top-dx*i 080 020].*WS,...
                        str, any_enabled);                      

                cc = [inum_left+dx text_top+4-dx*i wx wy].*WS;
                h2(i) = add_matrix_input(cc, num2str(C(i,k)), enabled.C(i,k)==1);                  

            end
            drawnow
 
            % wait for 'done'
            %--------------------------------------------------------------
            set(gcf,'CurrentObject',h2(1))
            uiwait(Finter);   

            for i = 1:n
                C(i,k)   = get_matrix_input(h2(i));
            end

            % clean up
            %--------------------------------------------------------------            
            delete([h0; h1(:); h2(:)]);
            spm_input(' ',1,'d');
        end
    otherwise
        disp('Error in spm_dcm_connectivity_ui: matrix must be A, B or C');
        close
        return
end

% Bundle outputs
%--------------------------------------------------------------------------
con = struct('A',A,'B',B,'C',C);

delete(uic);

%--------------------------------------------------------------------------
function h = add_matrix_input(position, default_txt, enabled)
    % Adds an editor for a single element of a matrix
    if enabled == 1
        isvisible = 'On';
    else
        isvisible = 'Off';
    end            
    
    h = uicontrol(Finter,...
        'Position',position,...
        'BackgroundColor',BackgroundColor,...
        'Style','edit',...
        'Visible',isvisible,...
        'String',default_txt);
end
%--------------------------------------------------------------------------
function num = get_matrix_input(h)
    % Reads a number from a single element of a matrix
    entry=get(h,'string');
    entry=strtrim(entry);
    
    if isempty(entry)
        entry = '0';
    end
    
    try
        num = str2double(entry);
    catch
        error('Could not read matrix input');
    end
end
%--------------------------------------------------------------------------
function h = add_text(position, default_txt, visible, horizontalAlignment)
    % Adds a text label to the GUI
    if nargin < 3
        visible = 1;
    end
    if nargin < 4
        horizontalAlignment = 'left';
    end
    
    if visible
        visible = 'On';
    else
        visible = 'Off';
    end
    
    h  = uicontrol(Finter,'String',default_txt,...
        'Style','text',...
        'HorizontalAlignment',horizontalAlignment,...
        'BackgroundColor',BackgroundColor,...
        'Position',position,...
        'Visible',visible);
end
%--------------------------------------------------------------------------
function h = add_none_enabled_warning()
    % Adds a warning for when there are no enabled matrix entries
    position = [itext_left text_top-dx*1 250 020].*WS;
    nonestring = 'Nothing to enter - press done to continue';
    h = add_text(position, nonestring);
end

end
