classdef MatlabPathManager
    properties
        projectFileName = '.subpaths';
        stateFileName = 'state';
    end

    methods
        function obj = MatlabPathManager()
        end

        function p = stateFilePath(obj)
            p = fullfile(mpm.install_location(), obj.stateFileName);
        end

        % Load a given subpath into the state file and the matlab path and do savepath(), atomically
        function loadSubpath(obj, p)
            state = mpm.PersistentState(obj.stateFilePath);

            addpath(p);
            state.added_paths(p) = true;

            state.saveState();

            % TODO: Add savepath()
        end

        % Unload a given subpath from the state file and the matlab path and do savepath(), atomically
        function unloadSubpath(obj, p)
            state = mpm.PersistentState(obj.stateFilePath);

            rmpath(p);
            state.added_paths.remove(p);

            state.saveState();

            % TODO: Add savepath()
        end

        % Read project file in a folder and return cell array of all subpaths
        function sp = projectSubpaths(obj, projectFolder)
            try
                fstr = fileread(fullfile(projectFolder, obj.projectFileName));
            catch
                error('Subpath definition file ''%s'' not found.', obj.projectFileName);
            end
            sp = splitlines(strtrim(fstr));
        end

        function s = loadedSubpaths(obj)
            state = mpm.PersistentState(obj.stateFilePath);
            s = state.added_paths.keys();
            % TODO: Make it respect order from the matlab path
        end

        function ps = matlabPath(obj)
            ps = split(path(), pathsep);
        end

        % Return all subpaths loaded into the matlab path, mimicing the order they appear there.
        function s = pathStatus(obj)
        end

        % Return all subpaths in the project and if they are active on the matlab path or not.
        function s = projectStatus(obj, projectFolder)
        end

        % Load all subpaths for a project
        function checkin(obj, projectFolder)
            sp = obj.projectSubpaths(projectFolder);

            for i = 1:length(sp)
                fullSubpath = fullfile(projectFolder, sp{i});
                obj.loadSubpath(fullSubpath);
            end
        end

        % Unload all subpaths for a project
        function checkout(obj, projectFolder)
            sp = obj.projectSubpaths(projectFolder);

            for i = 1:length(sp)
                fullSubpath = fullfile(projectFolder, sp{i});
                obj.unloadSubpath(fullSubpath);
            end
        end

        % Check if the projects settings are correct
        % Is the project file correct?
        % The right version is in the matlab path
        % The right version is at the top of the path
        function b = verify(obj, projectFolder)
            mpath = obj.matlabPath();
            sp = obj.projectSubpaths(projectFolder);

            for i = 1:length(sp)
                if ~isAtTop(sp{i}, fullfile(projectFolder, sp{i}), mpath)
                    b = false;
                    return;
                end
            end
            b = true;

            function b = isAtTop(subpath, fullsubpath, paths)
                for i = 1:length(paths)
                    if ~endsWith(paths{i}, subpath)
                        continue
                    end

                    b = strcmp(fullsubpath, paths{i});
                    return
                end

                b = false;
            end

            % TODO: Refactor this into several methods?
        end

        % Unload all loaded subpaths. The matlab path should be returned to it's original state
        function clear(obj)
            sp = obj.loadedSubpaths();

            for i = 1:length(sp)
                obj.unload(sp{i});
            end
        end
    end
end
