import time
import logging
import struct
from screeninfo import get_monitors

logging.basicConfig(format='%(message)s')
log = logging.getLogger(__name__)

# evtype_sync = 0
# evtype_key = 1
e_type_abs = 3

# evcode_stylus_distance = 25
# evcode_stylus_xtilt = 26
# evcode_stylus_ytilt = 27
e_code_stylus_xpos = 1
e_code_stylus_ypos = 0
e_code_stylus_pressure = 24
evcode_finger_xpos = 53
evcode_finger_ypos = 54
evcode_finger_pressure = 58
evcode_finger_mv_id = 0x39

# wacom digitizer dimensions
wacom_width = 15725
wacom_height = 20967
# touchscreen dimensions
finger_width = 767
finger_height = 1023


# remap wacom coordinates to screen coordinates
def remap(x, y, wacom_width, wacom_height, monitor_width,
          monitor_height, mode, orientation):

    if orientation == 'bottom':
        y = wacom_height - y
    elif orientation == 'right':
        x, y = wacom_height - y, wacom_width - x
        wacom_width, wacom_height = wacom_height, wacom_width
    elif orientation == 'left':
        x, y = y, x
        wacom_width, wacom_height = wacom_height, wacom_width
    elif orientation == 'top':
        x = wacom_width - x

    ratio_width, ratio_height = monitor_width / wacom_width, monitor_height / wacom_height

    if mode == 'fill':
        scaling = max(ratio_width, ratio_height)
    elif mode == 'fit':
        scaling = min(ratio_width, ratio_height)
    else:
        raise NotImplementedError

    return (
        scaling * (x - (wacom_width - monitor_width / scaling) / 2),
        scaling * (y - (wacom_height - monitor_height / scaling) / 2)
    )


def read_tablet(args, remote_device):
    """Loop forever and map evdev events to mouse"""

    from pynput.mouse import Button, Controller

    lifted = True
    new_x = new_y = False

    mouse = Controller()

    monitor = get_monitors()[args.monitor]
    log.debug('Chose monitor: {}'.format(monitor))

    while True:
        _, _, e_type, e_code, e_value = struct.unpack('2IHHi', remote_device.read(16))

        if e_type == e_type_abs:

            # handle x direction
            if e_code == e_code_stylus_xpos:
                log.debug(e_value)
                x = e_value
                new_x = True

            # handle y direction
            if e_code == e_code_stylus_ypos:
                log.debug('\t{}'.format(e_value))
                y = e_value
                new_y = True

            # handle draw
            if e_code == e_code_stylus_pressure:
                log.debug('\t\t{}'.format(e_value))
                if e_value > args.threshold:
                    if lifted:
                        log.debug('PRESS')
                        lifted = False
                        mouse.press(Button.left)
                else:
                    if not lifted:
                        log.debug('RELEASE')
                        lifted = True
                        mouse.release(Button.left)


            # only move when x and y are updated for smoother mouse
            if new_x and new_y:
                mapped_x, mapped_y = remap(
                    x, y,
                    wacom_width, wacom_height,
                    monitor.width, monitor.height,
                    args.mode, args.orientation
                )
                mouse.move(
                    monitor.x + mapped_x - mouse.position[0],
                    monitor.y + mapped_y - mouse.position[1]
                )
                new_x = new_y = False

def read_finger(args, remote_device):
    """Loop forever and map evdev events to mouse"""

    from pynput.mouse import Button, Controller

    lifted = True
    new_x = new_y = False

    mouse = Controller()

    monitor = get_monitors()[args.monitor]
    log.debug('Chose monitor: {}'.format(monitor))

    rel_orig_x = -1
    rel_orig_y = -1

    last_x = 0
    last_y = 0

    while True:
        _, _, e_type, e_code, e_value = struct.unpack('2IHHi', remote_device.read(16))

        if e_type == e_type_abs:

            # handle x direction
            if e_code == evcode_finger_xpos:
                log.debug(e_value)

                if rel_orig_x == -1:
                    print("test")
                    t_mv_start = time.time();
                    rel_orig_x = e_value

                x = e_value
                new_x = True

            # handle y direction
            if e_code == evcode_finger_ypos:
                log.debug('\t{}'.format(e_value))

                if rel_orig_y == -1:
                    rel_orig_y = e_value

                y = e_value
                new_y = True

            if e_code == evcode_finger_mv_id:
                if e_value == -1:
                    if rel_orig_x == x and rel_orig_y == y:
                        print(time.time() - t_mv_start)
                        if (time.time() - t_mv_start) < 0.5:
                            mouse.press(Button.left)
                            mouse.release(Button.left)
                        else:
                            mouse.press(Button.right)
                            mouse.release(Button.right)
                    rel_orig_x = -1
                    rel_orig_y = -1
                    last_x = 0
                    last_y = 0

            # only move when x and y are updated for smoother mouse
            if new_x and new_y:

                if rel_orig_x != -1 and rel_orig_y != -1:
                    x_vect = y - rel_orig_y
                    y_vect = rel_orig_x - x

                    if(args.orientation == "bottom"):
                        mouse.move(old_x - x, old_y - y)
                    if(args.orientation == "top"):
                        mouse.move(x - old_x, y - old_y)
                    if(args.orientation == "left"):
                        mouse.move(2 * (x_vect - last_x), 2 * (y_vect - last_y))
                    if(args.orientation == "right"):
                        mouse.move(old_y - y, x - old_x)

                    new_x = new_y = False

                    last_x = x_vect
                    last_y = y_vect


