from domonic.javascript import Math

"""
t : current time
b : start value
c : change
d : total time

http://robertpenner.com/easing/

"""


class Back:
    @staticmethod
    def easeIn(t, b, c, d, aa, bb, s=1.70158):
        t /= d
        return c * t * t * ((s + 1) * t - s) + b

    @staticmethod
    def easeOut(t, b, c, d, aa, bb, s=1.70158):
        t = t / d - 1
        return c * (t * t * ((s + 1) * t + s) + 1) + b

    @staticmethod
    def easeInOut(t, b, c, d, aa, bb, s=1.70158):
        t /= d / 2
        s *= 1.525
        if t < 1:
            return c / 2 * (t * t * ((s + 1) * t - s)) + b

        t -= 2
        return c / 2 * (t * t * ((s + 1) * t + s) + 2) + b


class Bounce:
    @staticmethod
    def easeIn(t, b, c, d, aa=0, bb=0):
        return c - Bounce.easeOut(d - t, 0, c, d) + b

    @staticmethod
    def easeOut(t, b, c, d, aa=0, bb=0):
        t /= d
        if t < (1 / 2.75):
            return c * (7.5625 * t * t) + b

        elif t < (2 / 2.75):
            t -= 1.5 / 2.75
            return c * (7.5625 * t * t + 0.75) + b

        elif t < (2.5 / 2.75):
            t -= 2.25 / 2.75
            return c * (7.5625 * t * t + 0.9375) + b

        else:
            t -= 2.625 / 2.75
            return c * (7.5625 * t * t + 0.984375) + b

    @staticmethod
    def easeInOut(t, b, c, d, aa=0, bb=0):
        if t < d / 2:
            return Bounce.easeIn(t * 2, 0, c, d) * 0.5 + b
        return Bounce.easeOut(t * 2 - d, 0, c, d) * 0.5 + c * 0.5 + b


class Circ:
    @staticmethod
    def easeIn(t, b, c, d, aa, bb):
        t /= d
        return -c * (Math.sqrt(1 - t * t) - 1) + b

    @staticmethod
    def easeOut(t, b, c, d, aa, bb):
        t /= d
        t -= 1
        return c * Math.sqrt(1 - t * t) + b

    @staticmethod
    def easeInOut(t, b, c, d, aa, bb):
        t /= d / 2
        if t < 1:
            return -c / 2 * (Math.sqrt(1 - t * t) - 1) + b
        t -= 2
        return c / 2 * (Math.sqrt(1 - t * t) + 1) + b


class Cubic:
    @staticmethod
    def easeIn(t, b, c, d, aa, bb):
        t /= d
        return c * t * t * t + b

    @staticmethod
    def easeOut(t, b, c, d, aa, bb):
        t /= d
        t -= 1
        return c * (t * t * t + 1) + b

    @staticmethod
    def easeInOut(t, b, c, d, aa, bb):
        t /= d / 2
        if t < 1:
            return c / 2 * t * t * t + b
        t -= 2
        return c / 2 * (t * t * t + 2) + b


class Elastic:
    @staticmethod
    def easeIn(t, b, c, d, aa, bb):
        s = 1.70158
        p = 0
        a = c
        if t == 0:
            return b

        t /= d
        if t == 1:
            return b + c

        if not p:
            p = d * 0.3

        if a < abs(c):
            a = c
            s = p / 4
        else:
            s = p / (2 * Math.PI) * Math.asin(c / a)

        t -= 1
        return -(a * Math.pow(2, 10 * t) * Math.sin((t * d - s) * (2 * Math.PI) / p)) + b

    @staticmethod
    def easeOut(t, b, c, d, aa, bb):
        s = 1.70158
        p = 0
        a = c
        if t == 0:
            return b

        t /= d
        if t == 1:
            return b + c

        if not p:
            p = d * 0.3

        if a < abs(c):
            a = c
            s = p / 4
        else:
            s = p / (2 * Math.PI) * Math.asin(c / a)

        return a * Math.pow(2, -10 * t) * Math.sin((t * d - s) * (2 * Math.PI) / p) + c + b

    @staticmethod
    def easeInOut(t, b, c, d, aa, bb):
        s = 1.70158
        p = 0
        a = c
        if t == 0:
            return b

        t /= d / 2
        if t == 2:
            return b + c

        if not p:
            p = d * (0.3 * 1.5)

        if a < abs(c):
            a = c
            s = p / 4
        else:
            s = p / (2 * Math.PI) * Math.asin(c / a)

        if t < 1:
            t -= 1
            return -a / 2 * Math.pow(2, 10 * t) * Math.sin((t * d - s) * (2 * Math.PI) / p) + b

        t -= 1
        return a * Math.pow(2, -10 * t) * Math.sin((t * d - s) * (2 * Math.PI) / p) * 0.5 + c + b


class Expo:
    @staticmethod
    def easeIn(t, b, c, d, aa, bb):
        return c * Math.pow(2, 10 * (t / d - 1)) + b

    @staticmethod
    def easeOut(t, b, c, d, aa, bb):
        return c * (-Math.pow(2, -10 * t / d) + 1) + b

    @staticmethod
    def easeInOut(t, b, c, d, aa, bb):
        t /= d / 2
        if t < 1:
            return c / 2 * Math.pow(2, 10 * (t - 1)) + b
        t -= 1
        return c / 2 * (-Math.pow(2, -10 * t) + 2) + b


class Linear:

    # lambda t, b, c, d : c*t/d + b

    @staticmethod
    def easeNone(t, b, c, d, aa, bb):
        return c * t / d + b

    @staticmethod
    def easeIn(t, b, c, d, aa, bb):
        return c * t / d + b

    @staticmethod
    def easeOut(t, b, c, d, aa, bb):
        return c * t / d + b

    @staticmethod
    def easeInOut(t, b, c, d, aa, bb):
        return c * t / d + b


class Quad:
    @staticmethod
    def easeIn(t, b, c, d, aa, bb):
        t /= d
        return c * t * t + b

    @staticmethod
    def easeOut(t, b, c, d, aa, bb):
        t /= d
        return -c * t * (t - 2) + b

    @staticmethod
    def easeInOut(t, b, c, d, aa, bb):
        t /= d / 2
        if t < 1:
            return c / 2 * t * t + b
        t -= 1
        return -c / 2 * (t * (t - 2) - 1) + b


class Quart:
    @staticmethod
    def easeIn(t, b, c, d, aa, bb):
        t /= d
        return c * t * t * t * t + b

    @staticmethod
    def easeOut(t, b, c, d, aa, bb):
        t /= d
        t -= 1
        return -c * (t * t * t * t - 1) + b

    @staticmethod
    def easeInOut(t, b, c, d, aa, bb):
        t /= d / 2
        if t < 1:
            return c / 2 * t * t * t * t + b
        t -= 2
        return -c / 2 * (t * t * t * t - 2) + b


class Quint:
    @staticmethod
    def easeIn(t, b, c, d, aa, bb):
        t /= d
        return c * t * t * t * t * t + b

    @staticmethod
    def easeOut(t, b, c, d, aa, bb):
        t /= d
        t -= 1
        return c * (t * t * t * t * t + 1) + b

    @staticmethod
    def easeInOut(t, b, c, d, aa, bb):
        t /= d / 2
        if t < 1:
            return c / 2 * t * t * t * t * t + b
        t -= 2
        return c / 2 * (t * t * t * t * t + 2) + b


class Sine:
    @staticmethod
    def easeIn(t, b, c, d, aa, bb):
        return -c * Math.cos(t / d * (Math.PI / 2)) + c + b

    @staticmethod
    def easeOut(t, b, c, d, aa, bb):
        return c * Math.sin(t / d * (Math.PI / 2)) + b

    @staticmethod
    def easeInOut(t, b, c, d, aa, bb):
        return -c / 2 * (Math.cos(Math.PI * t / d) - 1) + b


# class Angle():

#     @staticmethod
#     def easeIn(t, b, c, d, aa, bb):
#         return -c * (t/d - 1) + b

#     @staticmethod
#     def easeOut(t, b, c, d, aa, bb):
#         return c * (t/d) + b

#     @staticmethod
#     def easeInOut(t, b, c, d, aa, bb):
#         if t==0:
#             return b
#         elif t==d:
#             return b+c
#         else:
#             return -c/2 * (t/d - 2) + b

# class Zoom():
#     @staticmethod
#     def easeIn(t, b, c, d, aa, bb):
#         return c * t/d + b

#     @staticmethod
#     def easeOut(t, b, c, d, aa, bb):
#         return c * (t - d/2)/d + b

#     @staticmethod
#     def easeInOut(t, b, c, d, aa, bb):
#         if t<d/2:
#             return c/2 * t/d + b
#         t-=d/2
#         return c/2 * (t/d - 1) + b

"""
class Exponential():
    
    @staticmethod
    def easeIn(t, b, c, d, aa, bb):
        if t == 0:
            return b
        else:
            return c * Math.pow(2, 10 * (t/d - 1)) + b

    @staticmethod
    def easeOut(t, b, c, d, aa, bb):
        if t == d:
            return b + c
        else:
            return c * (-Math.pow(2, -10 * t/d) + 1) + b

    @staticmethod
    def easeInOut(t, b, c, d, aa, bb):
        if t==0:
            return b
        elif t==d:
            return b+c

        t = t / (d * 0.5)

        if t < 1:
            return c/2 * Math.pow(2, 10 * (t - 1)) + b
        t -= 1
        return c/2 * (-Math.pow(2, -10 * t) + 2) + b
"""

# class PressIn():

#     @staticmethod
#     def easeIn(t, b, c, d, aa, bb):
#         return c - b*t/d

#     @staticmethod
#     def easeOut(t, b, c, d, aa, bb):
#         return b*t/d + c

#     @staticmethod
#     def easeInOut(t, b, c, d, aa, bb):
#         if t==0:
#             return b
#         t *= 2
#         if t < 1:
#             return c - b*t/d
#         return b*t/d + c
