function s = evalStates(this, model, names, varargin)
% EVALSTATES Evalutes model states.

% Author(s): Bora Eryilmaz
% Revised: 
% Copyright 1986-2004 The MathWorks, Inc.
% $Revision: 1.1.6.4 $ $Date: 2004/11/18 23:44:33 $

% Create return structure
s = struct('Block', names, 'Value', [], 'Ts', []);

% State vector names from sizes call
if ~isempty(varargin)
  [sys, x0, x0_str, ts, x0_ts] = deal( varargin{:} );
else
  % Will compile model
  [sys, x0, x0_str, ts, x0_ts] = this.evalModel(model);
end

old_env_block = handle(NaN); % Old environment handle

for ct = 1:length(names)
  block  = names{ct};
  hBlock = getBlockHandle(this, block);
  
  % Is this a SimMechanics block instead of a regular one?
  isPhysical = any( strcmp( hBlock.fieldnames, 'PhysicalDomain' ) );
  
  if ~isPhysical
    idxs = strcmp( block, x0_str );
    if any(idxs)
      s(ct).Value = x0(idxs);
      Ts          = x0_ts( idxs, 1 );
      s(ct).Ts    = Ts(1);
    else
      error('The block ''%s'' does not have states.', block)
    end
  else
    % Find the environment or the first ground block in the machine that
    % contains this block.
    sim_blks_struct = mech_get_blocks( block );
    if ~isempty( sim_blks_struct.Environment )
      env_block = sim_blks_struct.Environment;
    else
      env_block = sim_blks_struct.Ground(1);
    end
    
    % Get the state vector manager from the environment block
    if ( env_block ~= old_env_block )
      % Avoid recomputing Manager as long as the environent is the same
      Manager = mech_stateVectorMgr( block );
      old_env_block = env_block;
    end
    
    BlockStates = find( Manager.BlockStates, 'BlockName', block );
    if ~isempty(BlockStates)
      % REM: s(ct) may get its state values from multiple BlockStates.
      % For example
      % mech_motorcycle_plain/Universal//Front:R1
      % mech_motorcycle_plain/Universal//Front:R2
      s(ct).Value = LocalGetSimMechStates( Manager, BlockStates );
      s(ct).Ts    = 0;
    else
      error('The block ''%s'' does not have states.', block)
    end
  end
end

% --------------------------------------------------------------------------
function value = LocalGetSimMechStates(Manager, BlockStates)
value = [];

for ct = 1:length(BlockStates)
  BlockState = BlockStates(ct);
  
  % Find states with "partial" state name matching
  PartialStateName = [ BlockState.BlockName, ':', BlockState.Primitive ];
  tf = strncmp( PartialStateName, Manager.StateNames, length(PartialStateName) );
  
  % Store block/state info
  value = [ value; Manager.X(tf)' ];
end
