class Ball(Animation):
    BALL_STOP_BOUND = 1.3
    MAX_VELOCITY = 10

    def __init__(self, manager, position, frame, sfx, speed=1000):
        Animation.__init__(self, manager, frame, speed)
        self.collision = Collision()
        self.set_position_center(position[0], position[1])
        self.change_x = 0
        self.change_y = 0
        self.radius = 15.5
        self.is_ball_going_in = False
        self.is_ball_hit_wall = False
        self.goal = False
        self.m = 0.45
        self.prevent = 1.01
        self.ball_vs_wall_observable = BallVsWallObservable()
        self.ball_vs_wall_observer = BallVsWallObserver(sfx)
        self.ball_vs_wall_observable.register(self.ball_vs_wall_observer)

    def calc_frame_step(self):
        cx = math.fabs(self.change_x)
        cy = math.fabs(self.change_y)
        if max(cx, cy) == 0:
            return 1
        # elif 2 >= cx > 0.6 or 2 >= cy > 0.6:
        #     return 1
        elif 4 > cx > 2 or 4 > cy > 2:
            self.speed = 1000
            return 2
        elif 5 > cx >= 4 or 5 > cy >= 4:
            self.speed = 1000
            return 3
        elif cx >= 5 or cy >= 5:
            self.speed = 1000
            return 4
        else:
            self.speed = int(1000 * 0.5 / (self.change_x + self.change_y))
            # self.speed = 1000 - 80 / (self.change_x + self.change_y)
            return 1

    def update(self):
        if self.change_x + self.change_y == 0:
            self.is_static = True
        else:
            self.is_static = False
        Animation.update(self)
        if (
            self.rect.center[1] + self.change_y < constants.PLAY_SPACE_RECT[1]
            or self.rect.center[1] + self.change_y > constants.PLAY_SPACE_RECT[1] + constants.PLAY_SPACE_RECT[3]
        ):
            self.change_y = 0
        # if ((self.rect.center[0] + self.change_x < constants.PLAY_SPACE_RECT[0] or self.rect.center[0] + self.change_x >
        #         constants.PLAY_SPACE_RECT[0] + constants.PLAY_SPACE_RECT[2]) \
        #             and (self.rect.center[1] - self.radius + self.change_y < 260 or self.rect.center[1] + self.radius + self.change_y > 433)):
        #     self.change_x = 0
        self.max_min_velocity()
        if 1 > self.change_y > 0:
            self.rect.y += 1
        elif -1 < self.change_y < 0:
            self.rect.y -= 1
        else:
            self.rect.y += round(self.change_y)
        if 1 > self.change_x > 0:
            self.rect.x += 1
        elif -1 < self.change_x < 0:
            self.rect.x -= 1
        else:
            self.rect.x += round(self.change_x)
        self.collision.collisionBall2Wall(self, self.ball_vs_wall_observable)
        self.change_x /= self.prevent
        self.change_y /= self.prevent

        if self.change_x == 0:
            if self.change_y > 0:
                self.degree = -90
            else:
                self.degree = 90
        elif self.change_y == 0:
            if self.change_x > 0:
                self.degree = 0
            else:
                self.degree = 180
        else:
            self.degree = math.atan(math.fabs(self.change_y) / math.fabs(self.change_x)) * 180 / math.pi
            if self.change_x > 0 and self.change_y > 0:
                self.degree = -self.degree
            elif self.change_x > 0 > self.change_y:
                pass
            elif self.change_x < 0 < self.change_y:
                self.degree += 180
            elif self.change_x < 0 and self.change_y < 0:
                self.degree += (90 - self.degree) * 2
        # print(self.degree)
        self.rotate(self.degree)

    def set_velocity(self, vx, vy):
        self.change_x = vx
        self.change_y = vy

    def max_min_velocity(self):
        if self.change_y > Ball.MAX_VELOCITY:
            self.change_y = Ball.MAX_VELOCITY
        if self.change_x > Ball.MAX_VELOCITY:
            self.change_x = Ball.MAX_VELOCITY
        if (
            Ball.BALL_STOP_BOUND > self.change_x > -Ball.BALL_STOP_BOUND
            and Ball.BALL_STOP_BOUND > self.change_y > -Ball.BALL_STOP_BOUND
        ):
            self.change_x = 0
            self.change_y = 0