function [x, y, classnames] = loadLabeledData(fname, indLabel, codings)
% Loads a labeled data file (delimited ASCII); returns a 
% matrix of observations (as columns!) and a class coding matrix
% (as columns, taken from the given prototype codings).
%
% NOTES: 
%
%   - The file must have one observation on each line, variables 
%     separated by commas
%
%   - The entry at index indLabel on each line is interpreted as the
%     class label (The parameter is required to ascertain that you know 
%     whether your label is the first, the last, or some other).
%
%   - Class coding is interpreted as string. The strings are returned in
%     "classnames". Other data must be numerical.
%
%   - The label will be removed from the returned matrix x.
%
%   - The class codings must be given as column vectors.  If codings
%     are omitted, integers will be used. (TODO: make the latter the only
%     option? Would be easier; prototypes can be applied in applications..)
%
%   - Example of a valid file format:
%
%        1.3,1,0,0,768,0
%        1.2,0,1,0,768,1
%        1.8,1,1,-0.31,1e+8,0
%        1.2,0,1,0,769,2
%        ...
%
%% Check arguments

if (nargin~=2 && nargin~=3)
  error('Expected 3 parameters; see help text for descriptions');
end

useIntegers = false;
if (nargin==2)
  warning('robustmlp_mutil:revertToDefaultParam', ...
      'Label coding not specified. Assuming integer coding.');
  useIntegers = true;
end

%% Read data
% Read and transpose (->attributes as rows, observations as columns)
ca = readDelimitedAsCellArray(fname,',');

[nExpectedLines, nExpectedCols] = size(ca);

labeltext = ca(:,indLabel);
ca = ca(:,[(1:(indLabel-1)) (indLabel+1:nExpectedCols)]);
da = cellRangeToTyped(ca,1:nExpectedLines,1:(nExpectedCols-1),'double');
x = da';

% Translate labels from text to integer
% Uses containers.Map on Matlab and a terrible hack on Octave...
nclasses = 0;
labels = zeros(1,length(labeltext));
classnames = {};

if ~exist('OCTAVE_VERSION') % then likely using Matlab
  labelmap = containers.Map;
  for ii=1:length(labeltext)
    name = labeltext{ii};
    if ~isKey(labelmap, name); 
      nclasses = nclasses + 1;
      labelmap(name) = nclasses;
      classnames{nclasses} = name;
    end;
    labels(ii) = labelmap(name);
  end
else
  % On octave we use a very slow linear search of the classname.  I
  % don't know if Octave has something similar to Matlab's
  % containers.Map .. if it doesn't, it would be a nice exercise to
  % create one :) .. if somebody has the time and energy.
  labelmap = {};
  for ii=1:length(labeltext)
    name = labeltext{ii};
    is_key = 0;
    thislabel = 0;
    for ik=1:length(labelmap)
      if strcmp(labelmap{ik},name)
	is_key = 1;
	thislabel = ik;
	break
      end
    end
    if ~is_key
      nclasses = nclasses + 1;
      thislabel = nclasses;
      labelmap{nclasses} = name;
      classnames{nclasses} = name;
    end;
    labels(ii) = thislabel;
  end
end



% %% Check that the file was well-populated with labels

if useIntegers, codings = 1:nclasses; end;

if nclasses ~= size(codings,2)
  error(['Valid labels? ' ...
         'Mismatching # of prototypes and distinct labels in data ' ... 
         fname ]); 
end

%% Finally, apply the given label codings:
y = codings(:,labels);
