function UpdateModel(arg,optionalextra)
global AAMShapemodel_figure_handle
global AAMModelGenerator_handle
global AAMModelBuilder_handle
global AAMSetPicker_handle
global UpdateModel_handle
if nargin<2
    optionalextra=[];
end

if strcmp(class(arg), 'AAM')
    %close all;
    % Open the GUI for display
    fig = openfig(mfilename, 'reuse');
    % Generate a structure of handles to pass to callbacks, and store
    Data.handles = guihandles(fig);
    Data.handles.figMain = fig;
    UpdateModel_handle=fig;
    Data.handles.dat.plotH = [];
    Data.handles.dat.currentLoopNumber = 0;
    Data.handles.dat.currentLoop = [];
    Data.handles.AAM = arg;
    Data.handles.AAM = set(Data.handles.AAM ,'pointindices',optionalextra);
    set(Data.handles.txtCurrentStatus, 'ForegroundColor', 'blue','String', 'Please Choose an Operation');
    %DataMain = guidata(findobj('Tag', 'ModelBuilder'));
    Data.handles.PointModelTemplate = get(Data.handles.AAM, 'PointModelTemplate');
    %    Data.handles.dat.rootDirectory = DataMain.handles.dat.rootDirectory;
    if ~isempty(get(Data.handles.PointModelTemplate, 'image'))
        set(Data.handles.mainAxes, 'Visible', 'off');
        axes(Data.handles.mainAxes);
        cla(Data.handles.mainAxes);
        imagesc(get(Data.handles.PointModelTemplate, 'image'), 'HitTest', 'off', 'Parent', Data.handles.mainAxes); axis(Data.handles.mainAxes,  'image', 'ij');
        Data.handles.dat.plotH = PlotTemplate(Data.handles.mainAxes, Data.handles.PointModelTemplate, Data.handles, Data.handles.dat.plotH);
        Data.handles.workingDir = get(Data.handles.PointModelTemplate, 'direc');
        set(Data.handles.closedChk, 'value', 0);
        set(Data.handles.imageDirTxt, 'String', cut_string(get(Data.handles.PointModelTemplate, 'imageDir')));
        set(Data.handles.imageNameTxt, 'String', get(Data.handles.PointModelTemplate, 'imageName'));
        set(Data.handles.templateDirTxt, 'String', cut_string(get(Data.handles.PointModelTemplate, 'direc')));
        set(Data.handles.templateNameTxt, 'String', get(Data.handles.PointModelTemplate, 'name'));
    end
    guidata(fig, Data);
    %     uiwait(Data.handles.figMain);
    %     delete(Data.handles.figMain);
    return;
else
    Data = guidata(gcbo);

    switch arg
        case 'InterpolatePoints'
            [Data.handles] = InterpolatePoints(Data.handles);
        case 'ToggleLabeling'
            Data.handles.dat.plotH = PlotTemplate(Data.handles.mainAxes, Data.handles.PointModelTemplate, Data.handles, Data.handles.dat.plotH);
        case 'ToggleLandmarks'
            Data.handles.dat.plotH = PlotTemplate(Data.handles.mainAxes, Data.handles.PointModelTemplate, Data.handles, Data.handles.dat.plotH);
        case 'ToggleLines'
            Data.handles.dat.plotH = PlotTemplate(Data.handles.mainAxes, Data.handles.PointModelTemplate, Data.handles, Data.handles.dat.plotH);
        case 'SaveModel'
            [Data.handles] = SaveModel(Data.handles);
        case 'LoadTemplate'
            [Data.handles] = LoadTemplate(Data.handles);
        case 'SmoothLandmarks'
            Data.handles = SmoothLandmarks(Data.handles);
        case 'BrightenImage'
            brighten(Data.handles.figMain, .5);
        case 'SelectTemplateImage'
            Data.handles = SelectTemplateImage(Data.handles);
        case 'AddPointToLoop'
            Data.handles = AddPointToLoop(Data.handles);
        case 'AddLoopPoint'
            Data.handles = AddLoopPoint(Data.handles);
        case 'CloseLoop'
            Data.handles = CloseLoop(Data.handles);
        case 'UpdateLoop'
            Data.handles = UpdateLoop(Data.handles);
        case 'NewLoop'
            Data.handles = NewLoop(Data.handles);
        case 'InsertPoint'
            Data.handles = InsertPoint(Data.handles);
        case 'DeletePoints'
            Data.handles = DeletePoints(Data.handles);
        case 'DeletePoint'
            Data.handles = DeletePoint(Data.handles);
        case 'DefinePrimaries'
            Data.handles = DefinePrimaries(Data.handles);
        case 'TogglePrimary'
            Data.handles = TogglePrimary(Data.handles);
        case 'MoveMode'
            Data.handles = MoveMode(Data.handles);
        case 'PointSelect'
            Data.handles = PointSelect(Data.handles);
        case 'MovePoint'
            % Moving the selected point
            Data.handles = MovePoint(Data.handles);
        case 'DropPoint'
            set(Data.handles.figMain, 'WindowButtonMotionFcn' ,'','WindowButtonUpFcn','');
            Data.dat.PointToMove = [];
        case 'MovePointKeyPress'
            set(Data.handles.figMain, 'WindowButtonMotionFcn' ,'','WindowButtonUpFcn','');
            set(Data.handles.movePointBtn, 'Value', 0);
            % Recall the move point function to enable the gui controls
            eval(sprintf('%s MoveMode', mfilename));
        case 'ToggleZoom'
            Data.handles = ToggleZoom(Data.handles);
        case 'TogglePan'
            Data.handles = TogglePan(Data.handles);
        case 'Done'
            answer = questdlg('Do you want to save your model before quitting?');
            guidata(Data.handles.figMain, Data);
            
            % here we should do something to create a new set
            %function UpdateModelSaveNewSet(templatename,ext,dirProject)

            switch answer
                case 'Yes'
                    Data.handles = SaveModel(Data.handles);
                    %uiresume
                    %return
                case 'No'
                    aam = load([get(Data.handles.AAM, 'modelDirec'), filesep, 'model.aam_dat'], '-mat');
                    Data.handles.AAM = aam.aam;
                    %uiresume
                    %return
            end
            delete(UpdateModel_handle);
            ModelBuilder('Refresh')
        otherwise
            error('Unknown Option in AAMToolbox');
    end
%     if isfield(Data.handles, 'figMain')
%         guidata(Data.handles.figMain, Data);
%     end
end
return;
%%%%%%%%%%%%%%%%%%%%%%
%
%  TurnOffAll
%
%%%%%%%%%%%%%%%%%%%%%%
function [handles] = TurnOffAll(handles)
zoom off; pan off;
set(handles.figMain, 'Pointer', 'Arrow');
set([handles.zoomChk, handles.panChk], 'value', 0);
%%%%%%%%%%%%%%%%%%%%%%
%
%   Global Interpolate
%
%%%%%%%%%%%%%%%%%%%%%%
function [handles] = GlobalInterpolate(handles)
elements = get(handles.AAM, 'elements');
model_dir = get(handles.AAM, 'modelDirec');
template = get(handles.AAM, 'PointModelTemplate');
for i=1:length(elements)
    ce = elements{i};
    loops = get(ce, 'loops');
    closedloops = get(ce, 'closedloops');
    pts = get(ce, 'pts');
    new_pts =[];
    for l = 1:length(loops)
        loop = loops{l};
        if l>1
            old_loop = loops{l-1};
            prevind = old_loop(end);
        else
            prevind = 0;
        end
        if closedloops(l) == 1
            newloop = [prevind+1:prevind+2*length(loop)];
        else
            newloop = [prevind+1:prevind+2*length(loop)-1];
        end
        new_pts = [new_pts, pts(:, loop(1))];
        for p = 2:length(loop)
            v = pts(:, loop(p)) - pts(:,loop(p-1));
            nv = norm(v);
            v = v./nv;
            new_pts = [new_pts,  pts(:, loop(p-1)) + v*(nv/2)];
            new_pts = [new_pts, pts(:, loop(p))];
        end
        if closedloops(l)==1
            v = pts(:, loop(1)) - pts(:,loop(end));
            nv = norm(v);
            v = v./nv;
            new_pts = [new_pts, pts(:, loop(end)) + v*(nv/2)];
        end
        loops{l} = newloop;
    end;
    pts = new_pts;
    ce = set(ce, 'pts', pts);
    ce = set(ce, 'loops', get(template, 'loops'));
    ce = set(ce, 'closedloops', get(template, 'closedloops'));
    ce = set(ce, 'primaries', get(template, 'primaries'));
    elements{i} = ce;
end
handles.AAM = set(handles.AAM, 'elements', elements);
return
%%%%%%%%%%%%%%%%%%%%%%
%
%  Interpolate Points
%
%%%%%%%%%%%%%%%%%%%%%%
function [handles] = InterpolatePoints(handles)
pts = get(handles.PointModelTemplate, 'pts');
loops = get(handles.PointModelTemplate, 'loops');
closedloops = get(handles.PointModelTemplate, 'closedloops');
handles.PointModelTemplate = set(handles.PointModelTemplate, 'primaries', get(handles.PointModelTemplate, 'primaries')*2-1);
handles.PointModelTemplate = set(handles.PointModelTemplate, 'closedloops', get(handles.PointModelTemplate, 'closedloops')*2-1);
new_pts =[];
for l = 1:length(loops)
    loop = loops{l};
    if l>1
        old_loop = loops{l-1};
        prevind = old_loop(end);
    else
        prevind = 0;
    end
    if closedloops(l) == 1
        newloop = [prevind+1:prevind+2*length(loop)];
    else
        newloop = [prevind+1:prevind+2*length(loop)-1];
    end
    new_pts = [new_pts, pts(:, loop(1))];
    for p = 2:length(loop)
        v = pts(:, loop(p)) - pts(:,loop(p-1));
        nv = norm(v);
        v = v./nv;
        new_pts = [new_pts,  pts(:, loop(p-1)) + v*(nv/2)];
        new_pts = [new_pts, pts(:, loop(p))];
    end
    if closedloops(l)==1
        v = pts(:, loop(1)) - pts(:,loop(end));
        nv = norm(v);
        v = v./nv;
        new_pts = [new_pts, pts(:, loop(end)) + v*(nv/2)];
    end
    loops{l} = newloop;
end;
pts = new_pts;
handles.PointModelTemplate = set(handles.PointModelTemplate, 'loops', loops);
handles.PointModelTemplate = set(handles.PointModelTemplate, 'pts', pts);
handles.AAM = set(handles.AAM, 'PointModelTemplate', handles.PointModelTemplate);
handles = GlobalInterpolate(handles);
handles.dat.plotH = PlotTemplate(handles.mainAxes, handles.PointModelTemplate, handles, handles.dat.plotH);
return;
%%%%%%%%%%%%%%%%%%%%%%
%
%  Save Model    //Pretty Obvious
%
%%%%%%%%%%%%%%%%%%%%%%
function [handles] = SaveModel(handles)
%[filename, pathname] = uiputfile('*.model_dat', 'Save Model As...', [get(handles.AAM, 'modelDirec'), filesep, get(handles.AAM, 'modelName')]);

handles.AAM = set(handles.AAM, 'modelName', 'model.aam_dat');
aam = handles.AAM;
save([get(aam, 'modelDirec'), filesep, 'model.aam_dat'], 'aam');
PMTemplate = get(handles.AAM, 'PointModelTemplate');
save(['Templates', filesep, get(PMTemplate, 'name')], 'PMTemplate');

return;
%%%%%%%%%%%%%%%%%%%%%%
%
%  Select Template Image
%
%%%%%%%%%%%%%%%%%%%%%%
function [handles] = SelectTemplateImage(handles)
[filename, pathname] = uigetfile({'*.JPG; *.jpg', 'JPEG Files (*.JPG, *.jpg)'}, 'Select the Template Image', [handles.workingDir]);
if isequal(filename,0) | isequal(pathname,0)
    disp('User pressed cancel')
else
    handles.dat.currentLoopNumber = 0;
    handles.dat.currentLoop = [];
    handles.PointModelTemplate = PointModelTemplate;
    handles.PointModelTemplate = set(handles.PointModelTemplate, 'image', imread([pathname, filesep, filename]));
    imagesc(get(handles.PointModelTemplate, 'image'), 'HitTest', 'off'); axis image;
    handles.dat.plotH = PlotTemplate(handles.mainAxes, handles.PointModelTemplate, handles, handles.dat.plotH);
    handles.PointModelTemplate = set(handles.PointModelTemplate, 'imageName', filename);
    handles.PointModelTemplate = set(handles.PointModelTemplate, 'imageDir', pathname);
    set(handles.imageDirTxt, 'String', pathname);
    set(handles.imageNameTxt, 'String', filename);
end
%%%%%%%%%%%%%%%%%%%%%%
%
%   Global Add
%
%%%%%%%%%%%%%%%%%%%%%%
function [handles] = GlobalAdd(handles)
handles.AAM=read_in_pointmodels(handles.AAM,handles.workingDir);

elements = get(handles.AAM, 'elements');
model_dir = get(handles.AAM, 'modelDirec');
template = get(handles.AAM, 'PointModelTemplate');
templatename = get(template, 'name');
templatename = templatename(1:length(templatename)-9);
n = handles.dat.neighbours;
theta = handles.dat.theta;
k = handles.dat.k;
%JAB here we need to load the elements i.e. the point model data FROM DISC
imagenames = get(handles.AAM, 'imageFilenames');
% FILTER TO INCLUDE JUST THOSE WITH PM's
completed=get(handles.AAM,'completeElements');
for i=completed %1:length(imagenames)
    [path, name, ext, vers] = fileparts(imagenames{i});
    p = load(['PointModels', filesep, templatename, filesep, name, '_pm.mat']);
    p = p.pts; p = reshape(p, 2, length(p)/2);
    V1 = [p(1, n(2)) - p(1, n(1)), p(2, n(2)) - p(2, n(1))];
    v1 = norm(V1);
    V1 = V1/v1;
    v1 = V1*(v1 - (v1/(k+1)));
    R = rotmat(theta);
    V2 = (R*V1')';
    o = tan(theta)*(norm(v1));
    v2 = sqrt(o^2 + (norm(v1))^2)*V2;
    new_p = [p(1, n(1))+v2(1); p(2, n(1))+v2(2)];
    p = [p, new_p];%[p(:, 1:handles.dat.ptsind), new_p, p(:, handles.dat.ptsind+1:end)];
    pts = p(:);
    %save(['PointModels', filesep, templatename, filesep, name, '_pm.mat'], 'pts');
    ce = elements{i};

    ce = set(ce, 'pts', p);
    ce = set(ce, 'loops', get(template, 'loops'));
    ce = set(ce, 'closedloops', get(template, 'closedloops'));
    ce = set(ce, 'primaries', get(template, 'primaries'));
    elements{i} = ce;
end
handles.AAM = set(handles.AAM, 'elements', elements);
return

%%%%%%%%%%%%%%%%%%%%%%
%
% AddPointToLoop
%
%%%%%%%%%%%%%%%%%%%%%%
function [handles] = AddPointToLoop(handles)
handles = TurnOffAll(handles);

switch get(handles.addPointBtn, 'value')
    case 0
        set(handles.figMain, 'Pointer', 'Arrow');
        set(handles.figMain, 'WindowButtonDownFcn', '', 'WindowButtonMotionFcn' , '', 'WindowButtonUpFcn', '', 'KeyPressFcn', '', 'BackingStore','on');
        set(handles.txtCurrentStatus, 'ForegroundColor', 'blue','String', 'Please Choose an Operation');
    case 1
        set(handles.figMain, 'Pointer', 'cross');
        set(handles.txtCurrentStatus, 'ForegroundColor', 'blue','String', 'Add To Subset Mode');
        % First initialise button click function
        set(handles.figMain, 'BackingStore', 'off', 'WindowButtonDownFcn', [mfilename, ' AddLoopPoint']);
end



%%%%%%%%%%%%%%%%%%%%%%
%
%  AddLoopPoint
%
%%%%%%%%%%%%%%%%%%%%%%
function [handles] = AddLoopPoint(handles)
loops = get(handles.PointModelTemplate, 'loops');
pts = get(handles.PointModelTemplate, 'pts');
primaries = get(handles.PointModelTemplate, 'primaries');
indices = get(handles.AAM, 'pointindices');
CurrentPoint = get(handles.mainAxes, 'CurrentPoint');
CurrentPoint = CurrentPoint(1, 1:2)';
% Here we have to do some calculations to figure out where to place the
% point in the rest of the images....ahhhhhh
x = CurrentPoint(1); y = CurrentPoint(2);
d = sqrt((pts(1,:) - x).^2 + (pts(2,:) - y).^2);
[Y,I] = sort(d);
I = I(1:2);
v1 = [x - pts(1, I(1)) , y - pts(2, I(1))];
v2 = [pts(1, I(2)) - pts(1, I(1)), pts(2, I(2)) - pts(2, I(1))]
theta = acos(dot(v1, v2)/(norm(v1)*norm(v2)));
c1 = cos(theta)*norm(v1);
c2 = norm(v2) - c1;
k = c1/c2;
v3 = (v2/norm(v2))*c1;
v3 =[ pts(1, I(1)) pts(1, I(1))+v3(1)], [pts(2, I(1)) pts(2, I(1))+v3(2)];
handles.dat.k = k;
handles.dat.neighbours = I;
v1 = [x - pts(1, I(2)) , y - pts(2, I(2))];
v1 = [v1, 0]';
v2 =[v2, 0]';
c = cross(v1, v2);
handles.dat.theta =-1*sign(c(3))*theta;

if  handles.dat.currentLoopNumber == 0
    ptsind = size(pts, 2);
    pts = [pts, CurrentPoint];
else
    loop = loops{handles.dat.currentLoopNumber};
    looppts = pts(:, loop);
    distances = sqrt((looppts(1,:) - CurrentPoint(1)).^2+ (looppts(2,:) - CurrentPoint(2)).^2);
    nearestPoint = find(distances == min(distances));
    nearestPoint = nearestPoint(1);
    thresh = loop(nearestPoint);
    v1 = pts(:,loop(nearestPoint-1)) - pts(:, loop(nearestPoint));
    v2 = CurrentPoint - pts(:, loop(nearestPoint));
    currentLoop = [loop,size(pts,2)+1];%[loop(1:nearestPoint-1), loop(nearestPoint), loop(nearestPoint:end)+1];
    handles.dat.currentLoop = currentLoop;
    pts = [pts, CurrentPoint];%[pts(:, 1:ptsind), CurrentPoint, pts(:, ptsind+1:end)];
    indices =[indices, size(pts,2)];
    loops{handles.dat.currentLoopNumber} = handles.dat.currentLoop;

end
handles.PointModelTemplate = set(handles.PointModelTemplate, 'loops', loops);
handles.PointModelTemplate = set(handles.PointModelTemplate, 'pts', pts);
handles.PointModelTemplate = set(handles.PointModelTemplate, 'primaries', primaries);
handles.AAM = set(handles.AAM, 'PointModelTemplate', handles.PointModelTemplate);
handles.AAM = set(handles.AAM, 'pointindices', indices);


handles = GlobalAdd(handles);

handles.dat.plotH = PlotTemplate(handles.mainAxes, handles.PointModelTemplate, handles, handles.dat.plotH);

%%%%%%%%%%%%%%%%%%%%%%
%
%  CloseLoop
%
%%%%%%%%%%%%%%%%%%%%%%
function [handles] = CloseLoop(handles)
handles = TurnOffAll(handles);

closedloops = get(handles.PointModelTemplate, 'closedloops');
if(handles.dat.currentLoopNumber>0)
    closedloops(handles.dat.currentLoopNumber) = get(handles.closedChk, 'value');
    handles.PointModelTemplate = set(handles.PointModelTemplate, 'closedloops', closedloops);
end
handles.dat.plotH = PlotTemplate(handles.mainAxes, handles.PointModelTemplate, handles, handles.dat.plotH);
%%%%%%%%%%%%%%%%%%%%%%
%
%  UpdateLoop
%
%%%%%%%%%%%%%%%%%%%%%%
function [handles] = UpdateLoop(handles)
pts = get(handles.PointModelTemplate, 'pts');
if (size(pts, 2)>0)
    loops = get(handles.PointModelTemplate, 'loops');
    CurrentPoint = get(handles.mainAxes, 'CurrentPoint');
    distances = sqrt((pts(1,:) - CurrentPoint(1,1)).^2+ (pts(2,:) - CurrentPoint(1,2)).^2);
    nearestPoint = find(distances == min(distances));
    nearestPoint = nearestPoint(1);
    for l = 1:length(loops)
        loop = loops{l};
        ind = find(loop == nearestPoint);
        if ~isempty(ind)
            handles.dat.currentLoopNumber = l;
        end
    end
    closedloops = get(handles.PointModelTemplate, 'closedloops');
    if ~isempty(closedloops)
        set(handles.closedChk, 'value', closedloops(handles.dat.currentLoopNumber));
    else
        set(handles.closedChk, 'value', 0);
    end
    if handles.dat.currentLoopNumber>0
        handles.dat.currentLoop = loops{handles.dat.currentLoopNumber};
    else
        handles.dat.currentLoop = 0;
    end
    handles.dat.plotH = PlotTemplate(handles.mainAxes, handles.PointModelTemplate, handles, handles.dat.plotH);
end
%%%%%%%%%%%%%%%%%%%%%%
%
%  NewLoop
%
%%%%%%%%%%%%%%%%%%%%%%
function [handles] = NewLoop(handles)
switch (get(handles.insertPointBtn, 'value'))
    case 0
        set(handles.insertPointBtn, 'String', 'New Loop')
        set(handles.figMain, 'Pointer', 'Arrow');
        set(handles.figMain, 'WindowButtonDownFcn', '', 'WindowButtonMotionFcn' , '', 'WindowButtonUpFcn', '', 'KeyPressFcn', '', 'BackingStore','on');
        set(handles.txtCurrentStatus, 'ForegroundColor', 'blue','String', 'Please Choose an Operation');
    case 1
        set(handles.insertPointBtn, 'String', 'Finish Loop')
        set(handles.figMain, 'Pointer', 'fullcrosshair');
        set(handles.txtCurrentStatus, 'ForegroundColor', 'blue','String', 'Insert Landmark Mode');
        % First initialise button click function
        handles.dat.currentLoopNumber = length(get(handles.PointModelTemplate, 'loops')) + 1;
        handles.dat.currentLoop = [];
        set(handles.figMain, 'BackingStore', 'off', 'WindowButtonDownFcn', [mfilename, ' InsertPoint']);
        handles.PointModelTemplate = set(handles.PointModelTemplate, 'closedloops', [get(handles.PointModelTemplate, 'closedloops'), 0]);
end
%%%%%%%%%%%%%%%%%%%%%%
%
%  Save Template    //Pretty Obvious
%
%%%%%%%%%%%%%%%%%%%%%%
function [handles] = InsertPoint(handles)
pts = get(handles.PointModelTemplate, 'pts');
CurrentPoint = get(handles.mainAxes, 'CurrentPoint');
CurrentPoint = CurrentPoint(1, 1:2)';
pts = [pts, CurrentPoint];
handles.dat.currentLoop = [handles.dat.currentLoop size(pts, 2)];
loops = get(handles.PointModelTemplate, 'loops');
loops{handles.dat.currentLoopNumber} = handles.dat.currentLoop;
handles.PointModelTemplate = set(handles.PointModelTemplate, 'loops', loops);
handles.PointModelTemplate = set(handles.PointModelTemplate, 'pts', pts);
handles.dat.plotH = PlotTemplate(handles.mainAxes, handles.PointModelTemplate, handles, handles.dat.plotH);
%%%%%%%%%%%%%%%%%%%%%%
%
%   Global Delete
%
%%%%%%%%%%%%%%%%%%%%%%
function [handles] = GlobalDelete(handles)
elements = get(handles.AAM, 'elements');
model_dir = get(handles.AAM, 'modelDirec');
template = get(handles.AAM, 'PointModelTemplate');
templatename = get(template, 'name');
templatename = templatename(1:length(templatename)-9);
imagenames = get(handles.AAM, 'imageFilenames');
for i=1:length(imagenames)
    [path, name, ext, vers] = fileparts(imagenames{i});
    p = load(['PointModels', filesep, templatename, filesep, name, '_pm.mat']);
    p = p.pts; p = reshape(p, 2, length(p)/2);
    p(:, handles.dat.delPoint) = [];
    pts = p(:);
    %save(['PointModels', filesep, templatename, filesep, name, '_pm.mat'], 'pts');
    ce = elements{i};
    ce = set(ce, 'pts', p);
    ce = set(ce, 'loops', get(template, 'loops'));
    ce = set(ce, 'closedloops', get(template, 'closedloops'));
    ce = set(ce, 'primaries', get(template, 'primaries'));
    elements{i} = ce;
end
handles.AAM = set(handles.AAM, 'elements', elements);
return

%%%%%%%%%%%%%%%%%%%%%%
%
%  DeletePoints
%
%%%%%%%%%%%%%%%%%%%%%%
function [handles] = DeletePoints(handles)
handles = TurnOffAll(handles);

set([handles.movePointBtn, handles.definePrimariesBtn], 'Value', 0)
switch (get(handles.delPointBtn, 'Value'))
    case 0
        set(handles.figMain, 'Pointer', 'Arrow');
        set(handles.figMain, 'WindowButtonDownFcn', '', 'WindowButtonMotionFcn' , '', 'WindowButtonUpFcn', '', 'KeyPressFcn', '', 'BackingStore','on');
        set(handles.txtCurrentStatus, 'ForegroundColor', 'blue','String', 'Please Choose an Operation');
    case 1
        set(handles.figMain, 'Pointer', 'cross');
        set(handles.txtCurrentStatus, 'ForegroundColor', 'blue','String', 'Delete Landmark Mode');
        % First initialise button click function
        set(handles.figMain, 'BackingStore', 'off', 'WindowButtonDownFcn', [mfilename, ' DeletePoint']);
end
%%%%%%%%%%%%%%%%%%%%%%
%
%  DeletePoint
%
%%%%%%%%%%%%%%%%%%%%%%
function [handles] = DeletePoint(handles)
pts = get(handles.PointModelTemplate, 'pts');
loops = get(handles.PointModelTemplate, 'loops');
indices = get(handles.AAM, 'pointindices');
CurrentPoint = get(handles.mainAxes, 'CurrentPoint');
distances = sqrt((pts(1,:) - CurrentPoint(1,1)).^2+ (pts(2,:) - CurrentPoint(1,2)).^2);
delPoint = find(distances == min(distances));
if (length(delPoint)>0)
    delPoint = delPoint(1);
    pts(:, delPoint) = [];
    ind = find(indices == delPoint);
    indices(ind) = [];
    ind = find(indices>delPoint);
    indices(ind) = indices(ind)-1;
    for l = 1:length(loops)
        loop = loops{l};
        ind = find(loop == delPoint);
        loop(ind) = [];
        ind = find(loop > delPoint);
        loop(ind) = loop(ind) -1;
        loops{l} = loop;
    end
    handles.PointModelTemplate = set(handles.PointModelTemplate, 'loops', loops);
    handles.PointModelTemplate = set(handles.PointModelTemplate, 'pts', pts);
    pris = get(handles.PointModelTemplate, 'primaries');
    pri_exist = find( pris == delPoint);
    if length(pri_exist)>0
        pris(pri_exist) = [];
    end
    pri_exist = find( pris > delPoint);
    if length(pri_exist)>0
        pris(pri_exist) = pris(pri_exist)-1;
    end
    handles.PointModelTemplate = set(handles.PointModelTemplate, 'primaries', pris);
    handles.dat.delPoint = delPoint;
    handles.AAM = set(handles.AAM, 'PointModelTemplate', handles.PointModelTemplate);
        handles.AAM = set(handles.AAM, 'pointindices', indices);

    handles = GlobalDelete(handles);
    handles.dat.plotH = PlotTemplate(handles.mainAxes, handles.PointModelTemplate, handles, handles.dat.plotH);
end
%%%%%%%%%%%%%%%%%%%%%%
%
%  Save Template    //Pretty Obvious
%
%%%%%%%%%%%%%%%%%%%%%%
function [handles] = DefinePrimaries(handles)
handles = TurnOffAll(handles);

%  [handles] = DefinePrimaries(handles);
set(handles.movePointBtn, 'Value', 0)
switch(get(handles.definePrimariesBtn, 'Value'))
    case 0
        set(handles.figMain, 'Pointer', 'Arrow');
        set(handles.figMain, 'WindowButtonDownFcn', '', 'WindowButtonMotionFcn' , '', 'WindowButtonUpFcn', '', 'KeyPressFcn', '', 'BackingStore','on');
        set(handles.txtCurrentStatus, 'ForegroundColor', 'blue','String', 'Please Choose an Operation');
    case 1
        set(handles.figMain, 'Pointer', 'Fleur');
        set(handles.txtCurrentStatus, 'ForegroundColor', 'blue','String', 'Select Primaries Mode');
        % First initialise button click function
        set(handles.figMain, 'BackingStore', 'off', 'WindowButtonDownFcn', [mfilename, ' TogglePrimary']);
end
%%%%%%%%%%%%%%%%%%%%%%
%
%  Save Template    //Pretty Obvious
%
%%%%%%%%%%%%%%%%%%%%%%
function [handles] = TogglePrimary(handles)
pts = get(handles.PointModelTemplate, 'pts');
CurrentPoint = get(handles.mainAxes, 'CurrentPoint');
distances = sqrt((pts(1,:) - CurrentPoint(1,1)).^2+ (pts(2,:) - CurrentPoint(1,2)).^2);
PrimaryToToggle = find(distances == min(distances));
PrimaryToToggle = PrimaryToToggle(1);
pris = get(handles.PointModelTemplate, 'primaries');
pri_exist = find( pris == PrimaryToToggle);
if length(pri_exist)>0
    pris(pri_exist) = [];
else
    pris = [pris, PrimaryToToggle];
end
handles.PointModelTemplate = set(handles.PointModelTemplate, 'primaries', pris);
handles.dat.plotH = PlotTemplate(handles.mainAxes, handles.PointModelTemplate, handles, handles.dat.plotH);
%%%%%%%%%%%%%%%%%%%%%%
%
%  MoveMode
%
%%%%%%%%%%%%%%%%%%%%%%
function [handles] = MoveMode(handles)
handles = TurnOffAll(handles);

set(handles.definePrimariesBtn, 'value', 0);
switch(get(handles.movePointBtn, 'Value'))
    case 0
        set(handles.figMain, 'Pointer', 'Arrow');
        set(handles.figMain, 'WindowButtonDownFcn', '', 'WindowButtonMotionFcn' , '', 'WindowButtonUpFcn', '', 'KeyPressFcn', '', 'BackingStore','on');
        set(handles.txtCurrentStatus, 'ForegroundColor', 'blue','String', 'Please Choose an Operation');
    case 1
        zoom off; pan off;
        set(handles.figMain, 'Pointer', 'Fleur');
        set(handles.txtCurrentStatus, 'ForegroundColor', 'blue','String', 'Move Landmark Mode');
        % First initialise button click function
        set(handles.figMain, 'BackingStore', 'off', 'WindowButtonDownFcn', [mfilename, ' PointSelect'], 'KeyPressFcn', [mfilename, ' MovePointKeyPress']);
end
%%%%%%%%%%%%%%%%%%%%%%
%
%  PointSelect
%
%%%%%%%%%%%%%%%%%%%%%%
function [handles] = PointSelect(handles)
CurrentPoint = get(handles.mainAxes, 'CurrentPoint');
ce_pts = get(handles.PointModelTemplate, 'pts');
% Find distance of each point from the selected point on the screen.
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, ' MovePoint'], 'WindowButtonUpFcn', [mfilename, ' DropPoint']);
%%%%%%%%%%%%%%%%%%%%%%
%
%  GlobalMovePoint
%
%%%%%%%%%%%%%%%%%%%%%%
function [handles] = GlobalMovePoint(handles)
elements = get(handles.AAM, 'elements');
model_dir = get(handles.AAM, 'modelDirec');
template = get(handles.AAM, 'PointModelTemplate');
templatename = get(template, 'name');
[path, templatename, ext, vers] = fileparts(templatename);
imagenames = get(handles.AAM, 'imageFilenames');
delta_p = handles.dat.delta_p;
for i=1:length(imagenames)
    [path, name, ext, vers] = fileparts(imagenames{i});
    p = load(['PointModels', filesep, templatename, filesep, name, '_pm.mat']);
    p = p.pts; p = reshape(p, 2, length(p)/2);
    p(1,handles.dat.PointToMove) = p(1,handles.dat.PointToMove) + delta_p(1);
    p(2,handles.dat.PointToMove) = p(2,handles.dat.PointToMove) + delta_p(2);
    pts = p(:);
    %save(['PointModels', filesep, templatename, filesep, name, '_pm.mat'], 'pts');
    ce = elements{i};
    ce = set(ce, 'pts', p);
    ce = set(ce, 'loops', get(template, 'loops'));
    ce = set(ce, 'closedloops', get(template, 'closedloops'));
    ce = set(ce, 'primaries', get(template, 'primaries'));
    elements{i} = ce;
end
handles.AAM = set(handles.AAM, 'elements', elements);
return


%%%%%%%%%%%%%%%%%%%%%%
%
%  MovePoint
%
%%%%%%%%%%%%%%%%%%%%%%
function [handles] = MovePoint(handles)
CurrentPoint = get(handles.mainAxes, 'CurrentPoint');
ce_pts = get(handles.PointModelTemplate, 'pts');
handles.dat.delta_p = [CurrentPoint(1,1) - ce_pts(1,handles.dat.PointToMove); CurrentPoint(1,2) - ce_pts(2,handles.dat.PointToMove)];
ce_pts(1,handles.dat.PointToMove) = CurrentPoint(1,1);
ce_pts(2,handles.dat.PointToMove) = CurrentPoint(1,2);
handles.PointModelTemplate = set(handles.PointModelTemplate, 'pts', ce_pts);
handles.AAM = set(handles.AAM, 'PointModelTemplate', handles.PointModelTemplate);
handles = GlobalMovePoint(handles);
handles.dat.plotH = PlotTemplate(handles.mainAxes, handles.PointModelTemplate, handles, handles.dat.plotH);
%%%%%%%%%%%%%%%%%%%%%%
%
%  Save Template    //Pretty Obvious
%
%%%%%%%%%%%%%%%%%%%%%%
function [handles] = ToggleZoom(handles);
set([handles.insertPointBtn, handles.movePointBtn, handles.addPointBtn, handles.delPointBtn, handles.definePrimariesBtn, handles.smoothlandmarksBtn], 'value', 0);
switch(get(handles.zoomChk, 'Value'))
    case 0
        zoom off;
        set(handles.txtCurrentStatus, 'ForegroundColor', 'black', 'String', 'Zoom is off');
    case 1
        zoom on;
        set(handles.txtCurrentStatus, 'ForegroundColor', 'black', 'String', 'Zoom is on');
    otherwise
        set(handles.txtCurrentStatus, 'ForegroundColor', 'red', 'String', 'Unknown value for zoom mode');
end
%%%%%%%%%%%%%%%%%%%%%%
%
%  Save Template    //Pretty Obvious
%
%%%%%%%%%%%%%%%%%%%%%%
function [handles] = TogglePan(handles)
set([handles.insertPointBtn, handles.movePointBtn, handles.addPointBtn, handles.delPointBtn, handles.definePrimariesBtn, handles.smoothlandmarksBtn], 'value', 0);

switch(get(handles.panChk, 'Value'))
    case 0
        pan off;
        set(handles.txtCurrentStatus, 'ForegroundColor', 'black', 'String', 'Pan is off');
    case 1
        pan on;
        set(handles.txtCurrentStatus, 'ForegroundColor', 'black', 'String', 'Pan is on');
    otherwise
        set(handles.txtCurrentStatus, 'ForegroundColor', 'red', 'String', 'Unknown value for pan mode');
end

%%%%%%%%%%%%%%%%%%%%%%
%
%
%  PlotTemplate(A, template)
%
%%%%%%%%%%%%%%%%%%%%%%
function [plotH] = PlotTemplate(A, template, handles, plotH)
if(any(plotH))
    if any(ishandle(plotH))
        delete(plotH);
    end
    plotH = [];
end
% I = get(template, 'image');
pts = get(template, 'pts');
pri = get(template, 'primaries');
indices = get(handles.AAM, 'pointindices');
loops = get(template, 'loops');
closedloops = get(template, 'closedloops');



pri = intersect(pri, indices);
for l=1:length(loops)
    loops{l} = intersect(loops{l} , indices);
end

if isempty(closedloops)
    closedloops = 0;
end
axes(A); hold(A, 'on');
if get(handles.linesChk, 'value')
    %%%%%%%%%%%%%%
    %
    % Plot the loop lines in red
    %
    %%%%%%%%%%%%%%
    for i=1:length(loops)
        looppts = pts(:, loops{i});
        if (closedloops(i)==1)
            looppts = [looppts, looppts(:, 1)];
        end
        if (size(looppts,2)>0)
            plotH(length(plotH)+1) = plot(looppts(1, :), looppts(2,:), 'r', 'LineWidth', 1.5, 'MarkerEdgeColor', [112/255 91/255 223/255], 'HitTest', 'off','Parent', A );
        end
    end
    %%%%%%%%%%%%%%
    %
    % Plot the current loop in yellow
    %
    %%%%%%%%%%%%%%
    if (handles.dat.currentLoopNumber > 0)
        looppts = pts(:, loops{handles.dat.currentLoopNumber});
        if (closedloops(handles.dat.currentLoopNumber)==1)
            looppts = [looppts, looppts(:, 1)];
        end
        if (size(looppts, 2)>0)
            plotH(length(plotH)+1) = plot(looppts(1,:), looppts(2,:), 'y',  'LineWidth', 1.5, 'HitTest', 'off', 'Parent', A);
        end
    end
end
if get(handles.toggleLandmarksChk,'value')
    %%%%%%%%%%%%%%
    %
    % Plot all the landmarks in red
    %
    %%%%%%%%%%%%%%
    if (size(pts, 2) > 0)
        plotH(length(plotH)+1) = plot(pts(1, indices), pts(2,indices), 'or', 'MarkerEdgeColor', 'y', 'MarkerFaceColor', 'r', 'MarkerSize', 6, 'HitTest', 'off', 'Clipping', 'on', 'Parent', A );
    end
    %%%%%%%%%%%%%%
    %
    % Plot the primaries in green
    %
    %%%%%%%%%%%%%%
    if (length(pri)>0)
        plotH(length(plotH)+1) = plot(pts(1, pri), pts(2,pri), 'og','MarkerEdgeColor', 'y', 'MarkerFaceColor', 'g', 'MarkerSize', 6, 'HitTest', 'off', 'Parent', A);
    end
end
if get(handles.toggleLabelsChk, 'value')

    for i=indices
        plotH(length(plotH)+1) = text(pts(1, i), pts(2,i), num2str(i), 'Color', 'w', 'HitTest', 'off', 'Parent', A, 'Clipping', 'on');
    end
end
return;
%%%%%%%%%%%%%%%%%%%%%%
%
%  cut_string   //splits directory names so you can see the beginning and
%                   //the end
%%%%%%%%%%%%%%%%%%%%%%
function [s] = cut_string(s)
if (length(s)>83)
    s = [s(1:40), '...', s(end-40:end)];
end
%%%%%%%%%%%%%%%%%%%%%%
%
%  Load Template    //Pretty Obvious
%
%%%%%%%%%%%%%%%%%%%%%%
function [handles] = LoadTemplate(handles)
[filename, pathname] = uigetfile('*.temp_dat', 'Pick a File', [handles.workingDir]);
if isequal(filename,0) | isequal(pathname,0)
    disp('User pressed cancel')
else
    template = load([pathname, filename], '-mat');
    handles.PointModelTemplate = template.PMTemplate;
    handles.dat.plotH = [];
    set(handles.mainAxes, 'Visible', 'off');
    cla(handles.mainAxes);
    imagesc(get(handles.PointModelTemplate, 'image'), 'HitTest', 'off'); axis image ij;
    handles.dat.plotH = PlotTemplate(handles.mainAxes, handles.PointModelTemplate, handles, handles.dat.plotH);
    handles.workingDir = pathname;
    set(handles.closedChk, 'value', 0);
    set(handles.imageDirTxt, 'String', cut_string(get(handles.PointModelTemplate, 'imageDir')));
    set(handles.imageNameTxt, 'String', get(handles.PointModelTemplate, 'imageName'));
    set(handles.templateDirTxt, 'String', cut_string(get(handles.PointModelTemplate, 'direc')));
    set(handles.templateNameTxt, 'String', get(handles.PointModelTemplate, 'name'));
end
return;
%%%%%%%%%%%%%%%%%%%%%%
%
%  Save Template    //Pretty Obvious
%
%%%%%%%%%%%%%%%%%%%%%%
function [handles] = SaveTemplate(handles)
[filename, pathname] = uiputfile('*.temp_dat', 'Pick a File', 'Templates');
if isequal(filename,0) | isequal(pathname,0)
    disp('User pressed cancel')
else
    handles.PointModelTemplate = set(handles.PointModelTemplate, 'name', filename);
    handles.PointModelTemplate = set(handles.PointModelTemplate, 'direc', pathname);
    PMTemplate = handles.PointModelTemplate;
    save([pathname, filename], 'PMTemplate');
    disp(['User selected ', fullfile(pathname, filename)])
    handles.workingDir = pathname;
    set(handles.templateDirTxt, 'String', cut_string(pathname));
    set(handles.templateNameTxt, 'String', filename);
end
disp('Saving');
return;
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
%  SmoothLandmarks    //Smooths the secondary landmarks in a given loop
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function [handles] = SmoothLandmarks(handles)
handles = TurnOffAll(handles);

pri = get(handles.PointModelTemplate, 'primaries')';
pts = get(handles.PointModelTemplate, 'pts')';
pts_orig = pts;
currentLoop = handles.dat.currentLoopNumber;
loops = get(handles.PointModelTemplate, 'loops');
edges=loops{1};
ind = loops{currentLoop};
pts = pts(ind,:);
pri = intersect(pri, ind);
for p = 1:length(pri)
    pri(p) = find(ind == pri(p));
end
[handles,pts]=general_smoothlandmarks(handles,pts,pri,edges);
% 
% if(length(pri) <= 1)
%     set(handles.txtCurrentStatus, 'ForegroundColor', 'red', 'String', 'Need at least two primaries points');
%     return;
% end
% SectionsToSmooth = length(pri) - 1;
% loop = 0;
% % % If loop is complete, loop back to first primary
% if(loop)
%     SectionsToSmooth = length(pri);
%     pri = [pri pri(1)];
% else
%     SectionsToSmooth = length(pri) - 1;
% end
% % Array indexing chages for last section when complete loop is selected
% lastloop = 0;
% for k = 1:SectionsToSmooth
%     % Number of points in current section
%     NptsThisSection = pri(k+1) - pri(k) + 1;
%     x = zeros(NptsThisSection, 1);
%     y = zeros(NptsThisSection, 1);
%     if(NptsThisSection < 0)
%         % Last section, perform loop back to first primary point
%         lastloop = 1;
%         NptsThisSection = size(pts, 1) - pri(k) + 2;
%         x(1) = pts(pri(1),1);
%         x(NptsThisSection) = pts(pri(k), 1);
%         x(2:NptsThisSection-1) = pts(size(pts,1):-1:pri(k)+1,1)';
%         y(1) = pts(pri(1), 2);
%         y(NptsThisSection) = pts(pri(k), 2);
%         y(2:NptsThisSection-1) = pts(size(pts, 1):-1:pri(k)+1, 2)';
%     else
%         % Get x and y components of values between current landmark pair
%         x(1) = pts(pri(k), 1);
%         x(NptsThisSection) = pts(pri(k+1), 1);
%         x(2:NptsThisSection-1) = pts(pri(k)+1:pri(k)+NptsThisSection-2,1);
%         y(1) = pts(pri(k), 2);
%         y(NptsThisSection) = pts(pri(k+1), 2);
%         y(2:NptsThisSection-1) = pts(pri(k)+1:pri(k)+NptsThisSection-2,2);
%     end
%     Nint = 50; % Number of interpolation points used
%     % Fit data using a spline interpolation
%     t = 1:NptsThisSection;
%     ts = 1:1/Nint:NptsThisSection;
%     xfit = spline(t, x, ts); % x-coordinates of interpolating line
%     yfit = spline(t, y, ts); % y-coordinates of interpolating line
%     % Calculate the length of the line through the secondaries
%     xfitS = xfit(2:length(xfit)) - xfit(1:length(xfit)-1);
%     yfitS = yfit(2:length(yfit)) - yfit(1:length(yfit)-1);
%     LineLength = cumsum(sqrt((xfitS.^2) + (yfitS.^2)));
%     % Calculate what the spacing should be between the secondaries.
%     DistanceBetweenPoints = LineLength(length(LineLength)) / (NptsThisSection - 1);
%     % Clear from last iteration
%     newx=[]; newy=[];
%     % Find position of new points
%     for n = 2:NptsThisSection-1
%         idx = min(find(LineLength >= (n-1) * DistanceBetweenPoints)) + 1;
%         newx(n-1) = xfit(idx);
%         newy(n-1) = yfit(idx);
%     end
%     if(~lastloop)
%         pts(pri(k)+1:pri(k+1)-1, 1) = newx';
%         pts(pri(k)+1:pri(k+1)-1, 2) = newy';
%     else
%         pts(pri(k)+1:size(pts, 1), 1) = flipud(newx');
%         pts(pri(k)+1:size(pts, 1), 2) = flipud(newy');
%     end
% 
% end
pts_orig(ind, :) = pts;
handles.PointModelTemplate = set(handles.PointModelTemplate, 'pts', pts_orig');
handles.dat.plotH = PlotTemplate(handles.mainAxes, handles.PointModelTemplate, handles, handles.dat.plotH);
if(loop)
    pri = pri(1:length(pri)-1);
end
