import io


def create_apply_function_string(sigout, sigin, parameters):
    """
    Create a string for a function of the form::

       def ap_fuc(x_0, x_1, x_2, ...):
           for i in range(len(x_0)):
               x_0[i], ... = jitted_f(x_j[i], ...)
           return x_0[i], ...

    where the specific args to jitted_f and the number of
    values to return is determined by sigout and sigin.

    Parameters
    ----------
    sigout: iterable of the out arguments

    sigin: iterable of the in arguments

    parameters: iterable of which of the args (from in_args) are parameter
                variables (as opposed to column records). This influences
                how we construct the apply-style function

    Returns
    -------
    a String representing the function
    """
    fstr = io.StringIO()
    total_len = len(sigout) + len(sigin)
    out_args = ["x_" + str(i) for i in range(0, len(sigout))]
    in_args = ["x_" + str(i) for i in range(len(sigout), total_len)]

    fstr.write("def ap_func({0}):\n".format(",".join(out_args + in_args)))
    fstr.write("  for i in range(len(x_0)):\n")
    out_index = [x + "[i]" for x in out_args]
    in_index = []
    for arg, _var in zip(in_args, sigin):
        in_index.append(arg + "[i]" if _var not in parameters else arg)
    fstr.write("    " + ",".join(out_index) + " = ")
    fstr.write("jitted_f(" + ",".join(in_index) + ")\n")
    fstr.write("  return " + ",".join(out_args) + "\n")
    return fstr.getvalue()