function OrganizeAugmentedShapes(varargin)
%
%   Dr. A. I. Hanna (2006) CMP, UEA, 2006.
error(nargchk(0,inf,nargin));
ad.datadir = [pwd, filesep, 'Data'];
ad.augment_info_file = [ad.datadir, filesep, 'augment_info.mat'];
ad.seg_point_file = [ad.datadir, filesep, 'segmentpoint.mat'];
offsetfilename = [ad.datadir, filesep, 'offsetinfo.mat'];

ad.pdmfilename = [];
ad.selectedEdgeCol = 'r';
ad.selectedFaceCol = 'y';
ad.unselectedEdgeCol = 'b';
ad.unselectedFaceCol = 'w';
ad.unselectedLineCol = 'b';
ad.selectedLineCol = 'g';
ad.textcol = 'w';
ad.txtbgcol = 'k';

ad.currentShapeNum = 1;
ad.edges = [];
if ~exist(ad.augment_info_file)
    return;
end
if ~exist(ad.seg_point_file)
    return;
end

if mod(length(varargin),2) ~= 0
    % input args have not com in pairs, woe is me
    error('Arguments to OrganizeAugmentedShapes must come param/value in pairs.')
end
for i=1:2:length(varargin)
    switch lower(varargin{i})
        case 'pdmfilename'
            ad.pdmfilename = varargin{i+1};
        case 'edges'
            ad.edges = varargin{i+1};
        otherwise
            error(['Unknown parameter name passed to OrganizeAugmentedShapes.  Name was ' varargin{i}])
    end
end
if isempty(ad.pdmfilename) | ~exist(ad.pdmfilename)
    uiwait(msgbox(sprintf('You must have a valid pdm filename.'),'Error','modal'));
    error('ListString parameter is required.')
end
ad.pdm = load(ad.pdmfilename);
ad.pdm = ad.pdm.pdm;
% Open, move, and get the handles from the figure file.
fig = openfig(mfilename, 'reuse');
% 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(fig, 'Color', get(handles.shapes_panel, 'BackgroundColor'))
set(handles.shape_axis, 'Color', [0 0 0]);
% Set all the callback functions
set(handles.ok_btn, 'callback', {@doOk});
set(handles.shape_popup, 'callback', {@doSwitchShape});
set(fig, 'WindowButtonDownFcn', {@doAxisClicked});
set(handles.set_marker_face_color, 'callback', {@doSetMarkerFaceColor});
set(handles.set_marker_edge_color, 'callback', {@doSetMarkerEdgeColor});
set(handles.set_line_color, 'callback', {@doSetLineColor});
set(handles.update_axis_btn, 'callback', {@doUpdateAxisLimits});
set(handles.center_btn, 'callback', {@doCenterShapes});
set(handles.axis_tight_btn, 'callback', {@doTightAxis});


% Initialize the application data structure
ad.figMain = fig;
ad.handles = handles;
ad = load_augment_info(ad);
if exist(offsetfilename)
    ad.offset = load(offsetfilename);
    ad.offset = ad.offset.offset;
else
    ad.offset = zeros(length(ad.augInfo), 3);
end
ad = splitUpShapes(ad);
ad = plot_shapes(ad);
setappdata(0,'OrganizeAugmentedShapesData',ad);
doSwitchShape(ad.handles.shape_popup);

setAxisLimitsTxt;

try
    uiwait(fig);
catch
    if ishandle(fig)
        delete(fig)
    end
end
if isappdata(0,'OrganizeAugmentedShapesData')
    ad = getappdata(0,'OrganizeAugmentedShapesData');
    rmappdata(0,'OrganizeAugmentedShapesData')
else
    % figure was deleted
end
offsetfilename = [ad.datadir, filesep, 'offsetinfo.mat'];
offset = ad.offset;
save(offsetfilename, 'offset'); 
return;
%%%%%%
%
%
%%%%%%
function doOk(ok_btn, evd)
ad = getappdata(0,'OrganizeAugmentedShapesData');
delete(gcbf);
setappdata(0,'OrganizeAugmentedShapesData', ad);
%%%%%%
%
%
%%%%%%
function doMoveShape(shape_axis, evd)
cp = get(shape_axis, 'CurrentPoint');
cp = cp(1,1:2);
cp
%%%%%%
%
%
%%%%%%
function doSwitchShape(shape_popup, evd)
ad = getappdata(0,'OrganizeAugmentedShapesData');
shapenum = get(shape_popup, 'Value');
set(ad.shape_handles(ad.currentShapeNum), 'MarkerEdgeColor', ad.unselectedEdgeCol, 'MarkerFaceColor', ad.unselectedFaceCol);
edge_handles = ad.edge_handles{ad.currentShapeNum};
for i=1:length(edge_handles)
   set(edge_handles(i), 'Color', ad.unselectedLineCol);
end
ad.edge_handles{ad.currentShapeNum} = edge_handles;
ad.currentShapeNum = shapenum;
set(ad.shape_handles(ad.currentShapeNum), 'MarkerEdgeColor', ad.selectedEdgeCol,  'MarkerFaceColor', ad.selectedFaceCol);
edge_handles = ad.edge_handles{ad.currentShapeNum};
for i=1:length(edge_handles)
   set(edge_handles(i), 'Color', ad.selectedLineCol);
end
ad.edge_handles{ad.currentShapeNum} = edge_handles;
setappdata(0,'OrganizeAugmentedShapesData', ad);
%%%%%%
%
%
%%%%%%
function ad = load_augment_info(ad)
ad.augInfo = load(ad.augment_info_file);
ad.augInfo = ad.augInfo.augment_info;
ad.seg_points = load(ad.seg_point_file);
ad.seg_points = ad.seg_points.segmentpoint;
if length(ad.augInfo)==0
    fprintf('There are no shapes here');
    delete(ad.figMain);
end
str{1} = 'No shapes';
for i=1:length(ad.augInfo)
    str{i} = ['Shape ', num2str(i)];
end
set(ad.handles.shape_popup, 'String', str);
return;
%%%%%%
%
%
%%%%%%
function ad = plot_shapes(ad)
ad.shape_handles = [];
ad.shape_name_handle = [];
ad.edge_handles = {};
cla(ad.handles.shape_axis);
hold(ad.handles.shape_axis, 'on');
for i=1:length(ad.shapes)
    [prjdir, prjname, ext, vers] = fileparts(ad.augInfo(i).projectdir);
    pts = ad.shapes(i).pts;
    mu = mean(pts,2);
    edge_handles = plot_shape_edges(ad.shapes(i), ad.handles.shape_axis);
    ad.edge_handles{end+1} = edge_handles;
    ad.shape_handles(end+1) = plot(ad.handles.shape_axis, pts(1,:), pts(2,:), 'o', 'MarkerEdgeColor', ad.unselectedEdgeCol, 'MarkerFaceColor', ad.unselectedFaceCol);
    ad.shape_name_handle(end+1) = text(mu(1), mu(2), prjname, 'Color', ad.textcol, 'Interpreter', 'none', 'HorizontalAlignment', 'center', 'BackgroundColor', ad.txtbgcol);
end
hold(ad.handles.shape_axis, 'off');
axis(ad.handles.shape_axis, 'ij');
axis(ad.handles.shape_axis, [ad.xlim ad.ylim]);
return;

function edge_handles = plot_shape_edges(shape, axis_h)
hold(axis_h, 'on');
pts = shape.pts;
edges = shape.edges;
edge_handles = [];
for i=1:size(edges,1)
   p1 = pts(:, edges(i,1));
   p2 = pts(:, edges(i,2));
   edge_handles(end+1) = plot(axis_h, [p1(1) p2(1)], [p1(2) p2(2)], 'g');
end
%%%%%%
%
%
%%%%%%
function ad = splitUpShapes(ad)
Xm = ad.pdm.Xm;
Xm = reshape(Xm, 2, length(Xm)/2);
seg_pts = ad.seg_points;
seg_pts = [0; seg_pts; size(Xm,2)];
xlim = [0 0];
ylim = [0 0];
for i=1:length(seg_pts)-1
    pts = Xm(:, seg_pts(i)+1:seg_pts(i+1));
    edges = get(ad.augInfo(i).template,'loops');
    edges = edges{1};
    [pts] = trans_rot_points(pts, ad.offset(i,1:2)', ad.offset(i,3));
    if min(pts(1,:))<xlim(1); xlim(1) = min(pts(1,:))-10; end;
    if min(pts(2,:))<ylim(1); ylim(1) = min(pts(2,:))-10; end;
    if max(pts(1,:))>xlim(2); xlim(2) = max(pts(1,:))+10; end;
    if max(pts(2,:))>ylim(2); ylim(2) = max(pts(2,:))+10; end;
    shapes(i).pts = pts;
    shapes(i).edges = edges;
end
ad.shapes = shapes;
ad.xlim = xlim;
ad.ylim = ylim;
return;

%%%%%%%%%%%%%%%%%
% 
%%%%%%%%%%%%%%%%%
function doTightAxis(tight_axis_btn, evd)
ad = getappdata(0,'OrganizeAugmentedShapesData');
axis(ad.handles.shape_axis, 'tight');
setappdata(0,'OrganizeAugmentedShapesData', ad);
setAxisLimitsTxt();
%%%%%%%%%%%%%%%%%
% 
%%%%%%%%%%%%%%%%%
function doCenterShapes(center_btn, evd)
ad = getappdata(0,'OrganizeAugmentedShapesData');
for i=1:length(ad.shapes)
    ad.offset(i,1:2) = [0 0];
    pts = ad.shapes(i).pts;
    mu = mean(pts,2);
    pts = pts - mu*ones(1, size(pts, 2));
    edges = ad.shapes(i).edges;
    edge_handles = ad.edge_handles{i};
    for j=1:length(edge_handles)
        p1 = pts(:, edges(j,1));
        p2 = pts(:, edges(j,2));
        set(edge_handles(j), 'XData', [p1(1) p2(1)], 'YData', [p1(2) p2(2)]);
    end
    ad.edge_handles{ad.currentShapeNum} = edge_handles;
    ad.shapes(i).pts = pts;
end
setappdata(0,'OrganizeAugmentedShapesData', ad);
%%%%%%%%%%%%%%%%%
% 
%%%%%%%%%%%%%%%%%
function doUpdateAxisLimits(update_btn, evd)
ad = getappdata(0,'OrganizeAugmentedShapesData');
xlim(1) = str2num(get(ad.handles.x_min_txt, 'String'));
xlim(2) = str2num(get(ad.handles.x_max_txt, 'String'));
ylim(1) = str2num(get(ad.handles.y_min_txt, 'String'));
ylim(2) = str2num(get(ad.handles.y_max_txt, 'String'));
if (xlim(2)<=xlim(1)) | (ylim(2)<=ylim(1))
    fprintf('BAD AXIS COORDINATES, NAUGHTY');
    return;
else
    set(ad.handles.shape_axis, 'XLim', xlim, 'YLim', ylim);
    ad.xlim = xlim;
    ad.ylim = ylim;
end
setappdata(0,'OrganizeAugmentedShapesData', ad);
%%%%%%%%%%%%%%%%%
% 
%%%%%%%%%%%%%%%%%
function setAxisLimitsTxt()
ad = getappdata(0,'OrganizeAugmentedShapesData');
xlim = round(get(ad.handles.shape_axis, 'XLim'));
ylim = round(get(ad.handles.shape_axis, 'YLim'));
set(ad.handles.x_min_txt, 'String', num2str(xlim(1)));
set(ad.handles.x_max_txt, 'String', num2str(xlim(2)));
set(ad.handles.y_min_txt, 'String', num2str(ylim(1)));
set(ad.handles.y_max_txt, 'String', num2str(ylim(2)));
setappdata(0,'OrganizeAugmentedShapesData', ad);
%%%%%%%%%%%%%%%%%
% doAxisClicked
%%%%%%%%%%%%%%%%%
function doAxisClicked(axis_h, evd)
ad = getappdata(0,'OrganizeAugmentedShapesData');
movetype = get(ad.figMain,'SelectionType');
cp = get(ad.handles.shape_axis, 'CurrentPoint');
cp = cp(1,1:2);
ad.startPos = cp;
switch lower(movetype)
    case 'normal'
        set(ad.figMain, 'WindowButtonMotionFcn', {@doDrag});
    case 'alt'
        set(ad.figMain, 'WindowButtonMotionFcn', {@doRotate});
end
set(ad.figMain, 'WindowButtonUpFcn', {@doDropPoints});
setappdata(0,'OrganizeAugmentedShapesData',ad);
%%%%%%%%%%%%%%%%%
% doDrag
%%%%%%%%%%%%%%%%%
function doDrag(axis_h, evd)
ad = getappdata(0,'OrganizeAugmentedShapesData');
cp = get(ad.handles.shape_axis, 'CurrentPoint');
cp = cp(1,1:2);
d_pos = cp - ad.startPos;
ad.offset(ad.currentShapeNum,1:2) = ad.offset(ad.currentShapeNum,1:2) + d_pos;
ad.startPos = cp;
pts = ad.shapes(ad.currentShapeNum).pts;
pts = pts + d_pos'*ones(1, size(pts, 2));
set(ad.shape_handles(ad.currentShapeNum), 'XData', pts(1,:), 'YData', pts(2,:));
edges = ad.shapes(ad.currentShapeNum).edges;
edge_handles = ad.edge_handles{ad.currentShapeNum};
for i=1:length(edge_handles)
    p1 = pts(:, edges(i,1));
    p2 = pts(:, edges(i,2));
    set(edge_handles(i), 'XData', [p1(1) p2(1)], 'YData', [p1(2) p2(2)]);
end
ad.edge_handles{ad.currentShapeNum} = edge_handles;
ad.shapes(ad.currentShapeNum).pts = pts;
mu = mean(pts,2);
set(ad.shape_name_handle(ad.currentShapeNum), 'Position', [mu(1) mu(2) 0]);
setappdata(0,'OrganizeAugmentedShapesData',ad);
%%%%%%%%%%%%%%%%%
% doRotate
%%%%%%%%%%%%%%%%%
function doRotate(axis_h, evd)
ad = getappdata(0,'OrganizeAugmentedShapesData');
cp = get(ad.handles.shape_axis, 'CurrentPoint');
cp = cp(1,1:2);
dx = ad.startPos(1) - cp(1);
ad.startPos = cp;
if(dx > 0)
    theta = 0.05;
elseif(dx < 0)
    theta = -0.05;
else
    theta = 0;
end
ad.startPos = cp;
ad.offset(ad.currentShapeNum,3) = ad.offset(ad.currentShapeNum,3) + theta;
pts = ad.shapes(ad.currentShapeNum).pts;
m = mean(pts, 2)*ones(1, size(pts,2));
pts = pts - m;
R = [cos(theta) -sin(theta); sin(theta) cos(theta)];
pts = R*pts + m;
set(ad.shape_handles(ad.currentShapeNum), 'XData', pts(1,:), 'YData', pts(2,:));
ad.shapes(ad.currentShapeNum).pts = pts;
edges = ad.shapes(ad.currentShapeNum).edges;
edge_handles = ad.edge_handles{ad.currentShapeNum};
for i=1:length(edge_handles)
    p1 = pts(:, edges(i,1));
    p2 = pts(:, edges(i,2));
    set(edge_handles(i), 'XData', [p1(1) p2(1)], 'YData', [p1(2) p2(2)]);
end
ad.edge_handles{ad.currentShapeNum} = edge_handles;
setappdata(0,'OrganizeAugmentedShapesData',ad);
%%%%%%%%%%%%%%%%%
% doDropPoints
%%%%%%%%%%%%%%%%%
function doDropPoints(axis_h, evd)
ad = getappdata(0,'OrganizeAugmentedShapesData');
set(ad.figMain, 'WindowButtonMotionFcn', '');
set(ad.figMain, 'WindowButtonUpFcn', '');
setappdata(0,'OrganizeAugmentedShapesData',ad);
%%%%%%%%%%%%%%%%%
% doSetMarkerFaceColor
%%%%%%%%%%%%%%%%%
function doSetMarkerFaceColor(axis_h, evd)
ad = getappdata(0,'OrganizeAugmentedShapesData');
ad.selectedFaceCol = uisetcolor;
setappdata(0,'OrganizeAugmentedShapesData',ad);
doSwitchShape(ad.handles.shape_popup);
%%%%%%%%%%%%%%%%%
% doSetMarkerEdgeColor
%%%%%%%%%%%%%%%%%
function doSetMarkerEdgeColor(axis_h, evd)
ad = getappdata(0,'OrganizeAugmentedShapesData');
ad.selectedEdgeCol = uisetcolor;
setappdata(0,'OrganizeAugmentedShapesData',ad);
doSwitchShape(ad.handles.shape_popup);
%%%%%%%%%%%%%%%%%
% doSetLineColor
%%%%%%%%%%%%%%%%%
function doSetLineColor(axis_h, evd)
ad = getappdata(0,'OrganizeAugmentedShapesData');
ad.selectedLineCol = uisetcolor;
setappdata(0,'OrganizeAugmentedShapesData',ad);
doSwitchShape(ad.handles.shape_popup);
