%%%%%%%%%%%%%%%%%%%%%%%%%
%
% PlaceLandmarksSimple
%
% Uses the edge information of the binary image to place landmarks along
% the boundary
function [] = PlaceLandmarks(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;

if isa(arg, 'AAM')
    if exist('AAMShapemodel_figure_handle')
        if ishandle(AAMShapemodel_figure_handle)
            set(AAMShapemodel_figure_handle,'visible','off');
        end
    end
    PlaceLandmarks_gui_handle = openfig(mfilename, 'reuse');

    set(PlaceLandmarks_gui_handle, 'MenuBar', 'figure');
    Data.handles = guihandles(PlaceLandmarks_gui_handle);
    set(PlaceLandmarks_gui_handle, 'Color', get(Data.handles.uipanel3, 'BackgroundColor'));

    Data.handles.figMain = PlaceLandmarks_gui_handle;
    Data.handles.aam = arg;
    Data.handles.dat.npts = [];
    Data.handles.dat.landmarksegments = [];
    Data.handles = Init(Data.handles);
    Data.handles.dat.points_plot_handle = [];
    guidata(PlaceLandmarks_gui_handle, Data);
else
    Data = guidata(PlaceLandmarks_gui_handle);
    switch arg
        case 'ClickPrimaries'
            [Data.handles] = ClickPrimaries(Data.handles);
        case 'Next'
            [Data.handles] = Next(Data.handles);
        case 'KeyboardInput'
            [Data.handles] = KeyboardInput(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(PlaceLandmarks_gui_handle, Data);
    end
end
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
%  Quit
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function [handles] = Quit(handles)
delete(handles.figMain);
handles = rmfield(handles, 'figMain');
return;
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
%  KeyboardInput
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function [handles] = KeyboardInput(handles)
c = get(handles.figMain, 'CurrentCharacter');
switch lower(c)
    case 'n'
        handles = Next(handles);
    case 'h'
        handles = ClickPrimaries(handles);
end
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
handles.dat.edge_filename = [handles.dat.directoryname, filesep,'Binary', filesep, 'edge_', filename, '.edge_dat'];
if exist(handles.dat.edge_filename)
    handles.dat.edge = load(handles.dat.edge_filename, '-mat');
    se = handles.dat.edge.sorted_edge;
    if iscell(se)
        for i=1:length(se)
            handles.dat.pts{i} = double(se{i})';
            handles.dat.pts{i} = flipud(handles.dat.pts{i});
        end
    else

        handles.dat.pts{1} = double(handles.dat.edge.sorted_edge)';
        handles.dat.pts{1} = flipud(handles.dat.pts{1});
    end
    handles.dat.numsegments = length(handles.dat.pts);
end

[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);
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
%  GetTemplateSegments
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function [handles] = GetTemplateSegments(handles)
if isempty(handles.dat.landmarksegments)
    pts = handles.dat.npts;
    figh = figure;
    set(figh, 'Name', 'Please select each element of the image');
    I = get(handles.PMT, 'image');
    pts = get(handles.PMT, 'pts');
    imagesc(I); hold on;
    plot(pts(1,:), pts(2,:), 'o', 'markerEdgeColor', 'r', 'markerFaceColor', 'y');
    axis image ij;
    if isfield(handles.dat, 'numsegments')
        for i=1:handles.dat.numsegments
            [bw, las_x, las_y] = roipoly;
            in=inpolygon(pts(1,:),pts(2,:),las_x,las_y);
            ev_in=find(in>0);
            handles.dat.landmarksegments{i} = ev_in;
        end
    else
        handles.dat.numsegments = 1;
        handles.dat.landmarksegments{1} = 1:size(pts,2);
    end
    close(figh);
end
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
%  Update Image
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function [handles] = UpdateImage(handles,exterior_flag)
if nargin<2
    exterior_flag=0;
end
cla(handles.targetAxis);
npts = handles.dat.npts;
temp_pri = sort(get(handles.PMT, 'primaries'));

imagesc(handles.dat.CurrentImage, 'HitTest', 'off', 'Parent', handles.targetAxis);
axis(handles.targetAxis, 'image', 'ij');
hold(handles.targetAxis, 'on');

%     temp_pri = temp_pri(1:end-1);
%
handles.dat.points_plot_handle = [];
if size(npts,1)>0
    if exterior_flag==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'];
    else
        ext_pri=handles.dat.exterior_primary_points;
        handles.dat.points_plot_handle(end+1) = plot(handles.targetAxis, npts(1,ext_pri), npts(2,ext_pri), 'o', 'MarkerFaceColor', 'g', 'MarkerEdgeColor', 'b');
    end
end
%%%%
%
%%%%
function [handles] = ClickPrimaries(handles)

temp_pts = get(handles.PMT, 'pts');
temp_pri = get(handles.PMT, 'primaries'); %sort(get(handles.PMT, 'primaries'));
edges = get(handles.PMT, 'loops');
edges = edges{1};


temp_orig_pts = temp_pts;
temp_orig_pri = temp_pri;
npts = zeros(size(temp_pts));
middle_pts = temp_pts(:, handles.dat.interior_points);
exterior_index = setdiff(1:size(temp_pts,2), handles.dat.interior_points);
temp_pts(:, handles.dat.interior_points) = [];
middle_pri = intersect(temp_pri, handles.dat.interior_points);

for S=1:handles.dat.numsegments
    cla(handles.targetAxis); hold(handles.targetAxis, 'on');
    imageh=imagesc(handles.dat.CurrentImage, 'Parent', handles.targetAxis, 'HitTest', 'off');
    axis(handles.targetAxis, 'image', 'ij');
    temp_pri = intersect(temp_orig_pri, handles.dat.landmarksegments{S});
    perim_pts = handles.dat.pts{S};
    if(size(perim_pts,1)>2)
        return;
    end
    X = [];
    Y = [];
    for i=1:length(temp_pri)
        title(sprintf('Select point %d',temp_pri(i)))
        [x, y] = ginput(1);
        X(end+1) = x;
        Y(end+1) = y;
        plot(handles.targetAxis, X, Y, 'o', 'MarkerFaceColor', 'g', 'MarkerEdgeColor', 'b');
    end
    set(imageh,'visible','off'); %cla(handles.targetAxis);
    hold on
    plot(perim_pts(1,:), perim_pts(2,:), '.r'); hold on;
    plot(X, Y, 'go');
    axis(handles.targetAxis, 'image');
    %[X,Y] = ginput(length(temp_pri));
    distances = sqrt((perim_pts(1,:) - X(1)).^2 + (perim_pts(2,:) - Y(1)).^2);
    dist = find(distances == min(distances));
    dist = dist(1);

    perim_pts = [perim_pts(:, dist:end), perim_pts(:, 1:dist-1)];
    for p = 1:length(X)
        distances = sqrt((perim_pts(1,:) - X(p)).^2 + (perim_pts(2,:) - Y(p)).^2);
        dist(p) = find(distances == min(distances));
    end
    hold on
    plot(perim_pts(1,dist),perim_pts(2,dist),'*b');
    hold off
    axis(handles.targetAxis, 'image');
    if length(dist)>2
        if dist(3) < dist(2)
            perim_pts = fliplr(perim_pts);
            distances = sqrt((perim_pts(1,:) - X(1)).^2 + (perim_pts(2,:) - Y(1)).^2);
            dist = find(distances == min(distances));
            perim_pts = [perim_pts(:, dist:end), perim_pts(:, 1:dist-1)];
        end
    end
    hold on
    plot(perim_pts(1,dist),perim_pts(2,dist),'*y');
    hold off
    axis(handles.targetAxis, 'image');
    for p = 1:length(X)
        distances = sqrt((perim_pts(1,:) - X(p)).^2 + (perim_pts(2,:) - Y(p)).^2);
        dist(p) = find(distances == min(distances));
    end
    hold on
    plot(perim_pts(1,dist),perim_pts(2,dist),'*k');
    hold off
    num_points = size(temp_pts, 2);
    npts(:, temp_pri) = perim_pts(:, dist);
    dist = [dist, size(perim_pts, 2)];
    landmarkpts = handles.dat.landmarksegments{S};

    temp_pri = [temp_pri(:); landmarkpts(end)+1];
    for i=2:length(dist)
        side_pts  = temp_pri(i) - temp_pri(i-1)-1;
        e1 = dist(i-1); e2 = dist(i);
        ind = round((e2-e1)/(side_pts+1));
        ptstemp = dist(i-1)+ind:ind:dist(i-1)+side_pts*ind;
        npts(:, temp_pri(i-1)+1:temp_pri(i)-1) = perim_pts(:, ptstemp);
    end
end
%pts = zeros(size(temp_orig_pts));
%pts(:, exterior_index) = npts;
pts = npts;

pts(:, handles.dat.interior_points) = temp_orig_pts(:, handles.dat.interior_points);

% middle_pts = middle_pts - mean(temp_orig_pts ,2)*ones(1, size(middle_pts,2));
% middle_pts = middle_pts + mean(npts,2)*ones(1, size(middle_pts,2));
% pts(:, handles.dat.interior_points) = middle_pts;

a = temp_orig_pts(:, handles.dat.interior_points);
b = pts(:, exterior_index);
c = temp_orig_pts(:, exterior_index);

if ~isempty(a)
    [wpts] = TPS_pts_warp(a',c',b');
   
    pts(:, handles.dat.interior_points) = wpts';
end
pts = pts';
[pts]= smooth_secondary_landmarks(pts,temp_pri,edges, 5);
pts = pts';
npts = 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.dat.npts = npts;
[handles] = UpdateImage(handles);
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% Init
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function [handles] = Init(handles)
if isfield(handles,'aam')
    handles.PMT=get(handles.aam,'PointModelTemplate');
    % only get interior points if there is no file or field in the template
    modelDirec=get(handles.aam,'modelDirec');
    templatename=modelDirec(findstr(modelDirec,'StatisticalModels')+length('StatisticalModels')+1:end);
    templatename=templatename(1:findstr(templatename,'Set_')-2);
    %if ~exist(fullfile('Templates',[templatename,'.interior']))
        [handles.dat.interior_points, handles.dat.exterior_primary_points]= GetInteriorPoints(handles.PMT);
        intdata.interior_points=handles.dat.interior_points;
        intdata.exterior_primary_points=handles.dat.exterior_primary_points;
        save(fullfile('Templates',[templatename,'.interior']),'intdata');
    %else
    %    temp=load(fullfile('Templates',[templatename,'.interior']),'-mat');
    %    handles.dat.interior_points=temp.intdata.interior_points;
    %    handles.dat.exterior_primary_points=temp.intdata.exterior_primary_points;
    %end
else
    [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.interior_points = GetInteriorPoints(handles.PMT)
        set(handles.figMain, 'Visible', 'on');
    end
end
temp_pts = get(handles.PMT, 'pts');
temp_pri = sort (handles.dat.exterior_primary_points);% sort(get(handles.PMT, 'primaries'));
if (length(temp_pri)<1)
    error('Need at least 1 primary point to determine direction of flow');
    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.dat.X=[];
    handles.dat.Y=[];
    [handles] = GetTemplateSegments(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');
ind2=setdiff(temp_pri,handles.dat.interior_points);
plot(handles.templateAxis, temp_pts(1,ind2), temp_pts(2,ind2), 'o', 'MarkerFaceColor', 'g', 'MarkerEdgeColor', 'b');
%  for i=1:length(ind2)
%      text(temp_pts(1,ind2(i)), temp_pts(2,ind2(i)),sprintf('%3d',ind2(i)),'color','y','parent',handles.templateAxis);
%  end
title('Numbers show order to click primary points')
%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)))};
t=text(temp_pts(1,:), temp_pts(2,:), s, 'parent', handles.templateAxis, 'Color', 'w');
set(t(handles.dat.interior_points),'color','m');
% set(t(ind2),'color','g');
set(handles.figMain, 'Visible', 'on');

return;
