"""
very simple functions for overlapping line segments (or could be coordinates
or spans
"""
import sys


# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
def overlap_1d(line1, line2, touch_is_overlap=False):
    """
    determine if line1 or line2 overlap in a 1d plane. Note that:
    if max line1 == min line2 (or visa versa) then this is not considered an
    overlap

    Parameters
    ----------

    line1 :`tuple` of `int` or `float`
        The min [0] and max [1] boundaries of the first line
    line2 :`tuple` of `int` or `float`
        The min [0] and max [1] boundaries of the second line
    touch_is_overlap :`bool`
        If the lines are touching i.e. the end of one == the start of another
        then this is reported as an overlap wit the smallest unit available. so
        for ints this would be 1 and floats it is the smallest float available

    Returns
    -------

    overlap :`int` or `float`
        The amount of overlap or 0 if there is no overlap
    """
    is_int = True
    zero = 0

    # Are we dealing with all ints, if so we are ok, otherwise we have to make
    # everything floats
    if not all([isinstance(i, int) for i in line1]) or \
       not all([isinstance(i, int) for i in line2]):
        line1 = tuple([float(i) for i in line1])
        line2 = tuple([float(i) for i in line2])
        zero = 0.0
        is_int = False

    min1, max1 = line1
    min2, max2 = line2

    if touch_is_overlap is True:
        if is_int is True:
            min1 -= 1
            min2 -= 1
        else:
            min1 -= min1 * sys.float_info.epsilon
            min2 -= min2 * sys.float_info.epsilon

    return max(zero, min(max1, max2) - max(min1, min2))


# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
def who_spans_who(line1, line2):
    """
    determine if line1 spans line2 or line2 spans line1, or nether span either
    exact equaliy of coordinates == a span

    Parameters
    ----------

    line1 :`tuple` of `int` or `float`
        The min [0] and max [1] boundaries of the first line
    line2 :`tuple` of `int` or `float`
        The min [0] and max [1] boundaries of the second line

    Returns
    -------

    span :`tuple` of `bool`
        The tuple is of length 2, with element [0] indicating if line1 spans
        line2 and element [1] indicating if line 2 spans line 1. True indicates
        a span, False no span
    """

    line1_span = False
    line2_span = False

    # Are we dealing with all ints, if so we are ok, otherwise we have to make
    # everything floats
    if not all([isinstance(i, int) for i in line1]) or \
       not all([isinstance(i, int) for i in line2]):
        line1 = tuple([float(i) for i in line1])
        line2 = tuple([float(i) for i in line2])

    min1, max1 = line1
    min2, max2 = line2

    # Does line1 span line 2?
    if min1 <= min2 and max1 >= max2:
        line1_span = True

    # Does line2 span line 1?
    if min2 <= min1 and max2 >= max1:
        line2_span = True

    return line1_span, line2_span
