function MaskMaker(varargin)
% Dr. A. I. Hanna (2005) CMP, UEA, 2005.
error(nargchk(0,inf,nargin));
if mod(length(varargin),2) ~= 0
    % input args have not com in pairs, woe is me
    error('Arguments to MaskMaker must come param/value in pairs.')
end
ad.data.template_dir = '';
ad.data.template_name = '';
ad.data.template = [];
ad.data.mask = [];
ad.data.boundary_filename = '';
ad.data.boundary_index  = {};
ad.data.curr_region = 0;
ad.data.curr_reg_ind = [];
ad.data.curr_reg_plot_h = [];

for i=1:2:length(varargin)
    switch lower(varargin{i})
        case 'template_filename'
            [ad.data.template_dir, ad.data.template_name] = fileparts(varargin{i+1});
        otherwise
            error(['Unknown parameter name passed to MaskMaker.  Name was ' varargin{i}])
    end
end
if isempty(ad.data.template_dir) || isempty(ad.data.template_dir)
    [ad.data.template, filename] = loadTemplate;
    [ad.data.template_dir, ad.data.template_name] = fileparts(filename);
else
    ad.data.template = loadTemplate('filename', [ad.data.template_dir, filesep, ad.data.template_name]);
end
if isempty(ad.data.template)
    return;
end

% Open, move, and get the handles from the figure file.
fig = openfig(mfilename, 'reuse');
customtoolbar(fig);
% Move the gui and then show it, rather than have it jump all over the
% place.
movegui(fig, 'center');
set(fig, 'visible', 'on');
handles = guihandles(fig);

% Set all the callback functions
set(handles.add_region_btn, 'callback', {@doAddRegion});
set(handles.regions_popup, 'callback', {@doChangeRegion});
set(handles.del_region_btn, 'callback', {@doDeleteRegion});
set(handles.save_boundary_menu, 'callback', {@doSaveBoundary});

% Initialize the application data structure
ad.figMain = fig;
ad.handles = handles;
setappdata(0,'MaskMakerData',ad);
init_gui();
try
    uiwait(fig);
catch
    if ishandle(fig)
        delete(fig)
    end
end
if isappdata(0,'MaskMakerData')
    ad = getappdata(0,'MaskMakerData');
    rmappdata(0,'MaskMakerData')
else
    % figure was deleted
end
return;
%%%
%
%%%
function init_gui()
ad = getappdata(0,'MaskMakerData');
ad.plot_handles.template = plotTemplate('Template', ad.data.template, 'Parent', ad.handles.template_axes);
ad.data.boundary_filename = [ad.data.template_dir, filesep, ad.data.template_name,'.boundary'];
ad.data.boundary_index = loadBoundaryIndex(ad.data.boundary_filename);
ad.plot_handles.boundary_pts_h = [];
setappdata(0,'MaskMakerData', ad);
updateRegionPopup();
updateRegionsPlot();
updateMaskPlot();
%%%
%
%%%
function ph = plotBoundaryPts(pts, axish)
edgecol = 'g';
facecol = 'g';
ph = plot(axish, ...
    pts(1, :), pts(2, :), 'o', 'MarkerEdgeCol',...
    edgecol, 'MarkerFaceCol', facecol);
return;
%%%
%
%%%
function doChangeRegion(popup, evd)
ad = getappdata(0,'MaskMakerData');
regions = ad.data.boundary_index;
if isempty(regions)
    fprintf(' - no regions to display\n');
    return;
end
ad.data.curr_region = get(popup, 'Value');
setappdata(0,'MaskMakerData', ad);
updateRegionsPlot();
return
%%%
%
%%%
function doDeleteRegion(add_btn, evd)
ad = getappdata(0,'MaskMakerData');
regions = ad.data.boundary_index;
if isempty(regions)
    fprintf(' - no regions to delete\n');
    return;
end
curr_reg = get(ad.handles.regions_popup, 'Value');
ad.data.boundary_index(curr_reg) = [];
setappdata(0,'MaskMakerData', ad);
updateRegionPopup();
updateRegionsPlot();
updateMaskPlot();
%%%
%
%%%
function doAddRegion(add_btn, evd)
ad = getappdata(0,'MaskMakerData');
fprintf(' - adding a new region\n');
set(ad.figMain, 'WindowButtonDownFcn', {@doStartDragSelect}, 'WindowButtonUpFcn', {@doFinishedDragSelect});
return;
%%%
%
%%%
function doStartDragSelect(add_btn, evd)
ad = getappdata(0,'MaskMakerData');
ad.data.curr_reg_ind = [];
ad.data.curr_reg_plot_h = [];
ad.data.proximity = str2double(get(ad.handles.proximity_txt, 'String'));
setappdata(0,'MaskMakerData', ad);
set(ad.figMain, 'WindowButtonMotionFcn', {@doMoveMouse});
%%%
%
%%%
function doFinishedDragSelect(add_btn, evd)
ad = getappdata(0,'MaskMakerData');
ad.data.boundary_index = cat(2, ad.data.boundary_index, ad.data.curr_reg_ind);
delete(ad.data.curr_reg_plot_h);
ad.data.curr_reg_ind = [];
ad.data.curr_reg_plot_h = [];
set(ad.figMain, 'WindowButtonDownFcn', '', 'WindowButtonUpFcn', '', 'WindowButtonMotionFcn', '');
setappdata(0,'MaskMakerData', ad);
updateRegionPopup();
set(ad.handles.regions_popup, 'Value', length(ad.data.boundary_index));
updateRegionsPlot();
updateMaskPlot();
%%%
%
%%%
function doMoveMouse(add_btn, evd)
ad = getappdata(0,'MaskMakerData');
pts = get(ad.data.template, 'pts');
currPt = get(ad.handles.template_axes, 'CurrentPoint');
currPt = currPt(1, 1:2)';
d = sqrt(sum((pts - repmat(currPt, [1, size(pts,2)])).^2,1));
[val, ind] = min(d);
if (val<ad.data.proximity ) && ~any(ad.data.curr_reg_ind==ind(1))
    ad.data.curr_reg_ind = cat(2, ad.data.curr_reg_ind, ind(1));
    ad.data.curr_reg_plot_h = cat(2, ad.data.curr_reg_plot_h, plot(ad.handles.template_axes, pts(1, ind(1)), pts(2, ind(1)), 'o', 'MarkerEdgeColor', 'm', 'MarkerFaceColor', 'c'));
end
setappdata(0,'MaskMakerData', ad);
%%%
%
%%%
function updateMaskPlot()
ad = getappdata(0,'MaskMakerData');
regions = ad.data.boundary_index;

I = get(ad.data.template, 'image');
pts = get(ad.data.template, 'pts');
mask = zeros(size(I,1), size(I,2));
if ~isempty(regions)
    for i=1:length(regions)
        rind = regions{i};
        rpts = pts(:, rind);
        b = roipoly(I, rpts(1,:), rpts(2,:));
        mask = mask | b;
    end
end
ad.data.mask = mask;
setappdata(0,'MaskMakerData', ad);
mask_h = showMask();
%%%
%
%%%
function doSaveBoundary(save_menu, evd)
ad = getappdata(0,'MaskMakerData');
boundary_index = ad.data.boundary_index;
if isempty(boundary_index)
    fprintf(' - no regions to save\n');
    return;
end
save(ad.data.boundary_filename, 'boundary_index');
uiwait(msgbox('Successuly saved your boundary mask','Save','modal'));
setappdata(0,'MaskMakerData', ad);
%%%
%
%%%
function updateRegionsPlot()
ad = getappdata(0,'MaskMakerData');
regions = ad.data.boundary_index;
if isempty(regions)
    delete(ad.plot_handles.boundary_pts_h);
    ad.plot_handles.boundary_pts_h = [];
    fprintf(' - no regions to display\n');
else
    curr_reg = get(ad.handles.regions_popup, 'Value');
    pts = get(ad.data.template, 'pts');
    rpts = pts(:, regions{curr_reg});
    delete(ad.plot_handles.boundary_pts_h);
    ad.plot_handles.boundary_pts_h = plotBoundaryPts(rpts, ad.handles.template_axes);
end
setappdata(0,'MaskMakerData', ad);
return;
%%%
%
%%%
function updateRegionPopup()
ad = getappdata(0,'MaskMakerData');
regions = ad.data.boundary_index;
if isempty(regions)
    set(ad.handles.regions_popup, 'String', '<Empty');
    set(ad.handles.regions_popup, 'Value', 1);
else
    curr_ind = get(ad.handles.regions_popup, 'Value');
    if curr_ind>length(regions)
        curr_ind = length(regions);
    end
    str = {};
    for i=1:length(regions)
        str = cat(1, str, sprintf('Region: %.3d', i));
    end
    set(ad.handles.regions_popup, 'String', str);
    set(ad.handles.regions_popup, 'Value', curr_ind);
end
setappdata(0,'MaskMakerData', ad);
return;
%%%
%
%%%
function ind = loadBoundaryIndex(filename)
ind = {};
if exist(filename, 'file')
    ind = load(filename, '-mat');
    ind = ind.boundary_index;
    if ~iscell(ind)
        ind = {};
    end
end
return
%%%
%
%%%
function mask_h = showMask()
ad = getappdata(0,'MaskMakerData');
if isempty(ad.data.mask)
    return;
end
mask_h = imagesc(ad.data.mask, 'Parent', ad.handles.mask_axes);
axis(ad.handles.mask_axes, 'image', 'ij');
colormap(ad.handles.mask_axes, 'gray');
return
%%%
%
%%%
function customtoolbar(figh)
hA = findall(figh);
openfileh=findobj(hA,'TooltipString','Open File');
%set(openfileh, 'ClickedCallback', {@doOpenGrid});
%set(openfileh, 'TooltipString', 'Open Grid File');
newgridh=findobj(hA,'TooltipString','New Figure');
%set(newgridh, 'ClickedCallback', {@doNewGrid});
%set(newgridh, 'TooltipString', 'New Grid');
saveh=findobj(hA,'TooltipString','Save Figure');
set(saveh, 'ClickedCallback', {@doSaveBoundary});
set(saveh, 'TooltipString', 'Save Boundary');
roth=findobj(hA,'TooltipString','Rotate 3D');
datah=findobj(hA,'TooltipString','Data Cursor');
colbarh=findobj(hA,'TooltipString','Insert Colorbar');
legh=findobj(hA,'TooltipString','Insert Legend');
hideh=findobj(hA,'TooltipString','Hide Plot Tools');
showh=findobj(hA,'TooltipString','Show Plot Tools and Dock Figure');
delete([newgridh, openfileh, datah, colbarh, legh, hideh, showh]); 
