function [c] = TIfate(emesh, es, varargin)
% TIfate(emesh, es, varargin)
% Interactive tool for clustering triangles
% es = source TIs
% varargin:
% GUI
% 	max_slider = max position of slider
% 	nogui = just make clusters, no gui
% For hierachical clustering (default):
% 	metric = pdist metric
% 	linkage = linkage
% 	dist_cut = cluster cut
% For affinity propagation clustering (APC):
%	apc = use APC
%	apc_damp = APC dampening factor
%	WARNING: Interactive GUI will not work for APC
%

    DIST_CUT = 0.125; 
    SLIDER_MAX = 0.5;
    METRIC = 'correlation';
    LINKAGE = 'average';
    apc_cluster = 0;
    apc_damp = 0.5;
    gui = 1;
    
%    METRIC = 'cosine';

    if ~isempty(varargin)
        i = 1;
        while i <= length(varargin),
            switch(varargin{i}),
                case 'metric'
                    METRIC = varargin{i+1};
                    i = i+1;
                case 'linkage'
                    LINKAGE = varargin{i+1};
                    i = i+1;
                case 'dist_cut'
                    DIST_CUT = varargin{i+1};
                    i = i+1;
                case 'apc'
                    apc_cluster = 1;
                case 'apc_damp'
                    apc_damp = varargin{i+1};
                    i = i+1;
                case 'max_slider'
                    SLIDER_MAX = varargin{i+1};
                    i = i+1;
                case 'nogui'
                    gui = 0;
                otherwise
                    error('Argument %s not known', varargin{i});
            end
            i = i+1;
        end
    end

    
    dist_cut = DIST_CUT;
        
    pd = pdist(es,METRIC);
    
    Z = linkage(pd,LINKAGE);
    c = cluster(Z,'Cutoff',DIST_CUT, 'Criterion','distance');
    nC = max(c);

    if apc_cluster == 1,
        apc_dist = squareform(pd);
        apc_dist = apc_dist .^ 2;
        N=size(apc_dist,1);
        apc_s = zeros(N*N-N,3);
        j=1; 
        for i= 1:N,
            k=[1:i-1,i+1:N]; 
            apc_s([j:j+N-2],1) = i; 
            apc_s([j:j+N-2],2) = k; 
            apc_s(j:j+N-2,3) = -apc_dist(i,k); 
            j=j+N-1;
        end
        % apc_p = repmat(median(apc_s(:,3)), [1, N*N-N]);
        apc_p = median(apc_s(:,3));
        apc_idx = apcluster(apc_s,apc_p,'dampfact',apc_damp);
        
        SLIDER_MAX = 1;
        dist_cut = apc_damp;
        j = 1;
        c = zeros(length(unique(apc_idx)), 1);
        for i=unique(apc_idx)'
            c(find(apc_idx == i)) = j;
            j = j+1;
        end
    end
    
    if gui == 0,
        return;
    end
    
    p_scale = emesh.p_scale;
    t = emesh.t;
        
    ti = sprintf('polygon-clusters-linear %s %s',LINKAGE,METRIC); 
    
    % create GUI
    f = figure('Visible', 'off', 'Position', [360, 500, 1000, 400]);    
    hslider = uicontrol('style','slider',... 
        'value',dist_cut,... 
        'min',0,'max',SLIDER_MAX,... 
        'position',[700 10 200 20],... 
        'callback',{@slider_callback});     
    htext_t=uicontrol('style','text',... 
        'string','threshold:',...
        'position',[600 10 100 15]);
    htext_min=uicontrol('style','text',... 
        'string',num2str(0),...
        'position',[700 30 30 10]);
    htext_max=uicontrol('style','text',... 
        'string',num2str(SLIDER_MAX),...
        'position',[870 30 30 10]);
    hedit=uicontrol('style', 'edit',...
        'min',0,'max',1,... 
        'string',num2str(dist_cut),...
        'position', [900 10 40 20],...
        'callback',{@edit_callback});
%    hbutton=uicontrol('style', 'pushbutton',...
%        'string', 'Apply',...
%        'position', [950 10 40 20],...
%        'callback',{@edit_callback});     
    ha = axes('Units', 'Pixels', 'Position', [50, 50, 900, 450]);
    
    % Initialize GUI
    set([f, ha, hslider, hedit, htext_t, htext_min, htext_max], 'Units', 'normalized');
    set(f, 'Name', ti);
    movegui(f, 'center');

    % Create figure
    subplot(1,2,1); dendrogram(Z, 0, 'colorthreshold', DIST_CUT);
    subplot(1,2,2); displaymesh(c',p_scale, t); colormap(hsv); caxis([1 max(c)]); % colormap(colorcube);
    
    % Make visible
    set(f,'Visible', 'on');

    function slider_callback(source,eventdata) 
    
        val = get(source, 'Value');
        dist_cut = val; 
        % set(vh.hline,'ydata',v.x/v.div) 
        c = cluster(Z,'Cutoff',dist_cut, 'Criterion','distance');
        nC = max(c);
        subplot(1,2,1); dendrogram(Z, 0, 'colorthreshold', dist_cut);
        subplot(1,2,2); displaymesh(c',p_scale, t); colormap(hsv); caxis([1 max(c)]);
        set(hedit,'string', num2str(dist_cut));
    end

    function edit_callback(source,eventdata) 
        str = get(source, 'String');
        dist_cut = str2num(str); 
        % set(vh.hline,'ydata',v.x/v.div) 
        c = cluster(Z,'Cutoff',dist_cut, 'Criterion','distance');
        nC = max(c);
        subplot(1,2,1); dendrogram(Z, 0, 'colorthreshold', dist_cut);
        subplot(1,2,2); displaymesh(c',p_scale, t); colormap(hsv); caxis([1 max(c)]);
        if dist_cut > SLIDER_MAX,
            SLIDER_MAX = dist_cut;
            set(hslider,'max', SLIDER_MAX);
        end
        set(hslider,'value', dist_cut);
        set(hedit,'string', num2str(dist_cut));
    end

    function recluster()
        c = cluster(Z,'Cutoff',dist_cut, 'Criterion','distance');
        nC = max(c);
    end

end


function displaymesh(stain, p_scale, t)
    % colormap(hsv); caxis([1 255])
    colormap(hsv(max(stain)));
    axis ij; axis off;
    hold on;
    for i = 1:size(t,1)
        roic = fix(p_scale(t(i,:),1)');
        roir = fix(p_scale(t(i,:),2)');
        fill(roic,roir,stain(i));
        text(sum(roic)/3, sum(roir)/3, num2str(stain(i)), 'VerticalAlignment','middle',...
            'HorizontalAlignment','center', 'FontSize',8)
    end;
    hold off;
end
