function ambiGenerateEncoderPlugin(name, device, order, format)
%ambiGenerateEncoderPlugin Generate Ambisonic Encoder plugin for Higher
% Order Ambisonics (HOA)
%
% inputs
% name          : name of audioPlugin class
% device        : array of azimuth, elevation and optional devicetype
%                [azimuth; elevation; deviceType]
%                [azimuth; elevation]
%                where 
%                    azimuth may range from 0 degrees to 360 degrees
%                    elevation may range from -90 degrees to 90 degrees
%                    deviceTypes are 0 or 1, 
%                deviceType turns the element encoding on or off for the
%                particular element. If deviceType vector is omitted,
%                then the deviceTypes are set to 1.
% order         : ambisonic order, integer value 0 through 7
% format        : supported formats are 'acn-sn3d', 'acn-n3d', 'acn-fuma',
%                   'acn-maxn', 'fuma-sn3d', 'fuma-n3d', 'fuma-fuma',
%                   'fuma-maxn'; the default format is 'acn-sn3d' 
% 
% outputs
% The function produces a MATLAB audioPlugin class definition file
%
% This function ambiGenerateEncoderPlugin is for demonstration purposes.
% It may change in a future release.

%   Copyright 2018-2019 The MathWorks, Inc.

if nargin < 4
    format = 'acn-sn3d';
end
if nargin < 2
    order = 7;
end 
if size(device,1) == 2
    device = [device; ones(1,size(device,2))];
end
% -------------------------------------------------------------------------
nInputs = size(device,2);
nOutputs = (order+1)^2;
% -------------------------------------------------------------------------
s = StringWriter;
s.addcr('classdef %s < audioPlugin', name);
s.addcr('%#codegen');
s.addcr('% ambisonic encoder plugin');
    s.addcr('properties')
    for idx = 1:size(device,2)
       s.addcr('azimuth%d = %d', idx, device(1, idx));
    end
    for idx = 1:size(device,2)
       s.addcr('elevation%d = %d', idx, device(2, idx));
    end
    for idx = 1:size(device,2)
       s.addcr('deviceType%d = %d', idx, device(3, idx));
    end
    s.addcr('end')
    s.addcr('% ---------------------------------------------------------------------')
    s.addcr('properties')
        s.addcr('emtrx = zeros(%d,%d);', nInputs, nOutputs)
        s.addcr('end')
        s.addcr('% ---------------------------------------------------------------------')
        s.addcr('properties (Constant)')
        s.addcr('PluginInterface = audioPluginInterface( ...');
        for idx = 1:size(device,2)
            s.addcr(sprintf('audioPluginParameter(''azimuth%d'',''DisplayName'',''azimuth%d'',''Label'',''deg'',''Mapping'',{''lin'',0,360}),...', idx, idx));
            s.addcr(sprintf('audioPluginParameter(''elevation%d'',''DisplayName'',''elevation%d'',''Label'',''deg'',''Mapping'',{''lin'',-90,90}),...', idx, idx));
%             s.addcr(sprintf('audioPluginParameter(''deviceType%d'',''DisplayName'',''deviceType%d'',''Mapping'',{''int'',0,1}),...', idx, idx));
        end    
        s.addcr('''PluginName'',''%s'', ...', name)
        s.addcr('''VendorName'',''MathWorks'', ...')
        s.addcr('''VendorVersion'',''1.0'', ...')
        s.addcr('''UniqueId'',''MWAP'', ...')
        s.addcr('''InputChannels'',%d, ...', nInputs)
        s.addcr('''OutputChannels'',%d);', nOutputs);
        s.addcr('end')
    s.addcr('% ---------------------------------------------------------------------')
    s.addcr('methods')
    s.addcr('% -----------------------------------------------------------------')
    s.addcr('function obj = %s()', name)
        s.add('obj.emtrx = audioexample.ambisonics.ambiencodemtrx(')
        s.addcr(' %d, ...', order)
        s.add('[', order)
        for idx = 1:size(device,1)
            for jdx = 1:size(device,2)
                s.add(' %d', device(idx,jdx))
            end
            s.add(';')
        end
        s.addcr(']);', order)
        s.addcr('end')
        s.addcr('% -----------------------------------------------------------------')
    s.addcr('function out = process(obj, x)')
        s.addcr('out = audioexample.ambisonics.ambiencode(x, obj.emtrx, ''%s'');', format)
        s.addcr('end')
        s.addcr('% -----------------------------------------------------------------')
    s.addcr('%#ok<*MCSUP>')
    for idx = 1:size(device,2)
        s.addcr('function set.azimuth%d(obj, val)', idx)
        s.addcr('obj.azimuth%d = val;', idx)
        s.addcr('obj.emtrx(%d,:) = audioexample.ambisonics.ambiencodemtrx(%d, [val; obj.elevation%d; obj.deviceType%d]);', idx, order, idx, idx)
        s.addcr('end')
    end
    s.addcr('% -----------------------------------------------------------------')
    for idx = 1:size(device,2)
        s.addcr('function set.elevation%d(obj, val)', idx)
        s.addcr('obj.elevation%d = val;', idx)
        s.addcr('obj.emtrx(%d,:) = audioexample.ambisonics.ambiencodemtrx(%d, [obj.azimuth%d; val; obj.deviceType%d]);', idx, order, idx, idx)
        s.addcr('end')
    end
    s.addcr('% -----------------------------------------------------------------')
    for idx = 1:size(device,2)
        s.addcr('function set.deviceType%d(obj, val)', idx)
        s.addcr('obj.deviceType%d = val;', idx)
        s.addcr('obj.emtrx(%d,:) = audioexample.ambisonics.ambiencodemtrx(%d, [obj.azimuth%d; obj.elevation%d; val;]);', idx, order, idx, idx)
        s.addcr('end')
    end
    s.addcr('% -----------------------------------------------------------------')
    s.addcr('end')
s.addcr('end')
% -------------------------------------------------------------------------
indentCode(s);
fid = fopen(strcat(name,'.m'), 'w');
fprintf(fid, '%s', s);
fclose(fid);
end
