function layer = networkLayer(net, opts)
%networkLayer   Layer containing a sub-graph or nested network
%
%   layer = networkLayer(net) builds a network layer from a dlnetwork
%   layer = networkLayer(net, Name=name) optionally sets the layer name
%   layer = networkLayer(net, OutputNames=names) optionally sets the
%       outputs of the layer to be different from the those of the
%       underlying network. names can be any legitimate layer output
%       defined using the syntax "layerName" or "layerName/portName".
%   layer = networkLayer(layerArray, ...) builds a network layer from an
%       array of layers connected in series. It is equivalent to
%       networkLayer(dlnetwork(layerArray,Initialize=false), ...).
%
%   See also dlnetwork.
%
%   <a href="matlab:helpview('deeplearning','list_of_layers')">List of Deep Learning Layers</a>

%   Copyright 2023 The MathWorks, Inc.

arguments
    net {mustBeA(net,["dlnetwork","nnet.cnn.layer.Layer"])}
    opts.Name {mustBeTextScalar} = ''
    opts.OutputNames(1,:) {mustBeText} = string.empty
end
if isa(net, 'nnet.cnn.layer.Layer')
    net = dlnetwork(net,Initialize=false);
end
[net, outputNames] = iValidateNet(net, opts.OutputNames);

internalLayer = nnet.internal.cnn.layer.Network(net, opts.Name, net.getExampleInputs(), outputNames);
layer = nnet.cnn.layer.NetworkLayer(internalLayer);
end

function [net, outputNames] = iValidateNet(net, outputNames)
arguments
    net(1,1)
    outputNames
end

% Validate network has layers
% Fast way to get at underlying layer count without unnecessary conversion
numLayers = numel(getInternalLayers(getPrivateNetwork(net)));
assert(numLayers>0, message("nnet_cnn:layer:NetworkLayer:EmptyNetwork"));

% Validate output names against network
useDefaultOutputNames = false;
if isempty(outputNames)
    outputNames = net.OutputNames;
    useDefaultOutputNames = true;
end
areUnique = isequal(unique(outputNames,'stable'),outputNames);
assert(~useDefaultOutputNames||areUnique, ...
        message("nnet_cnn:layer:NetworkLayer:NonUniqueNetworkOutputs"));
assert(useDefaultOutputNames||areUnique, ...
        message("nnet_cnn:layer:NetworkLayer:NonUniqueOutputNames"));
end
