%%%%%%%%%%%%%%%%%%%%%%%%%
%
% PlaceLandmarksSimple
%
% Uses the edge information of the binary image to place landmarks along
% the boundary
function [] = ProjectiveOptimisationPlace(arg)
global AAMShapemodel_figure_handle
global AAMModelGenerator_handle
global AAMModelBuilder_handle
global AAMSetPicker_handle
global UpdateModel_handle
global PMTemplateBuilder_handle
global PDMWalk_handle
global ShapeSpaceTool_handle
global PreProcess_gui_handle;
global PlaceLandmarks_gui_handle;
global ProjectiveOptimisationPlace_gui_handle;

if isa(arg, 'AAM')
    if exist('AAMShapemodel_figure_handle')
        if ishandle(AAMShapemodel_figure_handle)
            set(AAMShapemodel_figure_handle,'visible','off');
        end
    end
    ProjectiveOptimisationPlace_gui_handle = openfig(mfilename, 'reuse');
    set(ProjectiveOptimisationPlace_gui_handle, 'MenuBar', 'figure');
    Data.handles = guihandles(ProjectiveOptimisationPlace_gui_handle);
    Data.handles.figMain = ProjectiveOptimisationPlace_gui_handle;
    Data.handles.aam = arg;
    Data.handles.dat.npts = [];
    Data.handles.dat.points_plot_handle = [];
    Data.handles.dat.marker_points = [];
    Data.handles = Init(Data.handles);
    if length(Data.handles.dat.marker_points)<4
        if exist('AAMShapemodel_figure_handle')
            if ishandle(AAMShapemodel_figure_handle)
                set(AAMShapemodel_figure_handle,'visible','on');
            end
        end
        [Data.handles] = Quit(Data.handles);
        return;
    else
         set(ProjectiveOptimisationPlace_gui_handle, 'visible','on');
    end
    Data.handles.dat.points_plot_handle = [];
    guidata(ProjectiveOptimisationPlace_gui_handle, Data);
else
    Data = guidata(ProjectiveOptimisationPlace_gui_handle);
    switch arg
        case 'AddMarkerPoint'
            [Data.handles] = AddMarkerPoint(Data.handles);

        case 'ToggleMarker'
            [Data.handles] = ToggleMarker(Data.handles);
        case 'MoveMarker'
            [Data.handles] = MoveMarker(Data.handles);
                    case 'SelectMarker'
            [Data.handles] = SelectMarker(Data.handles);
        case 'MoveMarkerPoint'
            [Data.handles] = MoveMarkerPoint(Data.handles);
        case 'DropPoint'
            [Data.handles] = DropPoint(Data.handles);
        case 'ClickPrimaries'
            [Data.handles] = ClickPrimaries(Data.handles);
        case 'Next'
            [Data.handles] = Next(Data.handles);
        case 'Skip'
            [Data.handles] = Skip(Data.handles);
        case 'Prev'
            [Data.handles] = Prev(Data.handles);
        case 'Quit'
            if exist('AAMShapemodel_figure_handle')
                if ishandle(AAMShapemodel_figure_handle)
                    set(AAMShapemodel_figure_handle,'visible','on');
                end
            end
            [Data.handles] = Quit(Data.handles);
        otherwise
            disp('Unknown option');
    end
    if isfield(Data.handles, 'figMain')
        guidata(ProjectiveOptimisationPlace_gui_handle, Data);
    end
end
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
%  DropPoint
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function [handles] = DropPoint(handles)
set(handles.figMain, 'WindowButtonMotionFcn' ,'','WindowButtonUpFcn','');

temp_pts = get(handles.PMT, 'pts');
X = handles.dat.npts(1, handles.dat.marker_points);
Y = handles.dat.npts(2, handles.dat.marker_points);
temp_pri = handles.dat.marker_points;
pts = ProjectiveOptimisationFit([temp_pts(1,:)', temp_pts(2,:)'], [X', Y'], temp_pri);
pts = TPS_pts_warp([temp_pts(1,:)', temp_pts(2,:)'], temp_pts(:,temp_pri)', [X', Y']);

handles.dat.npts = pts';
handles.dat.npts(1,handles.dat.marker_points) = X;
handles.dat.npts(2,handles.dat.marker_points) = Y;

% pts = pts';
% pts = pts(:);
% [path, templatename, ext, vers] = fileparts(get(handles.PMT, 'name'));
% [path, filename, ext, vers] = fileparts(handles.dat.CurrentImageName);
% save(['PointModels', filesep, templatename, filesep, filename, '_pm.mat'], 'pts');
[handles] = UpdateImage(handles);
set(handles.figMain, 'Pointer', 'arrow');

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
%  AddMarkerPoint
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function [handles] = AddMarkerPoint(handles)
switch(get(handles.AddMarkerPointBtn, 'Value'))
    case 0
        set(handles.figMain, 'Pointer', 'Arrow');
        set(handles.figMain, 'WindowButtonDownFcn', '', 'WindowButtonMotionFcn' , '', 'WindowButtonUpFcn', '', 'BackingStore','on');
    case 1
        set(handles.figMain, 'Pointer', 'crosshair');
        % First initialise button click function
        set(handles.figMain, 'BackingStore', 'off', 'WindowButtonDownFcn', [mfilename, ' ToggleMarker']);
end
return;
%%%%%%%%%%%%%%%%%%%%%%
%
%
%  Point Select
%
%%%%%%%%%%%%%%%%%%%%%%
function [handles] = ToggleMarker(handles)
CurrentPoint = get(handles.targetAxis, 'CurrentPoint');
ce_pts = handles.dat.npts;
distances = sqrt((ce_pts(1,:) - CurrentPoint(1,1)).^2 + (ce_pts(2,:) - CurrentPoint(1,2)).^2);
chosenPt = find(distances == min(distances));
ind = find(handles.dat.marker_points == chosenPt);
if any(ind)
    handles.dat.marker_points(ind) = [];
else
    handles.dat.marker_points = [handles.dat.marker_points; chosenPt];
end
handles = UpdateImage(handles);
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
%  MoveMarkerPoint
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function [handles] = MoveMarkerPoint(handles)
switch(get(handles.MoveMarkerPointBtn, 'Value'))
    case 0
        set(handles.figMain, 'Pointer', 'Arrow');
        set(handles.figMain, 'WindowButtonDownFcn', '', 'WindowButtonMotionFcn' , '', 'WindowButtonUpFcn', '', 'BackingStore','on');
    case 1
        set(handles.figMain, 'Pointer', 'crosshair');
        % First initialise button click function
        set(handles.figMain, 'BackingStore', 'off', 'WindowButtonDownFcn', [mfilename, ' SelectMarker']);
end
return;
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
%  SelectMarker
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function [handles] = SelectMarker(handles)
CurrentPoint = get(handles.targetAxis, 'CurrentPoint');
ce_pts = handles.dat.npts;
distances = sqrt((ce_pts(1,:) - CurrentPoint(1,1)).^2 + (ce_pts(2,:) - CurrentPoint(1,2)).^2);
handles.dat.PointToMove = find(distances == min(distances));
set(handles.figMain, 'WindowButtonMotionFcn', 	[mfilename, ' MoveMarker'], 'WindowButtonUpFcn', [mfilename, ' DropPoint']);
%%%%%%%%%%%%%%%%%%%%%%
%
%
% MoveMarker
%
%%%%%%%%%%%%%%%%%%%%%%
function [handles] = MoveMarker(handles)
% Moving the selected point
CurrentPoint = get(handles.targetAxis, 'CurrentPoint');
ce_pts = handles.dat.npts;
ce_pts(1,handles.dat.PointToMove) = CurrentPoint(1,1);
ce_pts(2,handles.dat.PointToMove) = CurrentPoint(1,2);
handles.dat.npts = ce_pts;
handles = UpdateImage(handles);

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
%  Quit
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function [handles] = Quit(handles)
delete(handles.figMain);
handles = rmfield(handles, 'figMain');
return;
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
%  Next
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function [handles] = Next(handles)
N = length(handles.dat.files);
v = get(handles.filenameList, 'value');
if (v < N)
    v = v +1;
    handles.dat.currentIndex =   handles.dat.currentIndex + 1;
else
    v = N;
end
set(handles.filenameList, 'value', v);
handles = Skip(handles);

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
%  Prev
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function [handles] = Prev(handles)
N = length(handles.dat.files);
v = get(handles.filenameList, 'value');
if (v > 1)
    v = v -1;
    handles.dat.currentIndex =   handles.dat.currentIndex + 1;
else
    v = 1;
end
set(handles.filenameList, 'value', v);
handles = Skip(handles);
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
%  Skip
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function [handles] = Skip(handles)

handles.dat.npts = [];
handles.dat.currentIndex = get(handles.filenameList, 'value');
I = imread([handles.dat.directoryname, filesep,handles.dat.files{handles.dat.currentIndex}]);
I = double(I);
handles.dat.CurrentImage = I./max(I(:));
handles.dat.CurrentImageName = handles.dat.files{handles.dat.currentIndex};
handles.dat.CurrentImageDir = handles.dat.directoryname;
[path, filename, ext, vers] = fileparts(handles.dat.CurrentImageName);
handles.dat.CurrentImageName
[path, templatename, ext, vers] = fileparts(get(handles.PMT, 'name'));
if exist(['PointModels', filesep, templatename, filesep, filename, '_pm.mat'])
    pts = load(['PointModels', filesep, templatename, filesep, filename, '_pm.mat']);
    pts = pts.pts;
    pts = reshape(pts, 2, length(pts)/2);
    handles.dat.npts = pts;
end
handles = UpdateImage(handles);
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
%  Update Image
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function [handles] = UpdateImage(handles)

cla(handles.targetAxis);
npts = handles.dat.npts;
temp_pri = sort(get(handles.PMT, 'primaries'));
temp_pri =  handles.dat.marker_points;
imagesc(handles.dat.CurrentImage, 'Parent', handles.targetAxis, 'HitTest', 'off');
axis(handles.targetAxis, 'image');
hold(handles.targetAxis, 'on');

%     temp_pri = temp_pri(1:end-1);
%
handles.dat.points_plot_handle = [];
if size(npts,1)>0
    handles.dat.points_plot_handle(end+1) = plot(handles.targetAxis, npts(1,:), npts(2,:), 'o', 'MarkerFaceColor', 'y', 'MarkerEdgeColor', 'b');
    handles.dat.points_plot_handle(end+1) = plot(handles.targetAxis, npts(1,temp_pri), npts(2,temp_pri), 'o', 'MarkerFaceColor', 'g', 'MarkerEdgeColor', 'b');

    s = {num2str(transpose(1:size(npts,2)))};

    text_h =  text(npts(1,:), npts(2,:), s, 'parent', handles.targetAxis, 'Color', 'w');
    handles.dat.points_plot_handle = [handles.dat.points_plot_handle, text_h'];
end
%     drawnow;
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% ClickPrimaries
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function [handles] = ClickPrimaries(handles)
set(handles.figMain, 'Pointer', 'cross');
cla(handles.targetAxis);
imagesc(handles.dat.CurrentImage, 'Parent', handles.targetAxis, 'HitTest', 'off');
axis(handles.targetAxis, 'image');
temp_pts = get(handles.PMT, 'pts');
temp_pri = sort(get(handles.PMT, 'primaries'));
% pts = handles.dat.pts;
% if(size(pts,1)>2)
%     return;
% end
temp_pri = handles.dat.marker_points;
X = [];
Y = [];
for i=1:length(temp_pri)
    cla(handles.templateAxis);
    imagesc(get(handles.PMT, 'image'), 'parent', handles.templateAxis);
    axis(handles.templateAxis, 'image');
    hold(handles.templateAxis, 'on');
    plot(handles.templateAxis, temp_pts(1,temp_pri(i)), temp_pts(2,temp_pri(i)), 'o', 'MarkerFaceColor', 'y', 'MarkerEdgeColor', 'b');
    [x, y] = ginput(1);
    X(end+1) = x;
    Y(end+1) = y;
    plot(handles.targetAxis, X, Y, 'o', 'MarkerFaceColor', 'g', 'MarkerEdgeColor', 'b');
end
cla(handles.templateAxis);
imagesc(get(handles.PMT, 'image'), 'parent', handles.templateAxis);
axis(handles.templateAxis, 'image');
hold(handles.templateAxis, 'on');
plot(handles.templateAxis, temp_pts(1,:), temp_pts(2,:), 'o', 'MarkerFaceColor', 'y', 'MarkerEdgeColor', 'b');
plot(handles.templateAxis, temp_pts(1,temp_pri), temp_pts(2,temp_pri), 'o', 'MarkerFaceColor', 'g', 'MarkerEdgeColor', 'b');
s = {num2str(transpose(1:size(temp_pts,2)))};
text(temp_pts(1,:), temp_pts(2,:), s, 'parent', handles.templateAxis, 'Color', 'w');
cla(handles.targetAxis);
plot(X, Y, 'yo');
pts = ProjectiveOptimisationFit([temp_pts(1,:)', temp_pts(2,:)'], [X', Y'], temp_pri);
pts = TPS_pts_warp([temp_pts(1,:)', temp_pts(2,:)'], temp_pts(:,temp_pri)', [X', Y']);

handles.dat.npts = pts';
pts = pts';
pts = pts(:);
[path, templatename, ext, vers] = fileparts(get(handles.PMT, 'name'));
[path, filename, ext, vers] = fileparts(handles.dat.CurrentImageName);
save(['PointModels', filesep, templatename, filesep, filename, '_pm.mat'], 'pts');
[handles] = UpdateImage(handles);
set(handles.figMain, 'Pointer', 'arrow');

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% Init
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function [handles] = Init(handles)
[filename, pathname] = uigetfile('*.temp_dat', 'Pick Template File');
if isequal(filename,0) | isequal(pathname,0)
    disp('User pressed cancel')
    handles.PMT = PointModelTemplate;
    return;
else
    PMT = load([pathname, filesep, filename], '-mat');
    handles.PMT = PMT.PMTemplate;
    disp(['User selected ', fullfile(pathname, filename)])
    handles.dat.marker_points = GetMarkerPoints(handles.PMT)
end
temp_pts = get(handles.PMT, 'pts');
temp_pri = sort(get(handles.PMT, 'primaries'));
temp_pri =  handles.dat.marker_points;
if (length(temp_pri)<4)
    fprintf('Need at least 4 marker points to fit points\n');
    return;
end
handles.dat.directoryname = 'Cropped';
if ~exist(handles.dat.directoryname, 'dir')
    uiwait(warndlg('Cannot find the ''Cropped'' directory, exiting.'));
    return;
end
handles.dat.files = dir([handles.dat.directoryname, filesep, '*.jpg']);
handles.dat.files = {handles.dat.files.name};
if length(handles.dat.files)>0
    set(handles.filenameList, 'String', handles.dat.files);
    set(handles.filenameList, 'value', 1);
    handles.dat.currentIndex = 1;
    handles = Skip(handles);
    handles = UpdateImage(handles);
else
    set(handles.filenameList, 'String', 'No images');
    set(handles.filenameList, 'value', 1);
    handles.dat.currentIndex = 1;
end
% Now we must plot the template and its points with labels
handles.N = size(temp_pts,2);
[path, templatename, ext, vers] = fileparts(get(handles.PMT, 'name'));
if ~exist(['PointModels', filesep, templatename], 'dir')
    mkdir(['PointModels', filesep, templatename]);
end
imagesc(get(handles.PMT, 'image'), 'parent', handles.templateAxis);
axis(handles.templateAxis, 'image');
hold(handles.templateAxis, 'on');
plot(handles.templateAxis, temp_pts(1,:), temp_pts(2,:), 'o', 'MarkerFaceColor', 'y', 'MarkerEdgeColor', 'b');
plot(handles.templateAxis, temp_pts(1,temp_pri), temp_pts(2,temp_pri), 'o', 'MarkerFaceColor', 'g', 'MarkerEdgeColor', 'b');
s = {num2str(transpose(1:size(temp_pts,2)))};
text(temp_pts(1,:), temp_pts(2,:), s, 'parent', handles.templateAxis, 'Color', 'w');
return;
