% setup_graphics.m
% Initialize the CMAC simulation graphical user interface
%
% This function creates a comprehensive GUI with multiple visualization panels:
% - Memory visualization (top-left): 2D heatmap of CMAC memory weights
% - Output comparison (top-right): learned vs. target function
% - Input selection (middle): interactive curve for selecting training points
% - Bucket visualization (bottom): shows which buckets are activated
% - Control buttons and parameter inputs

% Create and configure main figure window
clf reset            % Clear figure and reset properties
blackBackground(gcf)
set(gcf,'Units','normalized','Name','CMAC Simulation')

% Create memory visualization panel (top-left)
ax_mem = axes('Position',[0.05 0.52 0.40 0.45]);
% Display CMAC memory as a 32x32 heatmap (1024 = 32*32 memory locations)
h_mem = surf(0:31,0:31,zeros(32));
view([0 90])                    % Top-down view for 2D heatmap
axis([0 31 0 31]), axis off, axis equal  % Square aspect ratio, no axes
clim([-0.04,0.04])             % Set color scale for weight values
colormap(bwr);               % Use bwr colormap (blue=negative, red=positive)

% Create output comparison panel (top-right)
ax_out = axes('Position',[0.55 0.5 0.40 0.45]);
hold on
h_desired = plot(xcoords,ycoords,':','Color','c');  % Target function (cyan, dotted)
h_out = plot(xcoords,0*xcoords,'Color','w');        % CMAC output (white, solid)
axis([0 360 -1.3 1.3])  % Set axis limits for full input range
axis off                % Hide axis labels for cleaner appearance

% Create interactive input selection panel (middle)
ax_in = axes('Position',[0.15 0.30 0.75 0.18]);
hold on
h_in = plot(xcoords,ycoords,'g');              % Target function (green)
axis([0 360 -1.2 1.2])                        % Set axis limits
box off                                        % Remove box around plot
set(ax_in,'Xtick',[0 90 180 270 360])         % Show degree markers
set(ax_in,'ButtonDownFcn','clickhandler')     % Enable clicking on axes
set(h_in,'ButtonDownFcn','clickhandler')      % Enable clicking on curve
title('Click on the green curve to sample data points','Color','g')

% Create bucket visualization panel (bottom)
ax_hist = axes('Position',[0.15 0.18 0.75 0.10]);
hold on;
xlabel('Buckets in Input Space (0-359)');      % X-axis shows input degrees
ylabel('Hash #');                              % Y-axis shows hash table number
set(ax_hist, 'YDir', 'reverse');              % Hash 1 at top, higher numbers below
axis([0 360 0 Nhashes+1]);                    % Set axis limits
set(ax_hist,'Xtick',[0 90 180 270 360])         % Show degree markers
box on;                                        % Show box around plot
set(ax_hist, 'XColor', 'w', 'YColor', 'w');   % White axis labels

% Draw bucket rectangles for each hash table
g_h_hist_bars = cell(Nhashes * Nbuckets_per_hash, 1);  % Store patch handles
bmin_matrix = mod(reshape(bmin, Nhashes, Nbuckets_per_hash), 360);  % Bucket start positions
bmax_matrix = mod(reshape(bmax, Nhashes, Nbuckets_per_hash), 360);  % Bucket end positions
inactive_color = [0.4 0.4 0.4];  % Gray color for inactive buckets

% Draw bucket rectangles for each hash table
for i = 1:Nhashes
  for j = 1:Nbuckets_per_hash
    x_min = bmin_matrix(i,j);  % Bucket start position
    x_max = bmax_matrix(i,j);  % Bucket end position
    y_pos = i - 0.4;           % Vertical position for this hash
    height = 0.8;              % Height of bucket rectangle

    idx = sub2ind([Nhashes, Nbuckets_per_hash], i, j);  % Linear index

    % Handle wrap-around buckets that cross the 0/360 boundary
    if x_min > x_max
      % Split bucket into two parts: [x_min, 359] and [0, x_max]
      p1 = patch([x_min 359 359 x_min], [y_pos y_pos y_pos+height y_pos+height], inactive_color);
      p2 = patch([0 x_max x_max 0], [y_pos y_pos y_pos+height y_pos+height], inactive_color);
      g_h_hist_bars{idx} = [p1, p2];  % Store both patch handles
    else
      % Normal bucket that doesn't wrap around
      p = patch([x_min x_max x_max x_min], [y_pos y_pos y_pos+height y_pos+height], inactive_color);
      g_h_hist_bars{idx} = p;  % Store single patch handle
    end
  end
end

% Create control buttons (bottom row)
reset_button = ...
    uicontrol('Style','Pushbutton', ...
              'Units','Pixels', 'Position',[3 3 60 20], ...
              'BackgroundColor',[1 0.6 0.6], 'ForegroundColor', [0 0 0], 'String','Reset', ...
              'Callback','reset_cmac');  % Clear memory and training points

sample_button = ...
    uicontrol('Style','Pushbutton', ...
              'Units','Pixels', 'Position',[70 3 60 20], ...
              'BackgroundColor',[1 1 0], 'ForegroundColor', [0 0 0], 'String','Sample', ...
              'CallBack','sample_point;plot_cmac');  % Sample one random point

sample_10_button = ...
    uicontrol('Style','Pushbutton', ...
              'Units','Pixels', 'Position',[140 3 30 20], ...
              'BackgroundColor',[1 1 0],'String','x 10', 'ForegroundColor', [0 0 0], ...
              'CallBack','for i=1:10,sample_point,end,plot_cmac');  % Sample 10 random points

sample_50_button = ...
    uicontrol('Style','Pushbutton', ...
              'Units','Pixels', 'Position',[180 3 30 20], ...
              'BackgroundColor',[1 1 0], 'ForegroundColor', [0 0 0], 'String','x 50', ...
              'CallBack','for i=1:50,sample_point,end,plot_cmac');  % Sample 10 random points

function_menu = ...
    uicontrol('Style','Popup', ...
              'Units','Pixels', 'Position',[220 3 80 20], ...
              'BackgroundColor',[0.2 1 0.2], 'ForegroundColor', [0 0 0], ...
              'String',{'sin(x)','sin(3x)','sin(8x)','steps','random'}, ...
              'Value',func_mode, ...
              'CallBack','setup_data_points');  % Change target function

train_button = ...
    uicontrol('Style','Pushbutton', ...
              'Units','Pixels', 'Position',[310 3 70 20], ...
              'BackgroundColor',[1 1 0],'ForegroundColor', [0 0 0], 'String','Rehearse', ...
              'CallBack','for i=1:size(training_points,1),pcoords=training_points(i,:);train_point,end,plot_cmac');  % Retrain on all points

bucketmode_menu = ...
    uicontrol('Style','Popup', ...
              'Units','Pixels', 'Position',[390 3 100 20], ...
              'BackgroundColor',[0.2 1 0.2], 'ForegroundColor', [0 0 0], ...
              'String',{'Randon','Sequential'}, ...
              'Value',bucket_mode, ...
              'CallBack','setup_bucket_mode');  % Switch bucket assignment mode

% Create parameter control row (second row from bottom)
param_row_y = 33;

% Number of hash tables control
tx = 10; tw=80;
uicontrol('Style','text', 'Position',[tx param_row_y tw 20], ...
          'BackgroundColor',[0 0 0], 'ForegroundColor',[0.8 0.8 1], ...
          'String','N Hashes:');
tx = tx + tw + 10;
tw = 40;
uicontrol('Style','edit', 'Position',[tx param_row_y tw 20], ...
          'String',num2str(Nhashes), ...
          'BackgroundColor',[0.8 0.8 1], 'ForegroundColor', [0 0 0], ...
          'Tag','nhashes_box', ...
          'Callback','update_bucket_params');  % Update number of hash tables

% Number of buckets per hash control
tx = tx + tw + 20;
tw = 120;
uicontrol('Style','text', 'Position',[tx param_row_y tw 20], ...
          'BackgroundColor',[0 0 0], 'ForegroundColor',[0.8 0.8 1], ...
          'String','N Buckets/Hash:');
tx = tx + tw + 10;
tw = 60;
uicontrol('Style','edit', 'Position',[tx param_row_y tw 20], ...
          'String',num2str(Nbuckets_per_hash), ...
          'BackgroundColor',[0.8 0.8 1], 'ForegroundColor', [0 0 0], ...
          'Tag','nbuckets_box', ...
          'Callback','update_bucket_params');  % Update buckets per hash table

% Hash stride (offset between hash tables) control
tx = tx + tw + 20;
tw = 120;
uicontrol('Style','text', 'Position',[tx param_row_y tw 20], ...
          'BackgroundColor',[0 0 0], 'ForegroundColor',[0.8 0.8 1], ...
          'String','Hash Stride(°):');
tx = tx + tw + 10;
tw = 40;
uicontrol('Style','edit', 'Position',[tx param_row_y tw 20], ...
          'String',num2str(hash_stride), ...
          'BackgroundColor',[0.8 0.8 1], 'ForegroundColor', [0 0 0], ...
          'Tag','hashstride_box', ...
          'Callback','update_bucket_params');  % Update hash table offset

% Learning rate control
tx = tx + tw + 20;
tw = 100;
uicontrol('Style','Text', ...
          'Units','Pixels', 'Position',[tx param_row_y tw 20], ...
          'BackgroundColor',[0 0 0], 'ForegroundColor',[0.8 0.8 1], ...
          'String','Learning rate:');
tx = tx + tw + 10;
tw = 70;
uicontrol('Style','Edit', ...
          'Units','Pixels', 'Position',[tx param_row_y tw 20], ...
          'BackgroundColor',[0.8 0.8 1], 'ForegroundColor', [0 0 0], ...
          'String',num2str(g_val), ...
          'CallBack','setup_g_value');  % Update learning rate
