# Script to scrape all levels.
# geckodriver needs to be downloaded, and be in PATH

from selenium import webdriver
from time import sleep
import json, os, datetime
from termcolor import cprint

import constants

current_dir = os.getcwd()
data_dir = 'data'.join(current_dir.rsplit('code', 1))
level_dir = os.path.join(data_dir, 'levels')

if not os.path.exists(level_dir):
    os.makedirs(level_dir)

def get_levels_ids(driver):
    levels = driver.execute_script('return this.levelList;')
    levels_ids = list(map(lambda l: l['levelId'], filter(lambda l: l is not None, levels)))

    sleep(0.25)

    return levels_ids

def parse_level(driver, level_id):
    level = {}
    driver.execute_script('this.controller.requestGame(%d)' % level_id)
    for i in range(20):
        sleep(0.2)
        current_id = driver.execute_script('return this.controller && this.controller.gm && this.controller.gm.gameId;')
        if current_id == level_id:
            break
    else:
        cprint('%s: Scraping failed: %s' % (datetime.datetime.now(), level_name), 'red')
        return {}

    grid = driver.execute_script('return this.__g.getCurrentMap().getGrid();')

    # Compute everything.
    width = len(grid)
    height = len(grid[0])

    man_row, man_col = None, None
    boxes = []
    targets = []
    isWall = [ [False for c in range(width)] for r in range(height)]

    for r in range(height):
        for c in range(width):
            square = grid[c][r]
            if square['landscape'] == 3: isWall[r][c] = True
            if square['object'] == 1: man_row, man_col = r, c
            if square['object'] == 2:
                boxes.append((r,c))
            if square['isLocation']:
                targets.append((r,c))

    # Save 
    level['width'] = width
    level['height'] = height
    level['isWall'] = isWall
    level['man_row'] = man_row
    level['man_col'] = man_col
    level['boxes'] = sorted(boxes)
    level['targets'] = sorted(targets)
    return level

def save_level(level, level_name):
    level_text = json.dumps(level, sort_keys=True)
    level_name = os.path.join(level_dir, level_name)
    with open(level_name, 'w') as out:
        out.write(level_text)

driver = webdriver.Firefox()
driver.get(constants.SITE_URL)

sleep(0.25)

levels_ids = get_levels_ids(driver)

for level_id in levels_ids:
    level_name = constants.get_level_name(level_id)
    cprint('%s: Scraping: %s' % (datetime.datetime.now(), level_name), 'green')

    level = parse_level(driver, level_id)
    save_level(level, level_name)

driver.quit()
