classdef PlottingTool < matlab.apps.AppBase

    % Properties that correspond to app components
    properties (Access = public)
        UIFigure         matlab.ui.Figure
        GridLayout       matlab.ui.container.GridLayout
        GridLayout3      matlab.ui.container.GridLayout
        status           matlab.ui.control.Label
        generate         matlab.ui.control.Button
        heartGrid        matlab.ui.container.GridLayout
        line             matlab.ui.control.Label
        GridLayout2      matlab.ui.container.GridLayout
        currentPath      matlab.ui.control.EditField
        PathLabel        matlab.ui.control.Label
        loadBtn          matlab.ui.control.Button
        selectFolderBtn  matlab.ui.control.Button
    end

    
    properties (Access = private)
        fileSettings = {};      %Elements of the header rows
        figureBoxes = {};       %Elements of the channel rows
        tdmsFiles = {};         %TDMS file names
        csvFiles = {};          %CSV file names
        channels = {};          %Channel names of each file
        headerBoxes = {};       %Elements of the header Row
    end

    methods (Access = private)

        % Value changed function: CheckBox, DOES NOT WORK YET
        function checkboxValueChanged(app, event)
            for file = 1:length(app.tdmsFiles) + length(app.csvFiles)
                if app.fileSettings{file}{2}.Value == true
                    app.fileSettings{file}{3}.Enable = 'Off';
                else
                    app.fileSettings{file}{3}.Enable = 'On';
                end
            end
        end
        
        function checkboxToggleGraph(app, event)
            for files = 1:length(app.tdmsFiles) + length(app.csvFiles)
                for channelIt = 1:length(app.channels{files}) 
                    app.figureBoxes{2}{files}{channelIt}.Value = app.headerBoxes{2}.Value;
                end
            end
        end

        function checkboxToggleFourier(app, event)
            for files = 1:length(app.tdmsFiles) + length(app.csvFiles)
                for channelIt = 1:length(app.channels{files}) 
                    app.figureBoxes{3}{files}{channelIt}.Value = app.headerBoxes{3}.Value;
                end
            end
        end

        function checkboxToggleMovmean(app, event)
            for files = 1:length(app.tdmsFiles) + length(app.csvFiles)
                for channelIt = 1:length(app.channels{files}) 
                    app.figureBoxes{4}{files}{channelIt}.Value = app.headerBoxes{4}.Value;
                end
            end
        end

        function checkboxToggleDerivative(app, event)
            for files = 1:length(app.tdmsFiles) + length(app.csvFiles)
                for channelIt = 1:length(app.channels{files}) 
                    app.figureBoxes{5}{files}{channelIt}.Value = app.headerBoxes{5}.Value;
                end
            end
        end

        function defaultStartChange(app, event)
            for files = 1:length(app.tdmsFiles) + length(app.csvFiles)
                for channelIt = 1:length(app.channels{files}) 
                    app.figureBoxes{7}{files}{channelIt}.Value = app.headerBoxes{7}.Value;
                end
            end
        end

        function defaultStopChange(app, event)
            for files = 1:length(app.tdmsFiles) + length(app.csvFiles)
                for channelIt = 1:length(app.channels{files}) 
                    app.figureBoxes{9}{files}{channelIt}.Value = app.headerBoxes{9}.Value;
                end
            end
        end
    end
    

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

        % Code that executes after component creation
        function startupFcn(app)
            close all
            clear all
        end

        % Button pushed function: selectFolderBtn
        function selectFolderBtnButtonPushed(app, event)
            try
                %Open file dialog and get path
                selpath = uigetdir('C:\');
                app.currentPath.Value = selpath;
            catch exception
                app.status.Text = exception.message;
            end
        end

        % Button pushed function: loadBtn
        function loadBtnButtonPushed(app, event)
            % Reset heartGrid
            app.heartGrid = uigridlayout(app.GridLayout);
            app.heartGrid.ColumnWidth = {'1x'};
            app.heartGrid.RowHeight = {'1x'};
            app.heartGrid.Layout.Row = 3;
            app.heartGrid.Layout.Column = 1;
            app.heartGrid.Scrollable = 'on';

            %Deactivate buttons and set busy text
            app.status.Text = 'Status: BUSY - Load data';
            app.loadBtn.Enable = "off";
            app.generate.Enable = "off";
            drawnow

            %search for tdms files
            app.tdmsFiles=dir(append(app.currentPath.Value,'\*.tdms'));
            app.csvFiles=dir(append(app.currentPath.Value,'\*.csv'));
            app.csvFiles= cat(1,app.csvFiles, dir(append(app.currentPath.Value,'\*.txt')));

            %load channels from files
            app.channels = loadChannels(app.currentPath.Value, app.tdmsFiles, app.csvFiles);

            rowSetup = {'fit'};
            
            %Fill the row setup cell array
            counter = 2;
            for i = 1:(length(app.tdmsFiles) + length(app.csvFiles) )
                rowSetup{counter} = 'fit';
                counter = counter + 1;
                for y = 1:length(app.channels{i})
                    rowSetup{counter} = 'fit';
                    counter = counter + 1;
                end
                rowSetup{counter} = '1x';
                counter = counter + 1;
            end
        

            %set the row setup cell array
            app.heartGrid.RowHeight = rowSetup;

            %Label
            fileLabel = uilabel(app.heartGrid);
            fileLabel.Text = "Defaults:";
            fileLabel.Layout.Row = 1;
            fileLabel.Layout.Column = 1;
            fileLabel.FontSize = 15;
            fileLabel.FontWeight = 'bold';

            %Toggle All Graphs Checkbox
            choose = uicheckbox(app.heartGrid);
            choose.Value = 1;
            choose.Layout.Row = 1;
            choose.Layout.Column = 2;
            choose.Text = 'Toggle All Graphs';
            choose.ValueChangedFcn = createCallbackFcn(app, @checkboxToggleGraph, true);
            app.headerBoxes{2} = choose; 

            %Toggle All Fourier Checkbox
            choose = uicheckbox(app.heartGrid);
            choose.Value = 1;
            choose.Layout.Row = 1;
            choose.Layout.Column = 3;
            choose.Text = 'Toggle All Fourier';
            choose.ValueChangedFcn = createCallbackFcn(app, @checkboxToggleFourier, true);
            app.headerBoxes{3} = choose; 

            %Toggle All Movmean Checkbox
            choose = uicheckbox(app.heartGrid);
            choose.Value = 1;
            choose.Layout.Row = 1;
            choose.Layout.Column = 4;
            choose.Text = 'Toggle All Movmean';
            choose.ValueChangedFcn = createCallbackFcn(app, @checkboxToggleMovmean, true);
            app.headerBoxes{4} = choose; 

            %Toggle All Derivative Checkbox
            choose = uicheckbox(app.heartGrid);
            choose.Value = 1;
            choose.Layout.Row = 1;
            choose.Layout.Column = 5;
            choose.Text = 'Toggle All Derivative';
            choose.ValueChangedFcn = createCallbackFcn(app, @checkboxToggleDerivative, true);
            app.headerBoxes{5} = choose; 

            %Default Start Value
            channelLabel = uilabel(app.heartGrid);                         
            channelLabel.Text = "Default Start";
            channelLabel.FontSize = 12;
            channelLabel.HorizontalAlignment = 'right';
            channelLabel.Layout.Row = 1;  
            channelLabel.Layout.Column = 6;

            choose = uieditfield(app.heartGrid);
            choose.Value = '0';
            choose.Layout.Row = 1;
            choose.Layout.Column = 7;
            choose.ValueChangedFcn = createCallbackFcn(app, @defaultStartChange, true);
            app.headerBoxes{7} = choose;

            %Default Stop Value
            channelLabel = uilabel(app.heartGrid);                         
            channelLabel.Text = "Default Stop";
            channelLabel.FontSize = 12;
            channelLabel.HorizontalAlignment = 'right';
            channelLabel.Layout.Row = 1;  
            channelLabel.Layout.Column = 8;

            choose = uieditfield(app.heartGrid);
            choose.Value = '0';
            choose.Layout.Row = 1;
            choose.Layout.Column = 9;
            choose.ValueChangedFcn = createCallbackFcn(app, @defaultStopChange, true);
            app.headerBoxes{9} = choose;

            %Default Stop Value
            channelLabel = uilabel(app.heartGrid);                         
            channelLabel.Text = "Movmean Order";
            channelLabel.FontSize = 12;
            channelLabel.HorizontalAlignment = 'right';
            channelLabel.Layout.Row = 1;  
            channelLabel.Layout.Column = 10;

            choose = uieditfield(app.heartGrid);
            choose.Value = '20';
            choose.Layout.Row = 1;
            choose.Layout.Column = 11;
            choose.ValueChangedFcn = createCallbackFcn(app, @defaultStopChange, true);
            app.headerBoxes{11} = choose;

            %create labels, checkbox and edits in the first column
            counter = 2;
            app.fileSettings = {};
            for files = 1:length(app.tdmsFiles) + length(app.csvFiles)

                % switches from TDMS to CSV after running out of TDMS files
                if files > length(app.tdmsFiles)
                    fileName = app.csvFiles(files - length(app.tdmsFiles)).name;
                else
                    fileName = app.tdmsFiles(files).name;
                end

                %Label
                fileLabel = uilabel(app.heartGrid);
                fileLabel.Text = fileName;
                fileLabel.Layout.Row = counter;
                fileLabel.Layout.Column = 1;
                fileLabel.FontSize = 15;
                fileLabel.FontWeight = 'bold';

                %Folder name
                channelLabel = uilabel(app.heartGrid);                         
                channelLabel.Text = "Folder name:";
                channelLabel.FontSize = 12;
                channelLabel.HorizontalAlignment = 'right';
                channelLabel.Layout.Row = counter;  
                channelLabel.Layout.Column = 2;     

                %Folder name edit
                choose = uieditfield(app.heartGrid);
                choose.Value = fileName;
                choose.Layout.Row = counter;
                choose.Layout.Column = 3;
                app.fileSettings{files}{1} = choose;

                %Checkbox increment
                choose = uicheckbox(app.heartGrid);
                choose.Layout.Row = counter;
                choose.Layout.Column = 4;
                choose.Text = 'First row secs';
                choose.ValueChangedFcn = createCallbackFcn(app, @checkboxValueChanged, true);
                app.fileSettings{files}{2} = choose;

                %Increment label
                channelLabel = uilabel(app.heartGrid);                         
                channelLabel.Text = "Increment:";
                channelLabel.FontSize = 12;
                channelLabel.HorizontalAlignment = 'right';
                channelLabel.Layout.Row = counter;  
                channelLabel.Layout.Column = 5;

                %Increment edit
                choose = uieditfield(app.heartGrid, 'numeric');
                choose.Value = 0.001;
                choose.Layout.Row = counter;
                choose.Layout.Column = 6;
                app.fileSettings{files}{3} = choose;


                counter = counter + 1;
                for channelIt = 1:length(app.channels{files})
                    channelLabel = uilabel(app.heartGrid);
                    channelLabel.Text = app.channels{files}{channelIt};
                    channelLabel.FontSize = 13;
                    channelLabel.Layout.Row = counter;  
                    channelLabel.Layout.Column = 1;
                    counter = counter + 1;
                end
                counter = counter + 1;
            end
  
            
            %Setup column names and column setup
            columnNames = {'Graph', 'Fourier', 'Movmean', 'Derivative' ,'Start:', 'startEdit', 'End:', 'endEdit', 'Y-Axis:', 'yEdit', 'X-Axis:', 'xEdit'};
            columnSetup = {'1x', '1x', '1x', '1x', 'fit', '1x', 'fit', '1x', 'fit', '1x', 'fit'};
            app.heartGrid.ColumnWidth = columnSetup;
            
            %Create labels, checkboxes and editfields in all the columns
            for column = 2:length(columnNames)+1

                %Create Checkboxes
                if column-1 <= 4
                    counter = 2;
                    for files = 1:length(app.tdmsFiles) + length(app.csvFiles)
                        counter = counter + 1;
                        for channelIt = 1:length(app.channels{files}) 
                            choose = uicheckbox(app.heartGrid);
                            choose.Value = 1;
                            choose.Layout.Row = counter;
                            choose.Layout.Column = column;
                            choose.Text = columnNames{column-1};
                            app.figureBoxes{column}{files}{channelIt} = choose;
                            counter = counter + 1;
                        end
                        counter = counter + 1;
                    end
                end

                %Create labels and editfields
                if column-1 > 4
                    counter = 2;
                    for files = 1:length(app.tdmsFiles) + length(app.csvFiles)
                        counter = counter + 1;
                        for channelIt = 1:length(app.channels{files})
                            
                            %Create labels
                            if mod(column,2) == 0
                                channelLabel = uilabel(app.heartGrid);                         
                                channelLabel.Text = columnNames{column-1};
                                channelLabel.FontSize = 12;
                                channelLabel.HorizontalAlignment = 'right';
                                channelLabel.Layout.Row = counter;  
                                channelLabel.Layout.Column = column;
                                counter = counter + 1;

                            %Create edit fields
                            else
                                choose = uieditfield(app.heartGrid);
                                choose.Value = '0';
                                choose.Layout.Row = counter;
                                choose.Layout.Column = column;
                                app.figureBoxes{column}{files}{channelIt} = choose;
                                counter = counter + 1;
                            end
                        
                        end

                        counter = counter + 1;
                    end
                end

            end

            % Set default values for y-Axis
            for file = 1:length(app.figureBoxes{11})
                for channel = 1:length(app.figureBoxes{11}{file})
                    app.figureBoxes{11}{file}{channel}.Value = 'degree celsius [°C]';
                end
            end

            % Set default values for x-Axis
            for file = 1:length(app.figureBoxes{13})
                for channel = 1:length(app.figureBoxes{13}{file})
                    app.figureBoxes{13}{file}{channel}.Value = 'Time [s]';
                end
            end


            %Change label back to normal
            app.status.Text = 'Developed by Space Team Aachen e.V.';
            app.loadBtn.Text = 'Already loaded';
            app.generate.Enable = "on";

        end

        % Button pushed function: generate
        function generateButtonPushed(app, event)
            %Disable all fields
            for file = 1:length(app.tdmsFiles) + length(app.csvFiles)
                for channel = 1:length(app.channels{file})
                    app.figureBoxes{2}{file}{channel}.Enable = "off";
                    app.figureBoxes{3}{file}{channel}.Enable = "off";
                    app.figureBoxes{4}{file}{channel}.Enable = "off";
                    app.figureBoxes{5}{file}{channel}.Enable = "off";
                    app.figureBoxes{7}{file}{channel}.Enable = "off";
                    app.figureBoxes{9}{file}{channel}.Enable = "off";
                    app.figureBoxes{11}{file}{channel}.Enable = "off";
                    app.figureBoxes{13}{file}{channel}.Enable = "off";
                end
                app.fileSettings{file}{1}.Enable = "off";
                app.fileSettings{file}{2}.Enable = "off";
                app.fileSettings{file}{3}.Enable = "off";
            end
            %Disable top fields
            app.headerBoxes{2}.Enable = "off";
            app.headerBoxes{3}.Enable = "off";
            app.headerBoxes{4}.Enable = "off";
            app.headerBoxes{5}.Enable = "off";
            app.headerBoxes{7}.Enable = "off";
            app.headerBoxes{9}.Enable = "off";
            app.headerBoxes{11}.Enable = "off";

            drawnow
            
            %get saving location
            try
                %Open file dialog and get path
                selpath = uigetdir('C:\');
            catch exception
                app.status.Text = exception.message;
            end
            
            %Change label to busy
            app.status.Text = 'Status: BUSY - Gernerating Plots';
            app.generate.Enable = "off";
            drawnow
            
            %Load Data
            data = loadData(app.tdmsFiles, app.csvFiles);
            
            %React to user settings and call subfunctions for plotting
            for file = 1:length(app.tdmsFiles) + length(app.csvFiles)    

                %Plot Graph - Parameter: data, fileSettings, checkboxes,
                %start, stop, yAxis, xAxis, channels, path
                graphPlotFnc(data{file}, app.fileSettings{file}, app.figureBoxes{2}{file}, app.figureBoxes{7}{file}, ...
                    app.figureBoxes{9}{file}, app.figureBoxes{11}{file}, app.figureBoxes{13}{file}, ...
                    app.channels{file}, selpath);

                %Plot Mean - Parameter: data, fileSettings, checkboxes,
                %start, stop, yAxis, xAxis, channels, path, order
                meanPlotFnc(data{file}, app.fileSettings{file}, app.figureBoxes{4}{file}, app.figureBoxes{7}{file}, ...
                    app.figureBoxes{9}{file}, app.figureBoxes{11}{file}, app.figureBoxes{13}{file}, ...
                    app.channels{file}, selpath, app.headerBoxes{11}.Value); 

                %Plot Fourier - Parameter: data, fileSettings, checkboxes,
                %start, stop, yAxis, xAxis, channels, path
                fourierPlotFnc(data{file}, app.fileSettings{file}, app.figureBoxes{3}{file}, app.figureBoxes{7}{file}, ...
                    app.figureBoxes{9}{file}, app.figureBoxes{11}{file}, app.figureBoxes{13}{file}, ...
                    app.channels{file}, selpath); 

                %Plot Derivative - Parameter: data, fileSettings, checkboxes,
                %start, stop, yAxis, xAxis, channels, path
                diffPlotFnc(data{file}, app.fileSettings{file}, app.figureBoxes{5}{file}, app.figureBoxes{7}{file}, ...
                    app.figureBoxes{9}{file}, app.figureBoxes{11}{file}, app.figureBoxes{13}{file}, ...
                    app.channels{file}, selpath); 

            end

            %Enable all fields
            for file = 1:length(app.tdmsFiles) + length(app.csvFiles)
                for channel = 1:length(app.channels{file})
                    app.figureBoxes{2}{file}{channel}.Enable = "on";
                    app.figureBoxes{3}{file}{channel}.Enable = "on";
                    app.figureBoxes{4}{file}{channel}.Enable = "on";
                    app.figureBoxes{5}{file}{channel}.Enable = "on";
                    app.figureBoxes{7}{file}{channel}.Enable = "on";
                    app.figureBoxes{9}{file}{channel}.Enable = "on";
                    app.figureBoxes{11}{file}{channel}.Enable = "on";
                    app.figureBoxes{13}{file}{channel}.Enable = "on";
                end
                app.fileSettings{file}{1}.Enable = "on";
                app.fileSettings{file}{2}.Enable = "on";
                app.fileSettings{file}{3}.Enable = "on";
            end
            %Enable top fields
            app.headerBoxes{2}.Enable = "on";
            app.headerBoxes{3}.Enable = "on";
            app.headerBoxes{4}.Enable = "on";
            app.headerBoxes{5}.Enable = "on";
            app.headerBoxes{7}.Enable = "on";
            app.headerBoxes{9}.Enable = "on";
            app.headerBoxes{11}.Enable = "on";

            %Reactivate buttons and reset text
            app.status.Text = 'Developed by Space Team Aachen e.V.';
            app.generate.Enable = "on";

            %Renable load
            app.loadBtn.Enable = "on";
            app.loadBtn.Text = 'Load';
        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 1210 770];
            app.UIFigure.Name = 'MATLAB App';

            % Create GridLayout
            app.GridLayout = uigridlayout(app.UIFigure);
            app.GridLayout.ColumnWidth = {'1x'};
            app.GridLayout.RowHeight = {'fit', 'fit', '1x', 'fit'};
            app.GridLayout.Scrollable = 'on';

            % Create GridLayout2
            app.GridLayout2 = uigridlayout(app.GridLayout);
            app.GridLayout2.ColumnWidth = {'fit', 'fit', '1x', 'fit'};
            app.GridLayout2.RowHeight = {'1x'};
            app.GridLayout2.Layout.Row = 1;
            app.GridLayout2.Layout.Column = 1;

            % Create selectFolderBtn
            app.selectFolderBtn = uibutton(app.GridLayout2, 'push');
            app.selectFolderBtn.ButtonPushedFcn = createCallbackFcn(app, @selectFolderBtnButtonPushed, true);
            app.selectFolderBtn.FontSize = 15;
            app.selectFolderBtn.Layout.Row = 1;
            app.selectFolderBtn.Layout.Column = 1;
            app.selectFolderBtn.Text = 'Select Folder';

            % Create loadBtn
            app.loadBtn = uibutton(app.GridLayout2, 'push');
            app.loadBtn.ButtonPushedFcn = createCallbackFcn(app, @loadBtnButtonPushed, true);
            app.loadBtn.FontSize = 15;
            app.loadBtn.Layout.Row = 1;
            app.loadBtn.Layout.Column = 4;
            app.loadBtn.Text = 'Load';

            % Create PathLabel
            app.PathLabel = uilabel(app.GridLayout2);
            app.PathLabel.HorizontalAlignment = 'right';
            app.PathLabel.Layout.Row = 1;
            app.PathLabel.Layout.Column = 2;
            app.PathLabel.Text = 'Path:';

            % Create currentPath
            app.currentPath = uieditfield(app.GridLayout2, 'text');
            app.currentPath.Placeholder = 'C:\Users\max_h\Desktop\Testkampagne\data\coldflow\Data\STACF\02';
            app.currentPath.Layout.Row = 1;
            app.currentPath.Layout.Column = 3;
            app.currentPath.Value = 'C:\Users\max_h\Desktop\Testkampagne\data\coldflow\Data\STACF\02';

            % Create line
            app.line = uilabel(app.GridLayout);
            app.line.BackgroundColor = [0 0 0];
            app.line.FontSize = 0.3;
            app.line.Layout.Row = 2;
            app.line.Layout.Column = 1;

            % Create heartGrid
            app.heartGrid = uigridlayout(app.GridLayout);
            app.heartGrid.ColumnWidth = {'1x'};
            app.heartGrid.RowHeight = {'1x'};
            app.heartGrid.Layout.Row = 3;
            app.heartGrid.Layout.Column = 1;
            app.heartGrid.Scrollable = 'on';

            % Create GridLayout3
            app.GridLayout3 = uigridlayout(app.GridLayout);
            app.GridLayout3.ColumnWidth = {'1x', '1.5x'};
            app.GridLayout3.RowHeight = {'1x'};
            app.GridLayout3.Layout.Row = 4;
            app.GridLayout3.Layout.Column = 1;

            % Create generate
            app.generate = uibutton(app.GridLayout3, 'push');
            app.generate.ButtonPushedFcn = createCallbackFcn(app, @generateButtonPushed, true);
            app.generate.Enable = 'off';
            app.generate.Layout.Row = 1;
            app.generate.Layout.Column = 2;
            app.generate.Text = 'Generate Plots';

            % Create status
            app.status = uilabel(app.GridLayout3);
            app.status.VerticalAlignment = 'bottom';
            app.status.Layout.Row = 1;
            app.status.Layout.Column = 1;
            app.status.Text = 'Developed by Space Team Aachen e.V.';

            % 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 = PlottingTool

            % Create UIFigure and components
            createComponents(app)

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

            % Execute the startup function
            runStartupFcn(app, @startupFcn)

            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