function [trainPoints, trainLabels] = nonparam_2d_demo(method, K, distFunc, trainPoints, trainLabels)
% nonparam_2d_demo - Interactive 2d non-parametric methods demonstration.
% 
%   [trainPoints, trainLabels] = nonparam_2d_demo(method, K, distFunc, ...)
%
%   E.g:
%       nonparam_2d_demo('knn',1,'l2');
%       nonparam_2d_demo('kernreg', 0.5);
%   

% Handle setting default argument values
if nargin < 3
    distFunc = 'l2';
end
if nargin < 2
    K = 1;
end
if nargin < 1
    method = 'knn';
end

% Define the symbols and colors we'll use in the plots later
symbols = {'o','x'};
colors = [0.5 0.5 1; 1 0.5 0.5];
classvals = [-1 1];

% Initialize training data to empty; will get points from user
% Obtain points froom the user:
if nargin < 5
    trainPoints = []; trainLabels = [];

    f = figure('Name','KNN Demo');

    hold on; % Allow for overwriting existing plots
    xlim([-5 5]); ylim([-5 5]);
    
    for c = 1:2
        title(sprintf('Click to create points from class %d. Press enter when finished.', c));
        [x y] = getpts;
        
        plot(x,y,symbols{c},'LineWidth', 2, 'Color', 'black');
        
        % Grow the data and label matrices
        trainPoints = vertcat(trainPoints, [x y]);
        trainLabels = vertcat(trainLabels, repmat(classvals(c), numel(x), 1));
    end
    close(f);

end

% To evaluate the classifier, we discretize the range of inputted values
% into a grid of points that we will test on to produce the decision
% boundaries
res = 300;

xrange = linspace(-5, 5,res);
yrange = linspace(-5,5,res);

% meshgrid returns a matrix of X and Y values for every point in each
% combination of the X range and Y range that we specify; we string these
% 80x80 matrices out into a big 6400x2 matrix that we'll feed into the K-NN
% function:

[pixelX pixelY] = meshgrid(xrange, yrange);

testPoints = [pixelX(:) pixelY(:)];

if strcmp(method, 'knn')
    testLabels = sign(knn_test(K, trainPoints,trainLabels,testPoints,distFunc));
elseif strcmp(method, 'kernreg')
    testLabels = sign(kernreg_test(K, trainPoints,trainLabels,testPoints,distFunc));
else
    error('Unrecognized method');
end

% Generate the plot
figure('Name','KNN Demo');
Z = reshape(testLabels, [res res]);
contourf(pixelX, pixelY, Z, [-1 1], 'LineWidth', 2);
colormap(colors);
hold on;
for c = 1:2
    idx = find(trainLabels==classvals(c));
    plot(trainPoints(idx,1), trainPoints(idx,2), symbols{c}, 'Color','black','LineWidth',2);
end
title(sprintf('%s (K=%g): %s Distance', method, K, distFunc));
hold off;
axis xy;
axis off;
box on;
    