import six


def make_distance_to_line_auxfn(linename, fname, p, by_vector_dp=True):
    """Builds definition of an auxiliary function of (x,y) measuring
    (signed) distance from a 2D line given at run-time by coordinate
    names in the tuple of strings p and either a vector dp,
    or a point q, depending on the second input argument.
    Also returns list of parameter names used.
    """
    assert len(p)==2 and isinstance(p[0], six.string_types) \
           and isinstance(p[1], six.string_types)
    p0 = linename+'_p_'+p[0]
    p1 = linename+'_p_'+p[1]
    pars = [p0, p1]
    if by_vector_dp:
        # based on idea that q - p = dp
        # to prevent loss of precision
        dp0 = linename+'_dp_'+p[0]
        dp1 = linename+'_dp_'+p[1]
        pars.extend([dp0, dp1])
        q0_m_p0 = dp0
        q1_m_p1 = dp1
    else:
        q0 = linename+'_q_'+p[0]
        q1 = linename+'_q_'+p[1]
        pars.extend([q0, q1])
        q0_m_p0 = '(%s-%s)'%(q0,p0)
        q1_m_p1 = '(%s-%s)'%(q1,p1)
    denom = 'sqrt(%s*%s+%s*%s)'%(q0_m_p0,q0_m_p0,q1_m_p1,q1_m_p1)
    p1_m_y = '(%s-y)'%(p1)
    p0_m_x = '(%s-x)'%(p0)
    d = '(%s*%s-%s*%s)/%s'%(q0_m_p0, p1_m_y, p0_m_x, q1_m_p1, denom)
    return {'pars': pars, 'auxfn': {fname: (['x','y'], d)}}