classdef SettingsManager < handle
    %SETTINGSMANAGER Store and retrieve settings data.
    %   We'll load the data when initialized and set properties which other
    %   objects can discover. Also, "savesettings" will write updated
    %   properties. We'll just assume everything goes through the
    %   object properties.
    
    properties
        root
        ui
        
        serialport;
        filedir;
        
        acquireconnect;
        loadprogramconnect;
        stopconnect;
        autopause;
    end
    
    methods
        function obj = SettingsManager()
            obj.ui = [];
            obj.LoadSettings();
        end
        
        function ShowPreferencesUI(obj)
            if isempty(obj.ui)
                obj.ui = settingsui();
                set(obj.ui, 'UserData', obj);
                obj.updateGUI();
            elseif ishandle(obj.ui)
                set(obj.ui, 'Visible', 'on');
            end
        end
        
        function updateGUI(obj)
            handles = guidata(obj.ui);
            set(handles.ledsonconnect, 'Value', obj.acquireconnect);
            set(handles.programsonconnect, 'Value', obj.loadprogramconnect);
            set(handles.stoponconnect, 'Value', obj.stopconnect);
            set(handles.autopause, 'Value', obj.autopause);
        end
        
        function LoadSettings(obj)
            try
                obj.root = xmlread('settings.xml');
            catch error
                disp(['XML Read Error: ' error.message]);
                obj.NewSettingsFile();
                obj.ResetSettings();
            end
            
            obj.serialport = obj.getValue('serial');
            obj.filedir = obj.getValue('directory');
            obj.acquireconnect = str2double(obj.getValue('acquireconnect'));
            obj.loadprogramconnect = str2double(obj.getValue('loadprogramconnect'));
            obj.stopconnect = str2double(obj.getValue('stopconnect'));
            obj.autopause = str2double(obj.getValue('autopause'));
            obj.AddDefaults(); % If we failed to load anything, lets set that to default.
        end
        
        function SaveSettings(obj)
            obj.writeValue('serial', obj.serialport);
            obj.writeValue('directory', obj.filedir);
            
            obj.writeValue('acquireconnect', num2str(obj.acquireconnect));
            obj.writeValue('loadprogramconnect', num2str(obj.loadprogramconnect));
            obj.writeValue('stopconnect', num2str(obj.stopconnect));
            obj.writeValue('autopause', num2str(obj.autopause));
        end
        
        % If we failed to load anything, lets set that to default.
        function AddDefaults(obj)
            if isempty(obj.serialport)
                obj.serialport = 'COM5';
                obj.writeValue('serial', 'COM5');
            end
            if isempty(obj.filedir)
                obj.filedir = 'data';
                obj.writeValue('directory', 'data');
            end
            if isempty(obj.acquireconnect) || isnan(obj.acquireconnect)
                obj.acquireconnect = 0;
                obj.writeValue('acquireconnect', num2str(0));
            end
            if isempty(obj.loadprogramconnect)|| isnan(obj.loadprogramconnect)
                obj.loadprogramconnect = 0;
                obj.writeValue('loadprogramconnect', num2str(0));
            end
            if isempty(obj.stopconnect)|| isnan(obj.stopconnect)
                obj.stopconnect = 0;
                obj.writeValue('stopconnect', num2str(0));
            end
            if isempty(obj.autopause)|| isnan(obj.autopause)
                obj.autopause = 0;
                obj.writeValue('autopause', num2str(0));
            end
            
        end
        
        function ResetSettings(obj)
            obj.serialport = 'COM5';
            obj.writeValue('serial', 'COM5');
            obj.filedir = 'data';
            obj.writeValue('directory', 'data');
            
            obj.acquireconnect = 0;
            obj.writeValue('acquireconnect', num2str(0));
            obj.loadprogramconnect = 0;
            obj.writeValue('loadprogramconnect', num2str(0));
            obj.stopconnect = 0;
            obj.writeValue('stopconnect', num2str(0));
            obj.autopause = 0;
            obj.writeValue('autopause', num2str(0));
        end
        
        function NewSettingsFile(obj)
            obj.root = com.mathworks.xml.XMLUtils.createDocument('settings');
            obj.ResetSettings();
        end
        
        function node = createNode(obj, string)
            %Create node in obj with tag name @string
            node = obj.root.createElement(string);
            obj.root.getDocumentElement().appendChild(node);
        end
        
        function x = getValue(obj, string)
            x = obj.root.getElementsByTagName(string);
            x = x.item(0);
            if ~isempty(x)
                x = char(x.getTextContent());
            else
                x = [];
            end
        end
        
        function x = writeValue(obj, string, value)
            x = obj.root.getElementsByTagName(string);
            x = x.item(0);
            if isempty(x)
                x = obj.createNode(string);
                x.setTextContent(value);
            else
                x.setTextContent(value);
                % This next code may be confusing. What happens is we get a
                % lot of blank text nodes for some reason. The help forums
                % had a simple "Maybe convert it to a string and write that
                % to a file instead of using xmlwrite?" Well I say, that's
                % bogus. Since I have a flat structure, once I've found an
                % item I can just work horizontally to clear all these (at
                % least, traversing the trees in the command window leads
                % me to suspect this is true).
                m = x.getNextSibling();
                while ~isempty(m)
                    m.setTextContent(deblank(char(m.getTextContent())));
                    m = m.getNextSibling();
                end
            end
            xmlwrite('settings.xml', obj.root);
        end
    end
end

