classdef CropPositives < handle
    
    properties
        loader;
        viewer;
        points;
        outputPath;
    end
    
    methods
        
        function o = CropPositives(inputPath,outputPath)
            o.loader = ImageLoader(inputPath);
            o.viewer = ImageViewer(o.loader);
            o.outputPath = outputPath;
        
            o.viewer.createFigure('name','Input Images','NumberTitle','off','menubar','none','position',[80 80 900 900]);
            set(o.viewer.figureHandler,'WindowKeyPressFcn',{@o.keyboardHandler});
            set(o.viewer.figureHandler,'WindowButtonDownFcn',{@o.mouseHandler});
            set(o.viewer.figureHandler,'WindowButtonMotionFcn',{@o.mouseMoveHandler});
        
            o.viewer.draw();
        end
        
        function keyboardHandler(o,src,event)
            
            frame = o.loader.current_frame;
            o.viewer.callbackKeyPressed(src,event);
            
            if o.loader.current_frame~=frame
                o.points = [];
            end
            
            if event.Key=='s'
                o.correctPointsOrder();
                crop = o.getCrop(o.points(1,:),o.points(2,:),o.loader.current_image);
                
                filename = sprintf('%06d.png',o.loader.current_frame);
                filepath = fullfile(o.outputPath,filename);
                imwrite(crop,filepath,'PNG');
                disp(['Image ' filepath ' saved to disk'])
            end
            
            if event.Key=='g' %Grab detection
                o.saveDetection();
            end
        end
        
        function saveDetection(o)
            o.correctPointsOrder();
            filename = sprintf('%06d.txt',o.loader.current_frame);
            filepath = fullfile(o.outputPath,filename);
            fileid = fopen(filepath,'a');
            fprintf(fileid,'%g %g %g %g\n',o.points(1,1),o.points(1,2),...
                o.points(2,1),o.points(2,2));
            fprintf('New detection: %g %g %g %g\n',o.points(1,1),o.points(1,2),...
                o.points(2,1),o.points(2,2));

            fclose(fileid);
            
            h=findobj(o.viewer.axisHandler,'Tag','rect');
            if ~isempty(h)
                set(h,'edgecolor',[0.7 0.0 0.1],...
                    'linewidth',2);
            end
        end
        
        function drawGuides(o)%Draw two guide lines
            
            hold on
            h=findobj(o.viewer.axisHandler,'Tag','horizontalGuide');
            if ~isempty(h)
                delete(h)
            end
            
            point = get(o.viewer.axisHandler, 'CurrentPoint');
            imagesize = size(o.loader.current_image);
            point = point(1,:);
            point = point -3;
            
            %Draw horizontal line
            pleft = [1 point(1,2)];
            pright = [imagesize(2) point(1,2)];
            
            h=plot(o.viewer.axisHandler,[pleft(1) pright(1)],[pleft(2) pright(2)]);
            set(h,'Tag','horizontalGuide');
            
            h=findobj(o.viewer.axisHandler,'Tag','verticalGuide');
            if ~isempty(h)
                delete(h)
            end
            
            %Draw vertical line
            ptop = [point(1,1) 1];
            pbottom = [point(1,1) imagesize(1)];
            
            h=plot(o.viewer.axisHandler,[ptop(1) pbottom(1)],[ptop(2) pbottom(2)]);
            set(h,'Tag','verticalGuide');
            
        end
        
        function mouseMoveHandler(o,~,~)
            
            o.drawGuides();
            
            if isempty(o.points)
                return
            end
            
            if size(o.points,1)==1
                point = get(o.viewer.axisHandler, 'CurrentPoint');
                point = point(1,:);
                point = point -3;
                
                h=findobj(o.viewer.axisHandler,'Tag','rect');
                if ~isempty(h)
                    delete(h);
                end
                
                o.drawRectange(o.points(1,:),point,o.viewer.axisHandler,...
                    'Tag','rect','edgecolor',[1 0.4 0.4])
            end
        end
        
        function correctPointsOrder(o)
            p1 = o.points(1,:);
            p2 = o.points(2,:);
            
            if p1(1)>p2(1)
                t= p1(1);
                p1(1)=p2(1);
                p2(1)=t;
            end
            
            if p1(2)>p2(2)
                t= p1(2);
                p1(2)=p2(2);
                p2(2)=t;
            end
            
            o.points(1,:) = p1;
            o.points(2,:) = p2; 
        end
        
        function im = getCrop(o,p1,p2,image)
            im = image(p1(2):p2(2),p1(1):p2(1),:);
        end
        
        function drawRectange(~,p1,p2,handler,varargin)
            if p1(1)>p2(1)
                t= p1(1);
                p1(1)=p2(1);
                p2(1)=t;
            end
            
            if p1(2)>p2(2)
                t= p1(2);
                p1(2)=p2(2);
                p2(2)=t;
            end
            
            width = p2(1)-p1(1);
            height = p2(2)-p1(2);
            
            if width<=0 || height<=0
                return
            end
            
            h = rectangle('Position',[p1(1) p1(2) width height],'Parent',handler);
            set(h,varargin{:})
        end
        
        function mouseHandler(o,src,event)
            o.viewer.callbackImagePressed(src,event);
            
            if size(o.points,1)==2 && strcmp(get(o.viewer.figureHandler,'SelectionType'),'alt')
                o.saveDetection();
                return
            end
            
%             if strcmp(get(o.viewer.figureHandler,'SelectionType'),'alt')
%                 return;
%             end
                
            h=findobj(o.viewer.axisHandler,'Tag','pt');
            
            x = get(h,'xdata');
            y = get(h,'ydata');
            
            if isempty(isempty(o.points))
                o.points(1,:) = [x y];
            elseif size(o.points,1)==1
                o.points(2,:) = [x y];
            else
                o.points = [];
                o.points(1,:) = [x y];
            end
            
            h=findobj(o.viewer.axisHandler,'Tag','rect');
            if ~isempty(h)
                delete(h);
            end
            
            if size(o.points,1)==2
                o.drawRectange(o.points(1,:),o.points(2,:),o.viewer.axisHandler,...
                    'Tag','rect','edgecolor',[1 0 0]);
                
                if strcmp(get(o.viewer.figureHandler,'SelectionType'),'alt')
                    o.saveDetection();
                end
            end
            
        end
        
    end
end