function y = movfun(wfun,x,kleft,kright,dim,nanflag,ep,fillval,ytype)
%MATLAB Code Generation Library Function

%    * WFUN is a function of x, nx, and nanflag.
%    * KLEFT and KRIGHT are the elements of the equivalent 2-element vector
%      input for the window size.
%    * DIM is the dimension to operate along.
%    * NANFLAG must be 'o' for 'omitnan' or 'i' for 'includenan'. Longer
%      strings are OK, but only the first element is referenced.
%    * EP is the "endpoints" option to the mov* function. It must be 'f',
%      's', 'd', or a numeric or logical scalar that can be castLike X.
%    * AUTOFILLVALUE is a scalar of the same type as X. It is used when ep
%      == 'f' to fill missing values for windows that overlap the edges of
%      the data.
%    * YTYPE sets the type of Y. It must match the type returned by WFUN.

% Copyright 2016-2020 The MathWorks, Inc.
%#codegen

narginchk(3,inf);
coder.internal.prefer_const(kleft,kright,dim,nanflag,ep,fillval,ytype);
coder.internal.assert(~isreal(x) || isreal(ep), ...
    'MATLAB:movfun:complexFillValue');
nx = coder.internal.indexInt(size(x,dim));
if ep == 'd' % Discard
    ny = nx - kleft - kright;
    if ny < 0
        ny = coder.internal.indexInt(0);
    elseif ny > nx
        ny = nx;
    end
else
    ny = coder.internal.indexInt(size(x,dim));
end
vfun = @(x)vmovfun(wfun,x,nx,kleft,kright,nanflag,ep,fillval,ytype);
y = coder.internal.applyVectorFunction(vfun,x,dim,ny,ytype);

%--------------------------------------------------------------------------

function y = vmovfun(f,x,nx,kleft,kright,nanflag,ep,fillval,ytype)
coder.internal.prefer_const(nx,kleft,kright,nanflag,ep,fillval,ytype);
coder.internal.allowEnumInputs;
% endopt must be a scalar numeric value or
%'s' for "shrink",
%'f' for "fill", or
%'d' for "discard".
nw = kleft + kright + 1;
if ischar(ep) && ep == 'd' % Discard
    ny = nx - nw + 1;
    if ny < 0
        ny(1) = 0;
    elseif ny > nx
        ny = nx;
    end
    if coder.internal.isConstTrue(isrow(x))
        y = zeros(1,ny,'like',ytype);
    else
        y = zeros(ny,1,'like',ytype);
    end
else
    ny = nx;
    y = zeros(size(x),'like',ytype);
end
assert(ny <= nx); %<HINT>
coder.internal.treatAsParfor;
for k = 1:ny
    [buf,nbuf] = copywindow(k,x,kleft,kright,ep,fillval);
    y(k) = f(buf,nbuf,nanflag);
end

%--------------------------------------------------------------------------

function [buf,nbuf] = copywindow(i,x,kleft,kright,endopt,fillval)
coder.internal.prefer_const(kleft,kright,endopt);
coder.internal.allowEnumInputs;
nx = coder.internal.indexInt(numel(x));
nw = kleft + kright + 1;
[iLeft,iRight,nPadLeft,nPadRight] = movfunWindow(i,nx,kleft,kright,endopt);
xOffset = iLeft - 1;
nToCopy = iRight - iLeft + 1;
rightPadOffset = nPadLeft + nToCopy;
nbuf = rightPadOffset + nPadRight;
buf = coder.nullcopy(zeros(nw,1,'like',x));
for k = 1:nPadLeft
    buf(k) = fillval;
end
for k = 1:nToCopy
    buf(nPadLeft + k) = x(xOffset + k);
end
for k = (rightPadOffset + 1):nw
    buf(k) = fillval;
end

%--------------------------------------------------------------------------
