function a = subsref(t,s)
%SUBSREF Subscripted reference for tensors.
%
%   We can extract elements or subtensors from a tensor in the
%   following ways.
%
%   Case 1a: y = X(i1,i2,...,iN), where each in is an index, returns a
%   scalar.
%
%   Case 1b: Y = X(R1,R2,...,RN), where one or more Rn is a range and
%   the rest are indices, returns a sparse tensor.
%
%   Case 2a: V = X(S), where S is a p x n array of subscripts, returns a
%   vector of p values. If ndims(X)=1, use instead V = X(S,'extract') so
%   that it knows this is extracting values rather than giving a set of
%   indicies.
%
%   Case 2b: V = X(I), where I is a set of p linear indices, returns a
%   vector of p values. If ndims(X)=1, use V = X(I,'extract') instead.
%
%   Any ambiguity results in executing the first valid case. This
%   is particularly an issue if ndims(X)==1.
%
%   Examples
%   X = tensor(rand(3,4,2,1),[3 4 2 1]);
%   X.data %<-- returns multidimensional array
%   X.size %<-- returns size
%   X(1,1,1,1) %<-- produces a scalar
%   X(1,1,1,:) %<-- produces a tensor of order 1 and size 1
%   X(:,1,1,:) %<-- produces a tensor of size 3 x 1
%   X(1:2,[2 4],1,:) %<-- produces a tensor of size 2 x 2 x 1
%   X(1:2,[2 4],1,1) %<-- produces a tensor of size 2 x 2
%   X([1,1,1,1;3,4,2,1]) %<-- returns a vector of length 2
%   X = tensor(rand(10,1),10);
%   X([1:6]') %<-- extracts a subtensor
%   X([1:6]','extract') %<-- extracts a vector of 6 elements
%
%   See also TENSOR, TENSOR/FIND.
%
%Tensor Toolbox for MATLAB: <a href="https://www.tensortoolbox.org">www.tensortoolbox.org</a>



switch s(1).type
    case '{}'
        error('Cell contents reference from a non-cell array object.')
    case '.'
        fieldname = s(1).subs;
        switch fieldname
            case 'data'
                a = tt_subsubsref(t.data,s);
            case 'size'
                a = tt_subsubsref(t.size,s);
            otherwise
                error(['No such field: ', fieldname]);
        end
    case '()'

        % *** CASE 1: Rectangular Subtensor ***
        if (numel(s(1).subs) == ndims(t)) && ~isequal(s(1).subs{end},'extract')

            % Copy the subscripts
            region = s(1).subs;

            if numel(region) ~= ndims(t)
                error('Invalid number of subscripts');
            end

            % Extract the data
            newdata = t.data(region{:});

            % Determine the subscripts
            newsiz = [];                % (future) new size
            kpdims = [];                % dimensions to keep
            rmdims = [];                % dimensions to remove

            % Determine the new size and what dimensions to keep
            for i = 1:length(region)
                if ischar(region{i}) && (region{i} == ':')
                    newsiz = [newsiz size(t,i)];
                    kpdims = [kpdims i];
                elseif numel(region{i}) > 1
                    newsiz = [newsiz numel(region{i})];
                    kpdims = [kpdims i];
                else
                    rmdims = [rmdims i];
                end
            end

            % If the size is zero, then the result is returned as a scalar;
            % otherwise, we convert the result to a tensor.
            if isempty(newsiz)
                a = newdata;
            else
                if isempty(rmdims)
                    a = tensor(newdata,newsiz);
                else
                    a = tensor(permute(newdata,[kpdims rmdims]),newsiz);
                end
            end
            a = tt_subsubsref(a,s);
            return;
        end

        % *** CASE 2a: Subscript indexing
        if size(s(1).subs{1},2) == ndims(t)
            % extract array of subscripts
            subs = s(1).subs{1};
            a = squeeze(t.data(tt_sub2ind(t.size,subs)));
            if isrow(a), a = a'; end
            a = tt_subsubsref(a,s);
            return;
        end

        % *** CASE 2b: Linear indexing ***
        if (numel(s(1).subs) > 2) || ((numel(s(1).subs) == 2) && ~isequal(s(1).subs{end},'extract'))
            error('Invalid indexing');
        end

        idx = s(1).subs{1};
        if ~iscolumn(idx)
            error('Expecting a column index');
        end

        a = squeeze(t.data(idx));
        if isrow(a), a = a'; end
        a = tt_subsubsref(a,s);
        return;
end
