function [CSX,port] = AddCurvePort( CSX, prio, portnr, R, start, stop, excite, varargin )
%[CSX,port] = AddCurvePort( CSX, prio, portnr, R, start, stop [, excite, varargin] )
%
% Creates a curve port (1-dimensional).
% The mesh must already be initialized.
%
% input:
%   CSX:    CSX-object created by InitCSX()
%   prio:   priority for excitation, metal, sheet and probe boxes
%   portnr: (integer) number of the port
%   R:      internal resistance of the port
%   start:  3D start rowvector for port definition
%   stop:   3D end rowvector for port definition
%   excite (optional): if true, the port will be switched on (see AddExcitation())
%                       Note: for legacy support a string will be accepted
% optional (key/values):
%   varargin:   optional additional excitations options, see also AddExcitation
%   'PortNamePrefix': a prefix to the port name
%
% output:
%   CSX:
%   port:
%
% example:
%   start = [0 0 0]; stop = [0 0 12];
%   this defines a lumped port in z-direction
%   the excitation/probe is placed between start(1) and stop(1)
%
% (C) 2010 Sebastian Held <sebastian.held@uni-due.de>
% See also InitCSX AddExcitation

port.type='Lumped';
port.nr=portnr;

PortNamePrefix = '';

varargin_tmp  = varargin;
for n=1:2:numel(varargin_tmp)
    if strcmpi('PortNamePrefix',varargin_tmp{n})
        PortNamePrefix = varargin_tmp{n+1};
        varargin([n n+1]) = [];
    end
end

% make row vector
start = reshape( start, 1, [] );
stop  = reshape( stop , 1, [] );

% get grid
mesh{1} = sort(unique(CSX.RectilinearGrid.XLines));
mesh{2} = sort(unique(CSX.RectilinearGrid.YLines));
mesh{3} = sort(unique(CSX.RectilinearGrid.ZLines));
unit    = CSX.RectilinearGrid.ATTRIBUTE.DeltaUnit;

% find port direction
dir = abs(stop - start);
[dummy,dir] = max(dir);

% other directions
dir1 = mod(dir,3)+1;
dir2 = mod(dir+1,3)+1;

% normalize start and stop
if start(dir) < stop(dir)
    nstart = start;
    nstop  = stop;
else
    nstart = stop;
    nstop  = start;
end

% snap to grid
start_idx = zeros(1,3);
stop_idx  = zeros(1,3);
for n=1:3
    start_idx(n) = interp1( mesh{n}, 1:numel(mesh{n}), nstart(n), 'nearest' );
    stop_idx(n)  = interp1( mesh{n}, 1:numel(mesh{n}), nstop(n), 'nearest' );
end

% calculate position
port_start_idx = start_idx;
port_stop_idx  = stop_idx;
if abs(start_idx(dir) - stop_idx(dir)) ~= 1
    % calc port position
    idx  = interp1( mesh{dir},  1:numel(mesh{dir}),  (nstart(dir)+nstop(dir))/2,   'nearest' );
    idx1 = interp1( mesh{dir1}, 1:numel(mesh{dir1}), (nstart(dir1)+nstop(dir1))/2, 'nearest' );
    idx2 = interp1( mesh{dir2}, 1:numel(mesh{dir2}), (nstart(dir2)+nstop(dir2))/2, 'nearest' );
    port_start_idx(dir)  = idx;
    port_start_idx(dir1) = idx1;
    port_start_idx(dir2) = idx2;
    port_stop_idx(dir)   = idx+1;
    port_stop_idx(dir1)  = idx1;
    port_stop_idx(dir2)  = idx2;
    metalname = [PortNamePrefix 'port' num2str(portnr) '_PEC'];
    CSX = AddMetal( CSX, metalname );
    CSX = AddCurve( CSX, metalname, prio, [nstart.' [mesh{1}(port_start_idx(1));mesh{2}(port_start_idx(2));mesh{3}(port_start_idx(3))]] );
    CSX = AddCurve( CSX, metalname, prio, [nstop.' [mesh{1}(port_stop_idx(1));mesh{2}(port_stop_idx(2));mesh{3}(port_stop_idx(3))]] );
end

% calculate position of resistive material
delta1_n = mesh{dir1}(port_start_idx(dir1)) - mesh{dir1}(port_start_idx(dir1)-1);
delta1_p = mesh{dir1}(port_start_idx(dir1)+1) - mesh{dir1}(port_start_idx(dir1));
delta2_n = mesh{dir2}(port_start_idx(dir2)) - mesh{dir2}(port_start_idx(dir2)-1);
delta2_p = mesh{dir2}(port_start_idx(dir2)+1) - mesh{dir2}(port_start_idx(dir2));
m_start = zeros(1,3);
m_stop  = zeros(1,3);
for n=1:3
    m_start(n)  = mesh{n}(port_start_idx(n));
    m_stop(n)   = mesh{n}(port_stop_idx(n));
end
m_start(dir1) = m_start(dir1) - delta1_n/2;
m_stop(dir1)  = m_stop(dir1)  + delta1_p/2;
m_start(dir2) = m_start(dir2) - delta2_n/2;
m_stop(dir2)  = m_stop(dir2)  + delta2_p/2;

% calculate position of the voltage probe & excitation
v_start = [mesh{1}(port_start_idx(1)), mesh{2}(port_start_idx(2)), mesh{3}(port_start_idx(3))];
v_stop  = [mesh{1}(port_stop_idx(1)),  mesh{2}(port_stop_idx(2)),  mesh{3}(port_stop_idx(3))];

% calculate position of the current probe
i_start = m_start;
i_stop  = m_stop;
i_start(dir) = (i_start(dir)+i_stop(dir))/2;
i_stop(dir)  = i_start(dir);

% create the probes
port.U_filename = [PortNamePrefix 'port_ut' num2str(portnr)];
weight = -1;
CSX = AddProbe( CSX, port.U_filename, 0, 'weight', weight );
CSX = AddBox( CSX, port.U_filename, prio, v_start, v_stop );
port.I_filename = [PortNamePrefix 'port_it' num2str(portnr)];
weight = 1;
CSX = AddProbe( CSX, port.I_filename, 1, 'weight',  weight );
CSX = AddBox( CSX, port.I_filename, prio, i_start, i_stop );

% create port structure
port.drawingunit = unit;
% port.start = start;
% port.stop = stop;
% port.v_start = v_start;
% port.v_stop  = v_stop;
% port.i_start = i_start;
% port.i_stop  = i_stop;
% port.dir = dir;
% port.direction = direction;
% port.idx_cal = idx_cal;
% port.idx1 = idx1;
% port.idx1 = idx1;

if (nargin < 7)
    excite = false;
end

% legacy support, will be removed at some point
if ischar(excite)
    warning('CSXCAD:AddCurvePort','depreceated: a string as excite option is no longer supported and will be removed in the future, please use true or false');
    if ~isempty(excite)
        excite = true;
    else
        excite = false;
    end
end

port.excite = excite;

% create excitation
if (excite)
	% excitation of this port is enabled
	port.excite = 1;
    e_start = v_start;
    e_stop  = v_stop;
    CSX = AddExcitation( CSX, [PortNamePrefix 'port_excite_' num2str(portnr)], 0, start_idx ~= stop_idx, varargin{:});
	CSX = AddBox( CSX, [PortNamePrefix 'port_excite_' num2str(portnr)], prio, e_start, e_stop );
end

port.Feed_R = R;
if (R>0 && (~isinf(R))) 
    CSX = AddLumpedElement( CSX, [PortNamePrefix 'port_resist_' int2str(portnr)], dir-1, 'R', R);
    CSX = AddBox( CSX, [PortNamePrefix 'port_resist_' int2str(portnr)], prio, v_start, v_stop );
elseif (R==0)
    CSX = AddBox(CSX,metalname, prio, v_start, v_stop);
end