function net = resnet3dNetwork(inputSize, numClasses, options)
%

%   Copyright 2023 The MathWorks, Inc.

arguments
    inputSize {mustBeNumeric,mustBeInteger,mustBePositive,iMustBeValidInputSize(inputSize)}
    numClasses (1,1) {mustBeNumeric,mustBeInteger,mustBePositive}
    options.InitialFilterSize (1,3) {mustBeNumeric,mustBeInteger,mustBePositive} = 7
    options.InitialNumFilters(1,1) {mustBeNumeric,mustBeInteger,mustBePositive} = 64
    options.InitialStride (1,3) {mustBeNumeric,mustBeInteger,mustBePositive} = 2
    options.InitialPoolingLayer (1,:) char = 'max'
    options.ResidualBlockType (1,:) char = 'batchnorm-before-add'
    options.BottleneckType (1,:) char = 'downsample-first-conv'
    options.StackDepth (1,:) {mustBeNumeric,mustBeInteger,mustBePositive} = [3 4 6 3]
    options.NumFilters (1,:) {mustBeNumeric,mustBeInteger,mustBePositive} = [64 128 256 512]
    options.Normalization (1,:) char = 'zerocenter'
    options.Initialize {iAssertBinary} = true
end
try
    builder = deep.internal.util.Resnet3dBuilder();
    net = createNetwork(builder,inputSize,numClasses,options);
    if options.Initialize
        net = initialize(net);
    end
catch ex
    throw(ex);
end
end

function iMustBeValidInputSize(inputSize)
if ~iIsRowVectorOfThreeOrFour(inputSize)
    error(message('nnet_cnn:resnetLayers:InvalidImageSize3D'));
end
end

function tf = iIsRowVectorOfThreeOrFour(x)
tf = isrow(x) && (numel(x)==3 || numel(x)==4);
end

function iAssertBinary(value)
nnet.internal.cnn.options.OptionsValidator.assertBinary(value);
end