classdef ShadowTrack < matlab.mixin.Copyable
    properties
        setup       = struct();     % structure with camera models etc.
        opts        = struct();     % options for reconstruction        
        n_cameras   = 0;            % number of cameras
		n_t			= 0;			% number of frames
		n_added		= 0;			% number of active tracks added so far
		
        tidx        = 1;            % index of current time
        frame_range = [];           % range of frame indices to process
        t_axis      = [];           % time axis
        
        tracks      = [];           % set of completed tracks
		active		= [];			% set of active tracks
		img_ary		= {};			% current images for interrogation
		msk_ary		= {};			% mask for particle images

		% plotting stuff
		h_fig		= [];			% default figure handle
		h_img		= [];			% image handle
		h_img_ax	= [];			% handle to image space axes
		h_obj_ax	= [];			% handle to object space axes
    end
    
    methods
        % constructor
        function obj = ShadowTrack(varargin)
			% add relevant files to path
			addpath(genpath([fileparts(mfilename('fullpath')) '/../../core']));
            
            if nargin == 1 
                % load tracks from file      
                trk_file        = varargin{1};
                obj = ShadowTrack.load(trk_file);
            elseif nargin >= 2
                % build 
                setup           = varargin{1};
                opts            = varargin{2};
                obj.setup       = setup;
                obj.opts        = opts;
                obj.n_cameras   = length(setup.camera);
				
				% define frame range to process
				obj.frame_range = opts.frame_range;
				obj.t_axis		= opts.frame_range / opts.frame_rate;
				obj.t_axis		= obj.t_axis - obj.t_axis(1);
				obj.n_t			= numel(obj.frame_range);
				% update options structure so these are saved to file later
				obj.opts.t_range= obj.t_axis;
				obj.opts.n_t    = obj.n_t;
            end
        end

		% tracking routine
		track(obj, file_ary);

        % load images from file
        img_ary = read_image(obj, src_ary, frame);
        
        % find particles in images
        particles2d = find_particles(obj, img);

		% create debug plot
		plot_frame(obj, img_ary, particles3d, particles2d, t0);
        
        % match particle centers
        [particles3d, matches] = match(obj, particles2d);
        
        % link track objects to particles
        matches = link(obj, particles, tidx);

		% reconnect broken track objects
		reconnect(obj);
        
        % initialise track object
        track = new_track(obj, particle, t0);
        % add active track object
        add_track(obj, track);
		add_active(obj, track);
        
        % identify active tracks
        %i_track = active(obj);

        % select/reorder active track objects
        select_tracks(obj, subset);
		select_active(obj, subset);
		property_ary = get_active_property(obj, subset, tidx, property, gather);
		property_ary = get_track_property(obj, subset, tidx, property, gather);
		% get number of tracks
		[n_active, n_tracks] = count(obj);

		% update velocity and predict next position
		% build predictor velocity field
        %v_pred = predictor_field(obj, tidx);
		update_velocity(obj, subset, tidx);

		% fit smoothing spline to tracks
		fit_spline(obj, lambda);

		% save to file
		save(obj, trk_file);

		% trim and pad tracks down to minimal/full sequence length
		tracks = trim(obj, tracks);
		tracks = pad(obj, tracks);
	end

	methods (Static)
		% helper function to assign particles to tracks at given time step
		track = assign_particle_to_track(track, particle, t0);
        % load from file
        obj = load(trk_file);
	end
end