function x = readReducedVideoData(fn, reduceTemporal, reduceSpatial)
% -- Read reduced video data. 
%IN:  fn: filename with features
%     reduceTemporal: boolean indicating whehter we reduce the temporal
%     resulution by a factor 25 or not
%     reduceSpatial: boolean indicating whether we reduce the spatial
%     resolution by a factor 5 or not by cutting the left and right
%     columns, together with a downsampling of 2x2 blocks
    
    
    warning off; H = waitbar(0, ['Reading video features for ', fn]); warning on;
    % -- Allocate space - count frames
    m = countFrames(fn);
    if reduceTemporal
        m = floor(m/25);    % -- Discard last set of frames that don't make a full 25-block
    end
    
    n = countFeatures(fn);
    n_ori = n;
    if reduceSpatial
        n = (n-8)/(5) + 8;
    end
    
    x = zeros(m, n);
    
    f = fopen(fn, 'r');
    for i = 1:m
        waitbar(i/m, H);
        M = readBlock(f, n_ori);
        if reduceTemporal
            M = reduceTemporalResolution(M);
            if reduceSpatial
                M = reduceSpatialResolution(M);
            end
            x(i, :) = M;
        else 
            if reduceSpatial
                M = reduceSpatialResolution(M);
            end
            x((i-1)*24+1:i*25, :) = M;
        end
        
    end
    fclose(f);
    close(H);

end

function x = readBlock(f, n)
% -- Read and return a block of 25 frames g from an already open file
% handle f. n is the expected dimensionality and passed for efficiency
% (allows pre-allocation of memory)
    
    x = zeros(25, n);
    for i = 1:25
        d = fgetl(f);
        x(i,:) = line2feats(d);
    end
    
end

function g = countFrames(fn)
% -- Counts the number of instances in a data file
    f = fopen(fn, 'r');
    g = 0;
    while 1
        d = fgetl(f);
        if ~ischar(d), break, end
        g = g+1;
    end
    fclose(f);
end

function g = countFeatures(fn)
% -- Counts the number of features by inspecting the first line of a
% feature file
    f = fopen(fn, 'r');
    g = 0;
    
    d = fgetl(f);
    if ~ischar(d)
        return
    end
    D = regexp(d, ',');
    g = numel(D);
    
    fclose(f);
end

function b = reduceTemporalResolution(a)
% a is 25 x m
% b is 1 x m
    b = mean(a);    % - God, that's easy!
end

function b = reduceSpatialResolution(a)
    % -- Remove left- and right-most columns. Average histograms of all
    % remaining blocks in 2x2 neihbourhoods, maintaining new block ordering
    % a is a [n x 5908] matrix, n being 1 or 25, but should work for any n
    % b is a [n x 1188] matrix
    
    % - Height/width of new blockstructure
    w = 4;  
    h = 5;
    n = size(a,1);
    
    b = zeros(n, h*w*59+8);
    
    b(:,1:8) = a(:,1:8);    % - Copy face/eye detection info
    
    for i = 1:h        
        for j = 1:w
            I = oldBlockFeatureIndex(i,j);
            x = (a(:,I{1}) + a(:, I{2}) + a(:, I{3}) + a(:,I{4}))./4;
            J = newBlockFeatureIndex(i,j);
            b(:,J) = x;
        end
    end
    
end

function I = oldBlockFeatureIndex(i,j)
% -- Returns indices of original block structure features corresponding to
% new block at position i,j
    
    % - rows in original block structure for new structure block of row i. 
    r = [2*i-1, 2*i];   
    % - cols in original block structure for new structure block of col j
    % Note the offset, caused by the exclusion of column 1
    c = [2*j, 2*j+1];
    
    I = cell(1, 4);
    cnt = 0;
    for k = 1:2
        for l = 1:2
            s = 8 + ((r(k)-1)*10 + (c(l)-1)) * 59 + 1; % - Damn 1-based indexing!
            cnt = cnt + 1;
            I{cnt} = s:s+58;
        end
    end
end

function I = newBlockFeatureIndex(i,j)
% i is new block row index [1,5], j new block col index [1,4]
    s = 8 + ((i-1)*4 + (j-1)) * 59 + 1;
    I = s:s+58;
end