%%%%%%%%%%%
% Publish Script for Octave
% Ben Manning
% 14-11-2025
%
%Creates a markdown file similar to the traditional publish script of MATLAB
%
% In order to make PDF:
% 1. use own personal method to make pdf from md if familiar
%
% 2. use VS code extension Markdown PDF by yzane
%   1. Go to extensions in VS Code and search for  'Markdown PDF' by yzane
%   2. Open md file in VS code
%   3. while on the file in VS code, press F1 or Ctrl+Shift+P
%   4. Type export and select 'markdown-pdf: Export (pdf)'
%   5. PDF will be generated in same directory as md file.
%%%%%%%%%%

clear all;
close all;
warning('off', 'all')


%  USER CONFIGURATION (DEFINE ALL FILES TO BE PUBLISHED HERE)
publisher_name = "Ben Manning";
tasks = {
  struct(
      'target_file', 'functionTest.m',     % File 1: A function with plots
      'args', '40,50,30',                   % Arguments as a string
      'is_function', true,                  % Is a function
      'num_outputs', 1                      % Number of return values
  ),
  struct(
      'target_file', 'scriptTest.m',         % File 2: A simple script
      'args', '',                            % No arguments
      'is_function', false,                  % Is a script
      'num_outputs', 0                       % No return values
  )
  % You can add more structs here to publish additional
};

output_file = 'manning_report_test.md';
% ------------------

disp(sprintf('Starting Octave Publisher for %d tasks', length(tasks)));

fid = fopen(output_file, 'w');
fprintf(fid, '# Octave Publishing Report\n\n');
fprintf(fid, '## Publisher: `%s`\n\n', publisher_name);
fprintf(fid, '---\n\n');



for task_idx = 1:length(tasks)
  % Extract current task configuration
  task = tasks{task_idx};
  target_file = task.target_file;
  args = task.args;
  is_function = task.is_function;
  num_outputs = task.num_outputs;

  file_name_no_ext = strrep(target_file, '.m', '');

  % Initialize results for current task
  R = {}; % Cell array to store all generic return values
  plot_status = 'No figure found to save.';
  plot_files = {}; % List of saved plot filenames
  execution_mode = ifelse(is_function, 'Function', 'Script');

  disp(sprintf('Processing Task %d: %s (%s)...', task_idx, target_file, execution_mode));

  % 1. Read file code content
  if exist(target_file, 'file')
      code_content = fileread(target_file);
  else
      fprintf(fid, '## File %d: `%s` (Error)\n\n**ERROR**: Target file "%s" not found. Skipping.\n\n---\n\n', task_idx, target_file, target_file);
      disp(sprintf('ERROR: Target file "%s" not found. Skipping.', target_file));
      continue; % Skip to next task
  end

  % 2. Setup dynamic assignment and execute file
  try
      if is_function && num_outputs > 0
          % FUNCTION MODE: Capture Outputs
          lhs_names = '';
          for i = 1:num_outputs
              lhs_names = [lhs_names, 'out', num2str(i), ', '];
          end
          lhs_names = ['[', lhs_names(1:end-2), ']'];

          % Command construction: [out1] = functionTest(10, 5, 30);
          cmd = sprintf('%s = %s(%s);', lhs_names, file_name_no_ext, args);
          console_output = evalc(cmd);

          for i = 1:num_outputs
              R{i} = eval(['out', num2str(i)]);
          end

      else
          %  SCRIPT MODE: No Outputs Expected
          cmd = file_name_no_ext;
          console_output = evalc(cmd);
      end

      % 3. Save ALL plots generated by the file
      h_figs = get(0, 'children');
      plot_count_local = 0;

      if ~isempty(h_figs)

          h_figs = sort(h_figs);

          for i = 1:length(h_figs)
              h_fig = h_figs(i);
              plot_count_local = plot_count_local + 1;

              current_plot_file = sprintf('%s_plot_%d.png', file_name_no_ext, plot_count_local);

              % make sure figure is current and visible before saving
              figure(h_fig);
              set(h_fig, 'visible', 'on', 'papersize', [6, 4]);

              print(h_fig, current_plot_file, '-dpng', '-r100');

              plot_files{end+1} = current_plot_file;
          end
          if plot_count_local == 1
            plot_status = sprintf('1 plot found', plot_count_local);
          else
            plot_status = sprintf('%d plots found', plot_count_local);
          end
      else
          plot_status = 'No figures were found to save.';
      end

  catch
      % Handle execution errors
      console_output = lasterror.message;
      R = {};
      plot_status = 'File execution failed due to an error.';
  end

  close all hidden;

  % 4. Append Results to Report

  fprintf(fid, '## File %d: `%s` (%s)\n\n', task_idx, target_file, execution_mode);
  fprintf(fid, '### 1. Code\n\n');
  fprintf(fid, '```matlab\n%s\n```\n\n', code_content);

  fprintf(fid, '### 2. Execution Details\n\n');
  if is_function
      fprintf(fid, 'Arguments Used:\n\n```matlab\n%s\n```\n\n', args);
  end

  fprintf(fid, '### 3. Console Output\n\n');
  fprintf(fid, '```text\n%s\n```\n\n', strtrim(console_output));

  if is_function
      fprintf(fid, '### 4. Function Return Values\n\n');
      if isempty(R) && num_outputs > 0
          fprintf(fid, 'Function did not return expected values (execution error).\n');
      elseif isempty(R) && num_outputs == 0
          fprintf(fid, 'Function executed successfully but was configured to return zero explicit values.\n');
      else
          for i = 1:length(R)
              fprintf(fid, '* **Output #%d:** `%s`\n', i, mat2str(R{i}));
          end
      end
      fprintf(fid, '\n');
  end

  % Plot Section
  fprintf(fid, '### %d. Generated Plot(s)\n\n', ifelse(is_function, 5, 4));

  fprintf(fid, '%s\n\n', plot_status);

  if ~isempty(plot_files)
      for i = 1:length(plot_files)
          fprintf(fid, '#### Plot %d:\n', i);
          fprintf(fid, '![Plot %d Reference](%s)\n\n', i, plot_files{i});
      end
  end

  fprintf(fid, '\n---\n\n');
  disp(sprintf('Task %d (%s) complete.', task_idx, target_file));
end


% REPORT CLOSING


fclose(fid);

disp(sprintf('All %d tasks processed.', length(tasks)));
disp(sprintf('Full report saved to: %s', output_file));