import time


def _learn(ulearn, adaptive_learning_rate, increase_rate, decrease_rate, left_out, printer):
    """
    Perform the learning process on ulearn with the given parameters.
    Prints the preparation and learning time of the process using the printer.

    :param ulearn: The learning object
    :type ulearn: ULearner
    :param adaptive_learning_rate: Whether to dynamically change the learning rate when results improve/worsen.
    :type adaptive_learning_rate: bool
    :param increase_rate: The rate with which to multiply the learning rate when an improvement was found (>= 1).
    :type increase_rate: float
    :param decrease_rate: The rate with which to multiply the learning rate when a worse solution was found (<= 1).
    :type decrease_rate: float
    :param left_out: Whether a third of the data should be left out and used for testing instead of training.
    :type left_out: bool
    :param printer: The printer to write logging information to.
    :type printer: Printer
    """
    # Prepare
    starttime = time.time()
    ulearn.prepare()
    endtime = time.time()
    printer.print("Preparation took %s seconds" % (endtime - starttime))

    # Learn
    starttime = time.time()
    if adaptive_learning_rate and left_out:
        left_out_rate = 0.3333
        printer.print("Using %s of the data to validate." % left_out_rate)
        actual_results = ulearn.learn_adaptive_rate_left_out(increase_rate=increase_rate, decrease_rate=decrease_rate,
                                                             left_out=left_out_rate)
    elif adaptive_learning_rate and not left_out:
        actual_results = ulearn.learn_adaptive_rate(increase_rate=increase_rate, decrease_rate=decrease_rate)
    else:
        actual_results = ulearn.learn()
    endtime = time.time()
    printer.print("---")
    printer.print("Ran %s seconds." % (endtime - starttime))
    return actual_results