classdef RoaPre < matlab.apps.AppBase

    % Properties that correspond to app components
    properties (Access = public)
        RootFigure                      matlab.ui.Figure
        XYSmoothingsigmapixelsSliderLabel  matlab.ui.control.Label
        XYSmoothingsigmapixelsSlider    matlab.ui.control.Slider
        EditField                       matlab.ui.control.NumericEditField
        TimesmoothingframesSliderLabel  matlab.ui.control.Label
        TimesmoothingframesSlider       matlab.ui.control.Slider
        EditField_2                     matlab.ui.control.NumericEditField
        LoadButton                      matlab.ui.control.Button
        SaveButton                      matlab.ui.control.Button
        ProcessROACheckBox              matlab.ui.control.CheckBox
    end

    
    properties (Access = private)
        manager
        application
        data_change_listener
        view_data_change_listener
        view
        force_update_flag
    end
    
    methods (Access = private)
        
        function handle_view_changed(app,sr,ev)
            if ~isvalid(app)
                return;
            end
            % clear old event listeners:
            if ~isempty(app.data_change_listener)
                delete(app.data_change_listener);
            end
            if ~isempty(app.view_data_change_listener)
                delete(app.view_data_change_listener);
            end
    
            app.manager = ev.viewmanager;
            app.force_update_flag = true;

            % the new items could be empty - in whcih case we simply hide
            % outselves:
            if isempty(ev.viewmanager) || isempty(ev.to) || ~ev.viewmanager.data.has("roa_pre_param")
                app.RootFigure.Visible = false;
                app.view = [];
                return
            else
                app.RootFigure.Visible = true;
                
                % this steams focus, so we must focus top view again:
                ev.viewmanager.focus_top_view();
            
                app.manager.data.assign_changeflag("roa_pre_param","roa_pretool");
                app.manager.data.assign_changeflag("roa_pre_param_saved","roa_pretool");
                
                app.data_change_listener = addlistener(app.manager.data, ...
                   'on_data_changed', @(~, ~) app.handle_data_changed());
            
                app.view = ev.to;
                
                app.view.data.assign_changeflag("channel_samples","roa_pretool");
                app.view.data.assign_changeflag("channel_xy_smoothing","roa_pretool");
                app.view.data.assign_changeflag("channel","roa_pretool");
                
                app.view_data_change_listener = addlistener(ev.to.data, ...
                   'on_data_changed', @(~, ~) app.handle_data_changed());
                
                app.handle_data_changed();
            end
            
        end
        
        function handle_data_changed(app,sr,ev)
            
            if ~isvalid(app) || isempty(app.manager) || ~isvalid(app.manager) || isempty(app.view)
                return;
            end
            
            [~, ~, m_read,m_flagged] = app.manager.data.shorts();
            [v_has, ~, v_read,v_flagged] = app.view.data.shorts();
            
            if ~m_flagged("roa_pretool") && ~v_flagged("roa_pretool") && ~app.force_update_flag
                return;
            end
            app.force_update_flag = false;
            
            chan = v_read("channel",[]);
            if isempty(chan)
                return;
            end
            
            roa_pre_param = m_read("roa_pre_param");
            roa_pre_param_saved = m_read("roa_pre_param_saved");
            
            if isequal(roa_pre_param,roa_pre_param_saved) || isempty(roa_pre_param_saved)
                app.LoadButton.Enable = 'Off';
            else
                app.LoadButton.Enable = 'On';
            end
            
            if isempty(roa_pre_param_saved) || ~isequal(roa_pre_param_saved,roa_pre_param)
                app.SaveButton.Enable = 'On';
            else
                app.SaveButton.Enable = 'Off';
            end
            
            xy_smoothing = roa_pre_param(chan).roa_xy_smooth;
            if app.XYSmoothingsigmapixelsSlider.Limits(2) < xy_smoothing
                app.XYSmoothingsigmapixelsSlider.Limits(2) = xy_smoothing;
            end
            app.XYSmoothingsigmapixelsSlider.Value = xy_smoothing;
            app.EditField.Value = xy_smoothing;
            
            time_smoothiing = roa_pre_param(chan).roa_t_smooth;
            if app.TimesmoothingframesSlider.Limits(2) < time_smoothiing
                app.TimesmoothingframesSlider.Limits(2) = time_smoothiing;
            end
            app.TimesmoothingframesSlider.Value = time_smoothiing;
            app.EditField_2.Value = time_smoothiing;
            
            app.ProcessROACheckBox.Value = roa_pre_param(chan).roa_enabled;
        end
    end
    

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

        % Code that executes after component creation
        function startupFcn(app, application)
            addlistener(application, 'on_view_changed',...
                @app.handle_view_changed);
            
            app.application = application;
        end

        % Button pushed function: LoadButton
        function LoadButtonPushed(app, event)
            roa_pre_param = app.manager.data.read("roa_pre_param_saved");
            app.manager.data.write("roa_pre_param",roa_pre_param);
            
            v = app.manager.current_view;
            chan = v.data.read("channel");
            v.data.write("channel_samples",roa_pre_param(chan).roa_t_smooth);
            v.data.write("channel_xy_smoothing",roa_pre_param(chan).roa_xy_smooth);
        end

        % Button pushed function: SaveButton
        function SaveButtonPushed(app, event)
            roa_pre_param = app.manager.data.read("roa_pre_param");
            ts = app.manager.data.read("tseries");
            ts.save_var(roa_pre_param);
            
            app.manager.data.write("roa_pre_param_saved",roa_pre_param);
        end

        % Value changing function: XYSmoothingsigmapixelsSlider
        function XYSmoothingsigmapixelsSliderValueChanging(app, event)
            v = app.manager.current_view;
            chan = v.data.read("channel");
            
            roa_pre_param = app.manager.data.read("roa_pre_param");
            roa_pre_param(chan).roa_xy_smooth = event.Value;
            app.manager.data.write("roa_pre_param",roa_pre_param);
            v.data.write("channel_xy_smoothing",roa_pre_param(chan).roa_xy_smooth);
        end

        % Value changing function: TimesmoothingframesSlider
        function TimesmoothingframesSliderValueChanging(app, event)
            v = app.manager.current_view;
            chan = v.data.read("channel");
            
            roa_pre_param = app.manager.data.read("roa_pre_param");
            roa_pre_param(chan).roa_t_smooth = round(event.Value);
            app.manager.data.write("roa_pre_param",roa_pre_param);
            v.data.write("channel_samples",roa_pre_param(chan).roa_t_smooth);
        end

        % Value changed function: ProcessROACheckBox
        function ProcessROACheckBoxValueChanged(app, event)
            v = app.manager.current_view;
            chan = v.data.read("channel");
            
            roa_pre_param = app.manager.data.read("roa_pre_param");
            roa_pre_param(chan).roa_enabled = event.Value;
            app.manager.data.write("roa_pre_param",roa_pre_param);
        end

        % Value changed function: EditField
        function EditFieldValueChanged(app, event)
            v = app.manager.current_view;
            chan = v.data.read("channel");
            
            roa_pre_param = app.manager.data.read("roa_pre_param");
            roa_pre_param(chan).roa_xy_smooth = event.Value;
            app.manager.data.write("roa_pre_param",roa_pre_param);
            v.data.write("channel_xy_smoothing",roa_pre_param(chan).roa_xy_smooth);
        end

        % Value changed function: EditField_2
        function EditField_2ValueChanged(app, event)
            v = app.manager.current_view;
            chan = v.data.read("channel");
            
            roa_pre_param = app.manager.data.read("roa_pre_param");
            roa_pre_param(chan).roa_t_smooth = round(event.Value);
            app.manager.data.write("roa_pre_param",roa_pre_param);
            v.data.write("channel_samples",roa_pre_param(chan).roa_t_smooth);
        end
    end

    % Component initialization
    methods (Access = private)

        % Create UIFigure and components
        function createComponents(app)

            % Create RootFigure and hide until all components are created
            app.RootFigure = uifigure('Visible', 'off');
            app.RootFigure.Position = [100 100 234 271];
            app.RootFigure.Name = 'Preprocessing Parameters';

            % Create XYSmoothingsigmapixelsSliderLabel
            app.XYSmoothingsigmapixelsSliderLabel = uilabel(app.RootFigure);
            app.XYSmoothingsigmapixelsSliderLabel.HorizontalAlignment = 'right';
            app.XYSmoothingsigmapixelsSliderLabel.Position = [18 206 159 22];
            app.XYSmoothingsigmapixelsSliderLabel.Text = 'XY Smoothing (sigma pixels)';

            % Create XYSmoothingsigmapixelsSlider
            app.XYSmoothingsigmapixelsSlider = uislider(app.RootFigure);
            app.XYSmoothingsigmapixelsSlider.Limits = [0 10];
            app.XYSmoothingsigmapixelsSlider.ValueChangingFcn = createCallbackFcn(app, @XYSmoothingsigmapixelsSliderValueChanging, true);
            app.XYSmoothingsigmapixelsSlider.Tooltip = {'Input the number of pixels that will be gaussian smoothed to improve the signal-to-noise ratio. '};
            app.XYSmoothingsigmapixelsSlider.Position = [29 185 176 3];

            % Create EditField
            app.EditField = uieditfield(app.RootFigure, 'numeric');
            app.EditField.ValueChangedFcn = createCallbackFcn(app, @EditFieldValueChanged, true);
            app.EditField.Position = [183 206 29 22];

            % Create TimesmoothingframesSliderLabel
            app.TimesmoothingframesSliderLabel = uilabel(app.RootFigure);
            app.TimesmoothingframesSliderLabel.HorizontalAlignment = 'right';
            app.TimesmoothingframesSliderLabel.Position = [18 110 138 22];
            app.TimesmoothingframesSliderLabel.Text = 'Time smoothing (frames)';

            % Create TimesmoothingframesSlider
            app.TimesmoothingframesSlider = uislider(app.RootFigure);
            app.TimesmoothingframesSlider.Limits = [1 50];
            app.TimesmoothingframesSlider.ValueChangingFcn = createCallbackFcn(app, @TimesmoothingframesSliderValueChanging, true);
            app.TimesmoothingframesSlider.Tooltip = {'Input the number of frames that will be averaged together to improve the signal-to-noise ratio. '};
            app.TimesmoothingframesSlider.Position = [27 89 178 3];
            app.TimesmoothingframesSlider.Value = 1;

            % Create EditField_2
            app.EditField_2 = uieditfield(app.RootFigure, 'numeric');
            app.EditField_2.ValueChangedFcn = createCallbackFcn(app, @EditField_2ValueChanged, true);
            app.EditField_2.Position = [183 110 29 22];

            % Create LoadButton
            app.LoadButton = uibutton(app.RootFigure, 'push');
            app.LoadButton.ButtonPushedFcn = createCallbackFcn(app, @LoadButtonPushed, true);
            app.LoadButton.Position = [9 23 100 22];
            app.LoadButton.Text = 'Load';

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

            % Create ProcessROACheckBox
            app.ProcessROACheckBox = uicheckbox(app.RootFigure);
            app.ProcessROACheckBox.ValueChangedFcn = createCallbackFcn(app, @ProcessROACheckBoxValueChanged, true);
            app.ProcessROACheckBox.Tooltip = {'Turn on or off the ROA proecssing for this channel. '};
            app.ProcessROACheckBox.Text = 'Process ROA';
            app.ProcessROACheckBox.Position = [22 240 94 22];
            app.ProcessROACheckBox.Value = true;

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

    % App creation and deletion
    methods (Access = public)

        % Construct app
        function app = RoaPre(varargin)

            % Create UIFigure and components
            createComponents(app)

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

            % 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.RootFigure)
        end
    end
end