#!/usr/bin/env python3
import os
import time
from collections import deque
from itertools import count
from Xlib import error
from strategy import State
from interaction import get_exapunks_window, focus_window, screenshot_board, \
                        press_keys, listen_keys, KEY_DELAY


MAX_SPEED_ROWS = 3


def save_screenshot(win):
    board = screenshot_board(win).convert('RGB')
    os.makedirs('screens', exist_ok=True)
    for i in count(1):
        path = 'screens/board%d.png' % i
        if not os.path.exists(path):
            print('save screenshot in', path)
            board.save(path)
            break


if __name__ == '__main__':
    try:
        win = get_exapunks_window()
        focus_window(win)

        listen_keys({'s': lambda: save_screenshot(win)})

        solutions = deque([], maxlen=3)

        while True:
            try:
                board = screenshot_board(win)

                state = State.detect(board)
                print('\033c', end='')
                print('parsed:')
                state.print()
                print()

                start = time.time()
                solution = state.solve()
                end = time.time()
                print('thought for', round((end - start) * 1000, 1), 'milliseconds')
            except (TypeError, AssertionError):
                print('\rerror during parsing, wait for a bit...', end='')
                time.sleep(0.05)
                continue
            except error.BadMatch:
                print('\rEXAPUNKS window lost, wait for a bit...', end='')
                time.sleep(0.5)
                continue

            if len(solutions) == 3 and solution.loops(solutions.popleft()):
                print('\rloop detected, wait for a bit...', end='')
                time.sleep(0.03)
            elif solution.moves:
                print('moves:', solution.keys())
                print('     score:', solution.score)
                if solutions:
                    print('prev score:', solutions[-1].score)
                print()

                print('target after moves:')
                solution.newstate.print()

                press_keys(win, solution.keys())

                keys_delay = len(solution.moves) * 2 * KEY_DELAY
                moves_delay = max(0, solution.delay() - keys_delay)
                print('wait for',  moves_delay, 'ms')
                time.sleep(moves_delay / 1000)
            elif state.nrows() - 2 <= MAX_SPEED_ROWS:
                print('no moves, speed up')
                press_keys(win, 'l')
                time.sleep(0.03)
            else:
                print('no moves')

            solutions.append(solution)
    except KeyboardInterrupt:
        print('interrupted, quitting')
