classdef CropPupil < matlab.apps.AppBase

    % Properties that correspond to app components
    properties (Access = public)
        UIFigure             matlab.ui.Figure
        SaveButton           matlab.ui.control.Button
        TimeEditField        matlab.ui.control.EditField
        TimeEditFieldLabel   matlab.ui.control.Label
        FrameEditField       matlab.ui.control.EditField
        FrameEditFieldLabel  matlab.ui.control.Label
        Slider               matlab.ui.control.Slider
        UIAxes               matlab.ui.control.UIAxes
    end

    
    properties (Access = public)
        tr
        frame % Description
        rec
        roi

        img_handle
    end
    
    methods (Access = public)
        
        function show_frame(app)
            img = imread(fullfile(app.rec.path,app.rec.files(app.frame)));
            if isempty(app.img_handle)
                app.img_handle = imshow(img, "Parent", app.UIAxes);
            else
                app.img_handle.CData = img;
            end
        end
        
        function set_frame(app, frame)
            app.frame = round(frame);
            app.frame = max(app.frame, 1);
            app.frame = min(app.frame, length(app.rec.files));

            % Update frame text.
            app.FrameEditField.Value = num2str(app.frame);
            
            % Update time text.
            time = seconds(app.rec.frame_offset_s(app.frame));
            time.Format = "hh:mm:ss";
            app.TimeEditField.Value = string(time);

            app.show_frame();
        end
    end
    

    % Callbacks that handle component events
    methods (Access = private)

        % Code that executes after component creation
        function startupFcn(app, tr)
            % Save dloc to use when saving data.
            app.tr = tr;
            
            % Init pupil data manager object.
            rec_path = fullfile(tr.path, "pupil_data");
            app.rec = yucca.mod.puptool.PupilRecording(rec_path);

            % Init slider value.
            app.Slider.Value = 1;
            app.Slider.Limits = [1,length(app.rec.files)];

            app.set_frame(1);

            % Draw roi.
            % Set the crop based on the saved data.
            pupil_crop = tr.load_var("pupil_crop",[]);
            if isempty(pupil_crop)
                app.roi = drawrectangle(app.UIAxes,"Rotatable", true);
            else
                app.roi = drawrectangle(app.UIAxes,"Rotatable", true, ...
                    "Position",pupil_crop(1:4),"RotationAngle",pupil_crop(5));
            end
            
        end

        % Value changing function: Slider
        function SliderValueChanging(app, event)
            app.set_frame(event.Value);
        end

        % Button pushed function: SaveButton
        function SaveButtonPushed(app, event)
            if ~isempty(app.roi)
                pupil_crop = [app.roi.Position,app.roi.RotationAngle]
                app.tr.save_var(pupil_crop);
                disp("Saved pupil crop");
                close(app.UIFigure);
            end
        end
    end

    % Component initialization
    methods (Access = private)

        % Create UIFigure and components
        function createComponents(app)

            % Create UIFigure and hide until all components are created
            app.UIFigure = uifigure('Visible', 'off');
            app.UIFigure.Position = [100 100 649 697];
            app.UIFigure.Name = 'MATLAB App';

            % Create UIAxes
            app.UIAxes = uiaxes(app.UIFigure);
            app.UIAxes.XTick = [];
            app.UIAxes.YTick = [];
            app.UIAxes.Position = [2 126 650 650];

            % Create Slider
            app.Slider = uislider(app.UIFigure);
            app.Slider.MajorTicks = [];
            app.Slider.ValueChangingFcn = createCallbackFcn(app, @SliderValueChanging, true);
            app.Slider.MinorTicks = [];
            app.Slider.Position = [10 100 629 3];

            % Create FrameEditFieldLabel
            app.FrameEditFieldLabel = uilabel(app.UIFigure);
            app.FrameEditFieldLabel.HorizontalAlignment = 'right';
            app.FrameEditFieldLabel.Enable = 'off';
            app.FrameEditFieldLabel.Position = [168 42 40 22];
            app.FrameEditFieldLabel.Text = 'Frame';

            % Create FrameEditField
            app.FrameEditField = uieditfield(app.UIFigure, 'text');
            app.FrameEditField.Editable = 'off';
            app.FrameEditField.Enable = 'off';
            app.FrameEditField.Position = [223 42 100 22];

            % Create TimeEditFieldLabel
            app.TimeEditFieldLabel = uilabel(app.UIFigure);
            app.TimeEditFieldLabel.HorizontalAlignment = 'right';
            app.TimeEditFieldLabel.Enable = 'off';
            app.TimeEditFieldLabel.Position = [368 42 32 22];
            app.TimeEditFieldLabel.Text = 'Time';

            % Create TimeEditField
            app.TimeEditField = uieditfield(app.UIFigure, 'text');
            app.TimeEditField.Editable = 'off';
            app.TimeEditField.Enable = 'off';
            app.TimeEditField.Position = [415 42 100 22];

            % Create SaveButton
            app.SaveButton = uibutton(app.UIFigure, 'push');
            app.SaveButton.ButtonPushedFcn = createCallbackFcn(app, @SaveButtonPushed, true);
            app.SaveButton.Position = [522 42 100 22];
            app.SaveButton.Text = 'Save';

            % Show the figure after all components are created
            app.UIFigure.Visible = 'on';
        end
    end

    % App creation and deletion
    methods (Access = public)

        % Construct app
        function app = CropPupil(varargin)

            % Create UIFigure and components
            createComponents(app)

            % Register the app with App Designer
            registerApp(app, app.UIFigure)

            % Execute the startup function
            runStartupFcn(app, @(app)startupFcn(app, varargin{:}))

            if nargout == 0
                clear app
            end
        end

        % Code that executes before app deletion
        function delete(app)

            % Delete UIFigure when app is deleted
            delete(app.UIFigure)
        end
    end
end