function [ ] = multi_channel_viewer( )
%COUNT_CELL UI  version:  2.0.2
% View all channel together, for conveniently counting cell


% OUTPUT file format: 
% '*.csv' column -> [ x y z celltype channel ]
% '*_count.csv'   ->  cell number of each type


%% experiment setting
experiment = 3;  


%% data type seeting
datatype=1;  % 1 (single tif) or 2(tif series)
NChannel=3; % This is only used for datatype1 


%% key and mouse setting
z_scroll_direction = 1 ; %  (1 or -1) 
zoom_scroll_direction  = 1;  % (1 or -1) 
hold_space_to_pan = 0;  % (0 or 1 )  if hold space is needed to pan  


%% marker setting
marker_color = [0.5 0 1] ; % marker_color = 'green' ; % 'green', red, blue, cyan, magenta, white, yellow,  
marker_size = 10;
marker_thickness = 2;

%% cell type setting
switch experiment
    
    case 1
        exp1_str={'a+'};
        %                                          type name,  marker, color, size, thickness
        celltype_settings(1,:)={exp1_str{1},    'o',       [1 0 0],   8,   2 };
        
    case 2
        exp1_str={'a+b+' ;'a-b+' };

        
        celltype_settings(1,:)={exp1_str{1},    'o',       [1 0 0],   8,   2 };
        celltype_settings(2,:)={exp1_str{2},    '+',       [0 1 0],   8,    2 };
        
    case 3

 
            exp2_str={'a+b+' ;'a-b+' ;'a+b-'}; 

        celltype_settings(1,:)={exp2_str{1},    'o',       [1 0 0],   8,   2 };
        celltype_settings(2,:)={exp2_str{2},    '+',       [0 1 0],   8,    2 };
        celltype_settings(3,:)={exp2_str{3},    '^',       [1 1 0],   8,    2 };

        
        
    case 4
        exp1_str={'a+b-' ;'a+b+' ;'a+c-' ;'a+c+'};
        celltype_settings(1,:)={exp1_str{1},    'o',       [1 0 0],   8,   2 };
        celltype_settings(2,:)={exp1_str{2},    '+',       [0 1 0],   8,    2 };
        celltype_settings(3,:)={exp1_str{3},    'x',       [1 0 1],   8,    2 };
        celltype_settings(4,:)={exp1_str{4},    '^',       [1 1 0],   8,    2 };
        
        
    case 5
        exp1_str={'a' ;'b' ;'c' ;'d' ;'e'};
        celltype_settings(1,:)={exp1_str{1},    'o',       [1 0 0],   8,   2 };
        celltype_settings(2,:)={exp1_str{2},    '+',       [0 1 0],   8,    2 };
        celltype_settings(3,:)={exp1_str{3},    'x',       [1 0 1],   8,    2 };
        celltype_settings(4,:)={exp1_str{4},    '^',       [1 1 0],   8,    2 };
        celltype_settings(5,:)={exp1_str{5},    'p',       [0 1 1],   8,    2 };
        
  
        
end
 % marker type: + o * x s d ^ v > < p h

 
%% load data
source_file = mfilename('fullpath') ;
setting_file = [source_file '.settings.mat'];
if exist(setting_file,'file');
    load(setting_file)
else
    last_path='.\';
end

switch datatype
    case 1 % load single tif
        [file, Path]=uigetfile(fullfile(last_path,'*.*'));
        file=fullfile(Path,file);
        last_path = Path;
        [~, ~, ext] = fileparts(file);
        switch ext
            case '.tif'
                imstack = tif_stack_read(file, NChannel);
                
                
        end
        
    case 2 % tif series
        folder=uigetdir(last_path);
        imstack = tif_series_read(folder);
        file=fullfile(folder,'cells.tif');
        last_path = folder;
end
save(setting_file, 'last_path');

[Y, X, n, Nwindow] = size(imstack);


%% create window

hfig = figure('KeyReleaseFcn', @key_release, ...
    'KeyPressFcn', @key_press, ...
    'WindowButtonDownFcn', @mouse_down, ...
    'WindowButtonUpFcn', @mouse_up, ...
    'WindowScrollWheelFcn', @mouse_scroll, ...
    'WindowButtonMotionFcn', @mouse_move, ...
    'MenuBar', 'none', ...
    'ToolBar', 'none', ...
    'BusyAction', 'Cancel', ...
    'Units', 'normalized', ...
    'Renderer','painters',...
    'position', [ 0  0.05 1  0.91] ...
    ...
    );

colormap gray

gap = 0.03;
gaps=0.005;
ha = zeros(Nwindow,1);
screensize = get( 0, 'ScreenSize' );
aspect_ratio = screensize(3)/screensize(4) * 1.1;
switch Nwindow
    case 2
        s = (1-gaps)/Nwindow;
        ha(1) = axes('position', [0,0,s,1-gap]); %left top is zero
        ha(2) = axes('position', [s+gaps,0,s,1-gap]);
        target_aspect_ratio=aspect_ratio/2;
        y_label = 1-gap/2;
        
    case 3
        s = (1-gaps)/Nwindow;
        ha(1) = axes('position', [0,0,s,1-gap]);
        ha(2) = axes('position', [s+gaps,0,s,1-gap]);
        ha(3) = axes('position', [(s+gaps)*2,0,s,1-gap]);
        target_aspect_ratio=aspect_ratio/3;
        y_label = 1-gap/2;
        
    case 4
        s = (1-gap)/2;
        ha(1) = axes('position', [0,s+gap,s,s]);%,'DrawMode','fast');
        ha(2) = axes('position', [s+gap,s+gap,s,s]);%,'DrawMode','fast');
        ha(3) = axes('position', [0,0,s,s]);%,'DrawMode','fast');
        ha(4) = axes('position', [s+gap,0,s,s]);%,'DrawMode','fast');
        target_aspect_ratio=aspect_ratio;
        y_label = 0.5;
        
end

%% draw images
him = zeros(Nwindow,1);
z = 1;
for i = 1:Nwindow
    him(i) = imagesc( imstack(:,:,z,i), 'parent', ha(i),[0 255]);
    set(ha(i),'XTick',[],'YTick',[],'NextPlot','add','DataAspectRatio',[1 1 1],'DrawMode','fast');
    
 %readjust the image
    if X/Y < target_aspect_ratio
        ylim_tmp = get(ha(i),'YLim');
        ylim_tmp(2) = X/target_aspect_ratio;
        set(ha(i),'YLim',ylim_tmp);
    else
        xlim_tmp = get(ha(i),'XLim');
        xlim_tmp(2) = Y*target_aspect_ratio;
        set(ha(i),'XLim',xlim_tmp);
    end
    
end

%% draw marker
hmarker = zeros(Nwindow,1);
for i = 1:Nwindow
    hmarker(i) = plot(0,0,'Marker','+', 'Color', marker_color, ...
        'MarkerSize', marker_size, ...
        'LineWidth', marker_thickness, 'parent', ha(i));
end

%% load previous data
outputfile = [file(1:end-3) 'csv'];
outputfile_count= [file(1:end-4) '_count.csv'];
n_celltype = size(celltype_settings,1);

if exist(outputfile, 'file')
    temp = csvread(outputfile);
    ncell=size(temp,1);
    cells=zeros(ncell,6); % [x, y, z, type, axis, handle];
    cells(:,1:5)=temp;
    for i=1:ncell
        cells(i,end)=draw_cell_marker(cells(i,:), celltype_settings, ha);
    end
    cell_counter=count_cell(cells,n_celltype);
else
    cells=[];
    cell_counter=zeros(1,n_celltype);
end

 
 %% show cell type
 hlabel=zeros(n_celltype,1);
 width_label=0.1;
 
 for i=1:n_celltype
     hlabel(i) = annotation('textbox', [(i-1)*width_label, y_label-gap/2, width_label, gap ], ...
         'String', sprintf('%d:%s[%d]', i, celltype_settings{i,1}, cell_counter(i)) , 'FontSize', 15 ...
         ,'HorizontalAlignment', 'center');%, 'VerticalAlignment','middle'  );
 end

 
 %% pre setting
Ctrl = false;
mouse_point = [];
left_hold = false;
space_hold = false;
current_celltype=0;

%%  mouse down

    function mouse_down(src, evnt)
        buttonLeft = strcmp(get(src,'SelectionType'),'normal');
        buttonRight = strcmp(get(src,'SelectionType'),'alt') && ~Ctrl; %prevent mouse down and contral key to count the cell
        buttonDouble = strcmp(get(src,'SelectionType'),'open');
        
        if  buttonLeft && ( space_hold || ~hold_space_to_pan )
            left_hold = true;
            cp = get(gca,'CurrentPoint');
            mouse_point = (cp(1,1:2));
            set(src, 'pointer', 'fleur' )
        end
        
        if  buttonRight
            add_cell;
        end
        
        if buttonDouble
            delete_cell;
        end
       
    end

%%  add cell

    function add_cell()
        if current_celltype>0 && current_celltype<=n_celltype
            cp = get(gca,'CurrentPoint');
            current_channel = find(gca==ha);
            cells = [cells; cp(1,1:2) z current_celltype current_channel 0];
            cells(end,end) = draw_cell_marker(cells(end,:), celltype_settings, ha);
            csvwrite(outputfile,cells(:,1:end-1));
            cell_counter=count_cell(cells, n_celltype);
            csvwrite(outputfile_count, cell_counter')
            update_cell_counter;
        end
    end
%%
    function delete_cell()
        if ~isempty(cells)
            hcell = gco;  %get current object
            delcell = hcell == cells(:,end);
            if any(delcell)
                delete(hcell)
                cells=cells(~delcell,:);
                csvwrite(outputfile,cells(:,1:end-1));
                cell_counter=count_cell(cells, n_celltype);
                csvwrite(outputfile_count, cell_counter')
                update_cell_counter;
            end
        end
    end


   function delete_last_cell()
        if ~isempty(cells)
            hcell = cells(end,end);   
            delcell = hcell ;
            if any(delcell)
                delete(hcell)
                cells=cells(~delcell,:);
                csvwrite(outputfile,cells(:,1:end-1));
                cell_counter=count_cell(cells, n_celltype);
                csvwrite(outputfile_count, cell_counter')
                update_cell_counter;
            end
        end
    end


    function update_cell_counter
        for k=1:n_celltype
            set(hlabel(k), 'String', sprintf('%d:%s[%d]', k, celltype_settings{k,1}, cell_counter(k)));
        end
    end

    function mouse_scroll(src, evnt)
        scroll_down = evnt.VerticalScrollCount > 0;
        scroll_up =  evnt.VerticalScrollCount < 0;
        
        if Ctrl  % zoom
            
            if scroll_down
                Zoom(1-0.2*zoom_scroll_direction) 
            elseif scroll_up
                Zoom(1+0.2*zoom_scroll_direction) 
            end
            
        else % z move
            
            if scroll_down
                z_move(z_scroll_direction) 
            elseif scroll_up
                z_move(-z_scroll_direction)
            end
            
        end
        
    end

    function mouse_move(src, evnt)

        if  left_hold && ( space_hold || ~hold_space_to_pan )
            cp = get(gca,'CurrentPoint'); 
            d = (cp(1,1:2)-mouse_point);
            txl = get(gca,'XLim');
            tyl = get(gca,'YLim');
            for k=1:Nwindow
                xl = txl-d(1);
                yl = tyl-d(2);
                set( ha(k), 'XLim', xl, 'YLim', yl);
            end
        end
        
        cp = get(gca,'CurrentPoint');
        for k = 1:Nwindow
            set(hmarker(k),'XData',cp(1,1));
            set(hmarker(k),'YData',cp(1,2));
        end
        
    end

    function mouse_up(src, evnt)
        buttomLeft=strcmp(get(src,'SelectionType'),'normal');
        if  buttomLeft
            set(src, 'pointer', 'arrow' )
            left_hold = false;
        end
        
    end

    function key_press(src, evnt)
        % fprintf('%s\n',evnt.Key)
        switch evnt.Key
            case 'control'
                Ctrl = true;
            case 'space'
                space_hold = true;
        end
    end

    function key_release(src, evnt)
        
        switch evnt.Key
            case 'control'
                Ctrl = false;
                
            case 'space'
                space_hold = false;
                
            case 'leftarrow'
                for k=1:Nwindow
                    xl = get(ha(k),'XLim');
                    xl = xl - (xl(2)-xl(1));
                    set( ha(k), 'XLim', xl);
                end
                
            case 'rightarrow'
                for k=1:Nwindow
                    xl = get(ha(k),'XLim');
                    xl = xl + (xl(2)-xl(1));
                    set( ha(k), 'XLim', xl);
                end
                
            case 'uparrow'
                for k=1:Nwindow
                    yl = get(ha(k),'YLim');
                    yl = yl - (yl(2)-yl(1));
                    set( ha(k), 'YLim', yl);
                end
                
            case 'downarrow'
                for k=1:Nwindow
                    yl = get(ha(k),'YLim');
                    yl = yl + (yl(2)-yl(1));
                    set( ha(k), 'YLim', yl);
                end
                
            case 'hyphen'
                if Ctrl
                    Zoom(1.2)
                end
            case 'equal'
                if Ctrl
                    Zoom(0.8)
                end
            case 'z'
                if Ctrl
                    delete_last_cell;
                end
        end
        
        keynum = str2double(evnt.Key(end));
        if keynum>0 && keynum <= n_celltype
            current_celltype = keynum;
            for k=1:n_celltype
                set(hlabel(k),'Color','k');
            end
            set(hlabel(current_celltype),'Color',celltype_settings{current_celltype,3});
        end
        
    end

    function Zoom(scaling_factor)
        % scaling_factor = 1.2 or 0.8
        for k = 1:Nwindow
            xl = get(ha(k),'XLim');
            yl = get(ha(k),'YLim');
            xc = mean(xl);
            xl = (xl-xc)*scaling_factor+xc;
            yc = mean(yl);
            yl = (yl-yc)*scaling_factor+yc;
            set(ha(k),'XLim', xl, 'YLim', yl);
        end
    end

    function z_move(move_direction)
        if move_direction > 0
            if z<n
                z=z+1;
                for k=1:Nwindow
                    set(him(k),'Cdata', imstack(:,:,z,k));
                end
            elseif z>n
                z=n;
            end
            
        elseif move_direction < 0
            if z>1
                z=z-1;
                for k=1:Nwindow
                    set(him(k),'Cdata', imstack(:,:,z,k));
                end
            elseif z<1
                z=1;
            end
        end
    end

end

function cell_counter=count_cell(cells, ntype)

cell_counter=zeros(ntype,1);
celltype=cells(:,4);
for i=1:ntype
    cell_counter(i)=sum(celltype==i);
end

end

function h = draw_cell_marker(cell1, setting, ha)
celltype=cell1(4);
setting=setting(celltype,:);
h=plot(cell1(1), cell1(2),'Marker', setting{2} ...
    ,'Color', setting{3} ...
    ,'MarkerSize', setting{4} ...
    ,'LineWidth', setting{5} ...
    ,'parent', ha(cell1(5)) );
end