function image = detect_track(image, detector, center_col, num_track_cols, directions, strip_idx)

% image = detect_track(image, detector, center_col, num_track_cols, directions, strip_idx)
%
% run the strip-based edge detection and two-sided tracking
% from a single input strip
%
%
% INPUT:
% -------------------------------------------------------------------------
% image       		- a structure containing the input image
% detector      	- a structure containing parameters that determine
%			  the behaviour of the edge detector
% center_col		- the middle column of the strip in question
% num_track_cols	- the extent to which the tracking procedure should cover
% directions		- leftward, rightward tracking or both
% strip_idx		- the index of the strip in question
%
% OUTPUT:
% -------------------------------------------------------------------------
% image     		- modified structure which contains the detected edges
%
%
% Written by Yi-Qing Wang, 2016

	half_size = 2^(detector.max_scale-1);
	detector_col_range = (-half_size:half_size) + center_col;

	myDetector = CurveDetector(image.noisy(:, detector_col_range), detector);
	fire_stats_cell = multiscale_detector(myDetector);

	display_every = detector.display_every;

	% curve extension towards right
	track_col_rangel = detector_col_range(1):(detector_col_range(1)+num_track_cols);
	% curve extension towards left
	if strip_idx == 1
		lend = 1;
	else
		lend = (detector_col_range(end)-num_track_cols);
	end
	track_col_ranger = lend:detector_col_range(end);

	for direction = directions

		% try to extend to the right with direction = 1
		% try to extend to the left with direction = 2

		if direction == 1
			rhs = image.noisy(:, track_col_rangel);
			prs = image.pixel_responses(:, track_col_rangel);
		else
			rhs = fliplr(image.noisy(:, track_col_ranger));
			prs = fliplr(image.pixel_responses(:, track_col_ranger));
		end

		if ~detector.extend_all
			% avoid repeated detection
			detected_rowids = [];
		end

		for c = 1:numel(fire_stats_cell)

			% extend one scale at a time
			if ~isempty(fire_stats_cell{c})

				fire_stats = fire_stats_cell{c};

				if ~detector.extend_all
					if isempty(detected_rowids)
						% starting rows that have been looked at
						detected_rowids = fire_stats.rowid;
					else
						retained_idx = [];
						for k = 1:numel(fire_stats.rowid)
							% avoid those rows likely to originate from the same underlying curve
							% however, if the edge contrast is not constant, when a shorter detection
							% fails to extend, a longer detection may also be excluded from an extension, to test
							if min(abs(detected_rowids-fire_stats.rowid(k))) > 2
								retained_idx = [retained_idx, k];
							end
						end
						if isempty(retained_idx)
							% nothing to do
							continue;
						else
							fire_stats.rowid = fire_stats.rowid(retained_idx);
							fire_stats.signed_response = fire_stats.signed_response(retained_idx);
							fire_stats.coefs = fire_stats.coefs(retained_idx, :);
							fire_stats.controls = fire_stats.controls(retained_idx, :);
							fire_stats.contid = fire_stats.contid(retained_idx);
							detected_rowids = vertcat(detected_rowids, fire_stats.rowid);
						end
					end
				end

				% place this code block here so that it reflects precisely which detection is tracked afterward
				if direction == 1
					fire_stats.disp_col_offset = detector_col_range(1) - 1;
					image.curve_coordinates.detected{strip_idx, c} = visualize(myDetector, fire_stats, image.background, center_col);
				else
					fire_stats.disp_col_offset = size(image.background, 2) - detector_col_range(end);
					% assert(isequal(sum(fire_stats.coefs, 2), fire_stats.controls(:, end)));
					fire_stats.controls = fliplr(fire_stats.controls);
					fire_stats.coefs = bsxfun(@times, (-1).^(2:(1+size(fire_stats.coefs, 2))), fire_stats.coefs);
					% assert(isequal(sum(fire_stats.coefs, 2), fire_stats.controls(:, end)));
				end


				myTracker = EdgeTracker(rhs, prs, fire_stats, detector);

				% distinguish between fast and slow mode based whether we want to display intermediate results or not (display_every)
				if direction == 1
					if display_every < 0
						rec = full_track(myTracker, display_every);
					else
						rec = full_track(myTracker, display_every, image.background);
					end
					image.curve_coordinates.right{strip_idx, c} = rec;
				else
					if display_every < 0
						rec = full_track(myTracker, display_every);
					else
						rec = full_track(myTracker, display_every, flip(image.background, 2));
					end
					% revert the coordinates
					for k = 1:numel(rec)
						if ~isempty(rec{k})
							rec{k}.colids = size(image.background, 2) - rec{k}.colids + 1;
						else
							break;
						end
					end
					image.curve_coordinates.left{strip_idx, c} = rec;
				end
			end
		end
	end
end
