function project(mode)

close all;

% Variables are declared global only because it makes debugging easier.
global SC;

% I'm a C programmer at heart. Thus, #define :
SC.M_MANUAL = 1;
SC.M_LINE   = 2;
SC.M_SPIRAL = 3;

if nargin == 0
    SC.mode = SC.M_MANUAL;
else
    if strcmpi(mode, 'LINE')
        SC.mode = SC.M_LINE;
    elseif strcmpi(mode, 'SPIRAL')
        SC.mode = SC.M_SPIRAL;
    else
        SC.mode = SC.M_MANUAL;
    end
end

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Constants: link budget
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

SC.k               = 1.3806504e-23;
SC.Tsys            = 345;
SC.SNR             = 5; % dB
SC.rfid_bw         = 20e3; % 20 kHz
SC.rfid_gain       = 0; % dBi
SC.rfid_turnon     = -20 - 30;  % -50 dBW turnown for the RFID
SC.rfid_proc_loss  = 0; % dB due to processing
SC.lander_bw       = 600e3; % 600 kHz bandwidth
SC.lander_gain     = 0; % dBi
SC.lander_min_rx   = 10*log10(SC.k*SC.Tsys*SC.lander_bw)+SC.SNR; % -145 dBW
SC.astro_gain      = 0; % dBi
SC.astro_min_rx_fromLander = 10*log10(SC.k*SC.Tsys*SC.lander_bw)+SC.SNR; % dBW
SC.astro_min_rx_fromRFID   = 10*log10(SC.k*SC.Tsys*SC.rfid_bw)+SC.SNR;   % dBW
SC.astro_tx_power  = 10*log10(10); % 10W is the largest that we consider safe
SC.c               = 299792458;    % m/s
SC.f               = 2.43e9;       % 2.43 GHz
SC.lambda          = SC.c/SC.f;    % meters

% This is a 4x3 matrix, since Matlab is column-major.
SC.fade_depth_data = [ 6.27, 4.95, 2; ... % astronaut, height = 2m
                       6.31, 4.98, 3; ... % rover,     height = 3m
                       6.38, 5.26, 5; ... % base,      height = 5m
                       4.32, 5.50, 15];   % tower,     height = 15m
SC.lander_fade_idx = 3; % A "base" seems like a good "lander"

% %99 confidence interval
SC.Mtotal =   SC.fade_depth_data(SC.lander_fade_idx, 1) + ...
            3*SC.fade_depth_data(SC.lander_fade_idx, 2);

% Algebraic manipulation of the NASA paper.
SC.lander_tx_power = log10(2e3).*40 + ...
                     SC.astro_min_rx_fromLander - ...
                     SC.lander_gain - ...
                     SC.astro_gain  - ...
                     2*(10*log10(SC.fade_depth_data(1, 3)) + ...
                        10*log10(SC.fade_depth_data(SC.lander_fade_idx, 3))) + ...
                     SC.Mtotal;
                 
fprintf(1, 'SC.lander_tx_power: %f dBW\n', SC.lander_tx_power);
fprintf(1, 'SC.lander_tx_power: %f mW\n', ...
    10^(SC.lander_tx_power./10)*1e3);
        
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Constants and variables: plot and grid 
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

SC.fig_wo_lander = -1; % -1 is a temporary value. This will be the figure
    % handle for the plots that don't include the lander. "wo" is "without"
SC.fig_with_lander = -1;

SC.xmin = -10;  % -20 meters
SC.xmax =  90; %  20 m
SC.ymin = -10;  % -20 m
SC.ymax =  90; %  20 m
SC.x_count = 250;
SC.y_count = 250;
SC.x_axis  = linspace(SC.xmin, SC.xmax, SC.x_count);
SC.y_axis  = linspace(SC.ymin, SC.ymax, SC.y_count);
[SC.X, SC.Y]  = meshgrid(SC.x_axis, SC.y_axis); % Remember, using (i,j) to
    % index into X and Y means i is the y-coordinate and j is the
    % x-coordinate!
SC.Zmin          = zeros(SC.x_count, SC.y_count);
SC.Zmax          = zeros(SC.x_count, SC.y_count);
SC.Zmax_woLander = zeros(SC.x_count, SC.y_count);
    % The max value at any given (x,y), ignoring the Lander

SC.rfid_max   = 16; % Arbitrary maximum number of RFIDs.
SC.rfid_count = 1;  % RFID #1 is the lander
SC.rfid_locs = zeros(2, SC.rfid_max);

SC.gains          = zeros(SC.x_count, SC.y_count, SC.rfid_max);
SC.gains_woLander = zeros(SC.x_count, SC.y_count, SC.rfid_max-1);
    % the gains with out the lander. "with out" --> "wo"
    
% These two variables keep track of which transponder is the most powerful
% at any given location. In other words, they keep track of the sort order
% alterations made fo SC.gains and SC.gains_woLander
SC.sort_order          = ones(SC.x_count, SC.y_count, SC.rfid_max);
SC.sort_order_woLander = ones(SC.x_count, SC.y_count, SC.rfid_max-1);

for i = 2:SC.rfid_max
    SC.sort_order(:,:,i) = SC.sort_order(:,:,i).*i;
end

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Constants and variables: mode specific
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

switch SC.mode
    case SC.M_LINE
        SC.line_delta = 0.1; % 1 meter
    case SC.M_SPIRAL
        SC.line_delta  = 0.1;
end

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% find the maximum radius for the lander<->astro link
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

% We can use equation 7 from the Foore paper because d >> Ht and Hr for
% this maximum case. The lander and the astronaut might have different
% receive and transmit powers and sensitivities, so we need to compute this
% twice.
lander_range1 = 10.^( (SC.lander_gain     + ...
                       SC.astro_gain      + ...
                       SC.lander_tx_power - ...
                       SC.astro_min_rx_fromLander + ...
                       2*(10*log10(SC.fade_depth_data(1, 3)) + ...
                          10*log10(SC.fade_depth_data(SC.lander_fade_idx, 3))) - ...
                       SC.Mtotal) ./40);
lander_range2 = 10.^( (SC.astro_gain     + ...
                       SC.lander_gain    + ...
                       SC.astro_tx_power - ...
                       SC.lander_min_rx  + ...
                       2*(10*log10(SC.fade_depth_data(1, 3)) + ...
                          10*log10(SC.fade_depth_data(SC.lander_fade_idx, 3))) - ...
                       SC.Mtotal) ./40);
                   
fprintf(1, 'lander->astro range: %f\n', lander_range1);
fprintf(1, 'astro->lander range: %f\n', lander_range2);

if (lander_range1 < lander_range2)
    SC.lander_range = lander_range1;
else
    SC.lander_range = lander_range2;
end

if (SC.lander_range < 2e3)
    fprintf(1, ['Warning: The lander<->astro link range is less than' ...
                ' the 2km required by the project\n']);
end
fprintf(1, 'SC.lander_range: %f\n', SC.lander_range);

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% find the maximum radius for one RFID in the RFID<->astro link
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

% The maximum distance for the (astronaut -> RFID) transmittion
astro_to_rfid = ...
    10.^( ((SC.astro_tx_power + ...
            SC.astro_gain + ...
            SC.rfid_gain - ...
            20.*log10(4*pi./SC.lambda)) ...
           - SC.rfid_turnon) ./ 20);
% The minimum distance for the (RFID -> astro) transmittion
rfid_to_astro = ... % This assumes the rfid received the turnon power
    10.^( (((SC.rfid_turnon -  SC.rfid_proc_loss) + ...
            SC.rfid_gain + ...
            SC.astro_gain  - ...
            20.*log10(4*pi./SC.lambda)) ...
           - SC.astro_min_rx_fromRFID ) ./ 20);

if ( astro_to_rfid < rfid_to_astro )
    SC.rfid_range = astro_to_rfid;
else
    SC.rfid_range = rfid_to_astro;
end
fprintf(1, 'SC.rfid_range  : %f\n', SC.rfid_range);

if SC.mode == SC.M_LINE || SC.mode == SC.M_SPIRAL
    %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    % initial transitters: the lander and an RFID on the x-axis
    %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

    % process the lander
    compute_gain(SC.rfid_count);
    resort(SC.rfid_count);
    update_plot_values();

    % process the first RFID at 10 meters
    SC.rfid_locs(:, 2) = [SC.rfid_range./sqrt(2); 0];
    SC.rfid_count = 2;
end

%{
% For explanation introduction only
SC.rfid_locs(:, 2:3) = ...
    [SC.rfid_range./sqrt(2), 0; ...
     0, SC.rfid_range./sqrt(2)];
SC.rfid_count = 3;
refresh_plots(1:3, true);
%}

% The rest of the program is event-driven, so call refresh_plots to setup
% the callback.
refresh_plots();
end

function run_mode_line()

global SC;

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Compute the perp line, the locus, the top line, and the bottom line
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

pt1 = SC.rfid_locs(:, 2);
pt2 = SC.rfid_locs(:, 3);

if (pt1(1) == pt2(1) || ...
    pt1(2) == pt2(2))
    error(mfilename, ...
          'Fatal error: cannot handle the case of infinite slope.');
end

% column 1 is the slope and y-intercept of RFIDs 2 and 3 (which is
%   perpendicular to the 2nd and 3rd lines)
% column 2 is the slope and y-intercept of the 2nd RFID
% column 3 is the slope and y-intercept of the 3rd RFID
% column 4 is the slope and y-intercept of the locus
% The third row is the x delta.
lines = zeros(3, 4); 

% first line
lines(1, 1) = (pt1(2)-pt2(2))./(pt1(1)-pt2(1));
lines(2, 1) = pt1(2) - lines(1,1).*pt1(1);
lines(3, 1) = SC.line_delta./sqrt(1+lines(1,1).^2);

% second line
lines(1, 2) = -1./lines(1, 1);
lines(2, 2) = pt1(2) - lines(1, 2).*pt1(1);
lines(3, 2) = SC.line_delta./sqrt(1+lines(1,2).^2);

% third line
lines(1, 3) = -1./lines(1, 1);
lines(2, 3) = pt2(2) - lines(1, 3).*pt2(1);
lines(3, 3) = SC.line_delta./sqrt(1+lines(1,3).^2);

% fourth line
lines(1, 4) = -1./lines(1, 1);
lines(2, 4) = (lines(2,2) + lines(2,3))./2;
lines(3, 4) = SC.line_delta./sqrt(1+lines(1,4).^2);

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Perform the actual iteration to find the subsequent RFID locations
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
i = 0;
while ((3+2*(i+1)) <= SC.rfid_max)

    pt1 = SC.rfid_locs(:, 2+2*i); % The bottom-line point
    pt2 = SC.rfid_locs(:, 3+2*i); % The top-line point

    %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    % Find the location of the next bottom-line point. We can't use the
    % general grid for this because the line delta is probably smaller than
    % the grid delta.
    %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    
    out_of_range = false; % Why doesn't Matlab have a do-while?!
    j = 1;
    while ~out_of_range
        % If we're applying deltas to the bottom line then calculate the
        % path loss relative to the most recent top line point.
        Pr_rfid = received_power( ...
            SC.astro_tx_power, ...
            SC.astro_gain, ...
            SC.rfid_gain, ...
            SC.lambda, ...
            norm( [ ((pt1(1) + j.*lines(3, 2)) - pt2(1)) ...
                    ((pt1(2) + j.*lines(3, 2).*lines(1, 2)) - pt2(2)) ]) );

        if (Pr_rfid < SC.rfid_turnon)
            out_of_range = true;
        else
            Pr_astro = received_power( ...
                Pr_rfid - SC.rfid_proc_loss, ...
                SC.rfid_gain, ...
                SC.astro_gain, ...
                SC.lambda, ...
                norm( [ ((pt1(1) + j.*lines(3, 2)) - pt2(1)) ...
                        ((pt1(2) + j.*lines(3, 2).*lines(1, 2)) - pt2(2)) ]) );
            if (Pr_astro < SC.astro_min_rx_fromRFID)
                out_of_range = true;
            else
                out_of_range = false;
            end
        end
        
        if ~out_of_range
            j = j + 1;
        end
    end
    % j is the delta multiplier for the first point that is out of range
    
    if j == 1 
        error(mfilename, ...
              'RFIDs #2 and #3 are too far apart.');
    else
        
        % The next RFID along the bottom line.
        SC.rfid_locs(1, 2+2*(i+1)) = ...
            SC.rfid_locs(1, 2+2*i) + (j-1).*lines(3, 2);
        SC.rfid_locs(2, 2+2*(i+1)) = ...
            SC.rfid_locs(2, 2+2*i) + (j-1).*lines(3, 2).*lines(1, 2);
        
        % The next RFID along the top line. TODO
        SC.rfid_locs(1, 3+2*(i+1)) = ...
            SC.rfid_locs(1, 3+2*i) + (j-1).*lines(3, 3);
        SC.rfid_locs(2, 3+2*(i+1)) = ...
            SC.rfid_locs(2, 3+2*i) + (j-1).*lines(3, 3).*lines(1, 3);
    end
    SC.rfid_count = SC.rfid_count + 2;
    
    refresh_plots([(SC.rfid_count-1) SC.rfid_count], false);
    %pause;
    
    i = i + 1;
end

end

function run_mode_spiral()

global SC;

rfid_distances = zeros(1, SC.rfid_count-1);
center_pt_idx  = -1;
theta = 0; % temporary value
R = zeros(2,2); % the rotation matrix

for i = SC.rfid_count:SC.rfid_max
    %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    % Compute the midpoint line
    %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    
    
    if (i <= 6)
        center_pt_idx = 2;
    elseif (i <= 8) % 7 to 8
        center_pt_idx = 1;
    else
        center_pt_idx = 3 + floor((i-9)/2);
    end
    
    %{
    if (i <= 6)
        center_pt_idx = 2;
    elseif (i <= 8) % 7 to 8
        center_pt_idx = 1;
    elseif (i <= 10)
        center_pt_idx = 3;
    elseif (i <= 12)
        center_pt_idx = 4;
    elseif (i <= 14)
        center_pt_idx = 5;
    elseif (i <= 16)
        center_pt_idx = 6;
    elseif (i <= 18)
        center_pt_idx = 7;
    elseif (i <= 20)
        center_pt_idx = 8;
    end
    %}
    
    if (i == 3)
        pt1 = SC.rfid_locs(:, 1);
        pt3 = SC.rfid_locs(:, 3);
        
        if (pt3(2) > 0)
            theta = -pi/2; % a 90 degree clockwise rotation
        else
            theta = pi/2;
        end
        R = [cos(theta) -sin(theta); sin(theta) cos(theta)];
        
    else
        pt1 = SC.rfid_locs(:, i-1);
        pt3 = SC.rfid_locs(:, i);
    end
    pt2 = SC.rfid_locs(:, center_pt_idx);
    
    midpoint = (pt3 + pt2)./2;

    if (pt1(1) == midpoint(1) || ...
        pt1(2) == midpoint(2))
        error(mfilename, ...
              'Fatal error: cannot handle the case of infinite slope.');
    end

    vector = R * ((pt3-pt2)./norm(pt3-pt2)).*SC.line_delta;
    
    %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    % Find the location of the next spiral point. We can't use the
    % general grid for this because the line delta is probably smaller than
    % the grid delta.
    %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    
    out_of_range = false; % Why doesn't Matlab have a do-while?!
    j = 1;
    while ~out_of_range
        
        Pr_rfid = received_power( ...
            SC.astro_tx_power, ...
            SC.astro_gain, ...
            SC.rfid_gain, ...
            SC.lambda, ...
            norm( (midpoint + j.*vector) - pt2 ) ...
        );

        % TODO
        if (Pr_rfid < SC.rfid_turnon)
            out_of_range = true;
        else
            Pr_astro = received_power( ...
                Pr_rfid - SC.rfid_proc_loss, ...
                SC.rfid_gain, ...
                SC.astro_gain, ...
                SC.lambda, ...
                norm( (midpoint + j.*vector) - pt2 ) ...
            );
            if (Pr_astro < SC.astro_min_rx_fromRFID)
                out_of_range = true;
            else
                out_of_range = false;
            end
        end
        
        if ~out_of_range
            j = j + 1;
        end
    end
    % j is the delta multiplier for the first point that is out of range
    
    % The next RFID along the line.
    SC.rfid_locs(:, i+1) = midpoint + (j-1).*vector;
        
    SC.rfid_count = SC.rfid_count + 1;
    refresh_plots(SC.rfid_count, false);
    %pause;
    foo = 1+1;
    
end

end

function Pr = received_power(Pt, Gt, Gr, lambda, r)
Pr = Pt + Gt + Gr - 20.*log10(4.*pi./lambda) - 20.*log10(r);
end

function Pr = received_power_Parsons(Pt, Gt, Gr, lambda, Ht, Hr, r)
%Pr = 10.*log10(4) + Pt + 20.*log10(lambda./(4*pi*r)) + Gt + Gr ...
%    + 10*log10(sin((2.*pi.*Ht.*Hr)./(lambda.*r)).^2) - SC.Mtotal;
global SC;
Pr = Pt + Gt + Gr + 20*log10((Ht.*Hr)./r.^2) - SC.Mtotal;
end

function compute_gain(rfid_number)

global SC;

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Lander Gain
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
if (rfid_number == 1)
    % Remember: MATLAB arrays are stored in column-major order.
    for i = 1:SC.x_count
        for j = 1:SC.y_count
            Pr_lander = received_power_Parsons( ...
                SC.astro_tx_power, ...
                SC.astro_gain, ...
                SC.lander_gain, ...
                SC.lambda, ...
                SC.fade_depth_data(1, 3), ...
                SC.fade_depth_data(SC.lander_fade_idx, 3), ...
                norm( [ SC.x_axis(i) SC.y_axis(j) ]) );
            
            if (Pr_lander < SC.lander_min_rx)
                SC.gains(j, i, rfid_number) = -Inf;
            else
                SC.gains(j, i, rfid_number) = received_power_Parsons( ...
                    SC.lander_tx_power, ...
                    SC.lander_gain, ...
                    SC.astro_gain, ...
                    SC.lambda, ...
                    SC.fade_depth_data(1, 3), ...
                    SC.fade_depth_data(SC.lander_fade_idx, 3), ...
                    norm( [ SC.x_axis(i) SC.y_axis(j) ] ) );
            end
        end
    end
else
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% RFID Gain
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    for i = 1:SC.x_count
        for j = 1:SC.y_count
            Pr_rfid = received_power( ...
                SC.astro_tx_power, ...
                SC.astro_gain, ...
                SC.rfid_gain, ...
                SC.lambda, ...
                norm( [ (SC.x_axis(i)-(SC.rfid_locs(1, rfid_number))) ...
                        (SC.y_axis(j)-(SC.rfid_locs(2, rfid_number))) ] ) );
            
            if (Pr_rfid < SC.rfid_turnon)
                SC.gains(j, i, rfid_number) = -Inf;
            else
                Pr_astro = received_power( ...
                    Pr_rfid - SC.rfid_proc_loss, ...
                    SC.rfid_gain, ...
                    SC.astro_gain, ...
                    SC.lambda, ...
                    norm( [ (SC.x_axis(i)-(SC.rfid_locs(1, rfid_number))) ...
                            (SC.y_axis(j)-(SC.rfid_locs(2, rfid_number))) ] ) );
                if (Pr_astro < SC.astro_min_rx_fromRFID)
                    SC.gains(j, i, rfid_number) = -Inf;
                else
                    SC.gains(j, i, rfid_number) = Pr_astro;
                end
            end
        end
    end
end

if (rfid_number >= 2)
    SC.gains_woLander(:, :, rfid_number-1) = SC.gains(:, :, rfid_number);
end

end

function resort(rfid_number)
% This sorts layers 1 through rfid_number

global SC;

if (rfid_number == 1)
    % Sorting one element is the trivial case.
    return;
end

% Gains with the lander
[SC.gains(:,:,1:rfid_number) IX] = ...
    sort(SC.gains(:,:,1:rfid_number), 3, 'descend');
for i = 1:SC.x_count
    for j = 1:SC.y_count
        SC.sort_order(j,i,1:rfid_number) = SC.sort_order(j,i,IX(j,i,:));
    end
end


if (rfid_number >= 2)
    
    if (rfid_number == 2)
        % Sorting one element is the trivial case.
        return;
    end
    
    % Gains without the lander
    [SC.gains_woLander(:,:,1:rfid_number-1) IX] = ...
        sort(SC.gains_woLander(:,:,1:rfid_number-1), 3, 'descend');
    for i = 1:SC.x_count
        for j = 1:SC.y_count
            SC.sort_order_woLander(j,i,1:rfid_number-1) = ...
                SC.sort_order_woLander(j,i,IX(j,i,:));
        end
    end
end

end

function update_plot_values()

global SC;

if (SC.rfid_count < 3)
    SC.Zmin = SC.gains(:,:,SC.rfid_count);
else
    SC.Zmin = SC.gains(:,:,3);
end
SC.Zmax = SC.gains(:,:,1);

if (SC.rfid_count >= 2)
    SC.Zmax_woLander = SC.gains_woLander(:,:,1);
end

end

function refresh_plots(rfids, set_callback)
% The first parameter is a vector of the RFIDs that were just added.
% The second parameter indicates whether or not to set the callback.

global SC;

if nargin < 1 || isempty(rfids)
    rfids = SC.rfid_count;
end
if nargin < 2
    set_callback = true; % assign the callback by default
end

% compute_gain only modifies the designated layers of the 3D gains matrix
% and nothing else.
for rfid = rfids
    compute_gain(rfid);
end

% Resort the gains of RFIDs 1 through rfid_count
resort(max(rfids));

update_plot_values();

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Plots that take the lander into account
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

if (SC.fig_with_lander == -1)
    scrsz = get(0,'ScreenSize');
    SC.fig_with_lander = figure('Position', ... % -50 b/c of the toolbar
                                [1 60 scrsz(3) (scrsz(4)-130)]);
else
    figure(SC.fig_with_lander);
end
% Surface plot for the min value
subplot(2,2,1);
h_max_surf = surf(SC.X, SC.Y, SC.Zmin, ...
    'FaceColor','interp',...
    'EdgeColor','none',...
    'FaceLighting','phong');
view([0 90]);
colorbar;
if set_callback
    set(h_max_surf, 'ButtonDownFcn', @clickCallback);
end
title({'Received signal strength for', ...
       'the 3rd most powerful signal at (x,y)'});
xlabel('x: meters');
ylabel('y: meters');

% Countour plot for the min value
subplot(2,2,2);
contour(SC.X, SC.Y, SC.Zmin);
if set_callback
    set(gca, 'ButtonDownFcn', @clickCallback);
end
title({'Received signal strength for', ...
       'the 3rd most powerful signal at (x,y)'});
xlabel('x: meters');
ylabel('y: meters');

% Surface plot for the max value
subplot(2,2,3);
h_min_surf = surf(SC.X, SC.Y, SC.Zmax, ...
    'FaceColor','interp',...
    'EdgeColor','none',...
    'FaceLighting','phong'); 
view([0 90]);
colorbar;
if set_callback
    set(h_min_surf, 'ButtonDownFcn', @clickCallback);
end
title({'Received signal strength for', ...
       'the most powerful signal at (x,y)'});
xlabel('x: meters');
ylabel('y: meters');

% Contour plot for the max value
subplot(2,2,4);
contour(SC.X, SC.Y, SC.Zmax);
if set_callback
    set(gca, 'ButtonDownFcn', @clickCallback);
end
title({'Received signal strength for', ...
       'the most powerful signal at (x,y)'});
xlabel('x: meters');
ylabel('y: meters');

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Plots that ignore the lander
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

if (SC.fig_wo_lander == -1 && max(rfids) >= 2)
    scrsz = get(0,'ScreenSize');
    SC.fig_wo_lander = figure('Position', ... % -50 b/c of the toolbar
                              [1 (scrsz(4)/2-80) scrsz(3) scrsz(4)/2]);
end

if SC.fig_wo_lander ~= -1
    figure(SC.fig_wo_lander);
    
    % Surface plot for the max value
    subplot(1,2,1);
    h_min_surf = surf(SC.X, SC.Y, SC.Zmax_woLander, ...
        'FaceColor','interp',...
        'EdgeColor','none',...
        'FaceLighting','phong'); 
    view([0 90]);
    colorbar;
    if set_callback
        set(h_min_surf, 'ButtonDownFcn', @clickCallback);
    end
    title({'Received signal strength for', ...
           'the most powerful signal at (x,y)'});
    xlabel('x: meters');
    ylabel('y: meters');

    % Contour plot for the max value
    subplot(1,2,2);
    contour(SC.X, SC.Y, SC.Zmax_woLander);
    if set_callback
        set(gca, 'ButtonDownFcn', @clickCallback);
    end
    title({'Received signal strength for', ...
           'the most powerful signal at (x,y)'});
    xlabel('x: meters');
    ylabel('y: meters');    
end

end

function clickCallback(hObject, eventdata)

global SC;

if (SC.rfid_count < SC.rfid_max)
    SC.rfid_count = SC.rfid_count + 1;
    if (strcmp(get(hObject, 'Type'), 'axes'))
        pos = get(hObject,'CurrentPoint');
    else
        pos = get(get(hObject, 'Parent'), 'CurrentPoint');
    end
    SC.rfid_locs(1:2, SC.rfid_count) = pos(1,1:2)';
    
    switch SC.mode
        case SC.M_LINE
            % display the third transponder
            refresh_plots([], false); % don't set the callback
            % compute and display the sequence
            run_mode_line();
            
        case SC.M_SPIRAL
            % display the third transponder
            refresh_plots([], false); % don't set the callback
            % compute and display the sequence
            run_mode_spiral();
            
        otherwise
            refresh_plots([], true);
            
    end
else
    fprintf(1, 'Warning: Your click had no effect. RFIDs are maxed out.\n');
end
end

