import math
import cocos
import pyglet.window.key as key
from app import keyboard_state


class RTSCameraMotion(cocos.actions.Action):
    scale_levels = [0.5, 0.8, 1.0, 1.5, 2.0, 3.0, 5.0, 10.0]

    def __init__(self):
        super().__init__()

    def step(self, dt):
        position = getattr(self.target, 'position', (0, 0))
        speed = getattr(self.target, 'speed', (0, 0))
        force = getattr(self.target, 'force', 10000)
        mu_k = getattr(self.target, 'mu_k', 9)
        scale_request_idx = getattr(self.target, 'scale_request_idx', 3)

        # Handle Acceleration
        speed = (speed[0] + (keyboard_state[key.RIGHT] - keyboard_state[key.LEFT]) * dt * force,
                 speed[1] + (keyboard_state[key.UP] - keyboard_state[key.DOWN]) * dt * force)
        # Handle Damping
        ds = (-mu_k*speed[0]*dt, -mu_k*speed[1]*dt)
        speed = (speed[0]+ds[0] if abs(ds[0]) < abs(speed[0]) else 0,
                 speed[1]+ds[1] if abs(ds[1]) < abs(speed[1]) else 0)
        # Update position and speed
        self.target.speed = speed
        self.target.position = (position[0] + speed[0]*dt, position[1] + speed[1]*dt)

        if scroller := getattr(self.target, 'scroller'):
            scroller.set_focus(self.target.x, self.target.y)
            scroller.scale += 5*(self.scale_levels[scale_request_idx] - scroller.scale)*dt

            # Keep object in bounds as calculated by the scroller
            if self.target.x != scroller.restricted_fx:
                self.target.position = (scroller.restricted_fx, self.target.position[1])
                self.target.speed = (0.0, self.target.speed[1])
            if self.target.y != scroller.restricted_fy:
                self.target.position = (self.target.position[0], scroller.restricted_fy)
                self.target.speed = (self.target.speed[1], 0.0)


class RTSCamera(cocos.layer.ScrollingManager):

    def __init__(self):
        pass

    def init(self):
        super().__init__()

        self.cam = cocos.cocosnode.CocosNode()
        self.cam.scroller = self
        self.cam_layer = cocos.layer.ScrollableLayer()
        self.cam_layer.add(self.cam)
        self.cam_motion = RTSCameraMotion()
        self.cam.do(self.cam_motion)
        self.add(self.cam_layer)

        self.overlay_layer = cocos.layer.ScrollableLayer()
        self.add(self.overlay_layer, z=1)


    @property
    def cam_position(self):
        return self.cam.position

    @cam_position.setter
    def cam_position(self, new_position):
        self.cam.position = new_position

    def zoom(self, delta):
        scale_request_idx_new = getattr(self.cam, 'scale_request_idx', 3) + delta
        if 0 <= scale_request_idx_new < len(self.cam_motion.scale_levels):
            self.cam.scale_request_idx = scale_request_idx_new


camera = RTSCamera()
