import json
import sys
from pathlib import Path

import cv2
import numpy as np

repo = Path.home() / 'TibiaPilotNG'
sys.path.insert(0, str(repo))

from src.repositories.radar.config import floorsImgs, pixelsColorsValues
from src.repositories.radar.extractors import getRadarImage
from src.repositories.radar.locators import getRadarToolsPosition
from src.utils.coordinate import getPixelFromCoordinate

data = json.loads((repo / 'file.json').read_text(encoding='utf-8-sig'))
waypoints = data['_default']['1']['config']['ng_cave']['waypoints']['items']
image = cv2.imread(str(repo / '.pilotng-live.png'), cv2.IMREAD_GRAYSCALE)
radar = getRadarImage(image, getRadarToolsPosition(image))
palette = np.array(sorted(set(pixelsColorsValues.values())), dtype=np.int16)
quantized = palette[
    np.abs(radar[:, :, None].astype(np.int16) - palette).argmin(axis=2)
].astype(np.uint8)
results = []
for floor in (7, 8, 9):
    route = [item['coordinate'] for item in waypoints
             if item['coordinate'][2] == floor]
    pixels = [getPixelFromCoordinate(item) for item in route]
    x0 = max(0, min(item[0] for item in pixels) - 150)
    y0 = max(0, min(item[1] for item in pixels) - 150)
    x1 = min(floorsImgs[floor].shape[1], max(item[0] for item in pixels) + 150)
    y1 = min(floorsImgs[floor].shape[0], max(item[1] for item in pixels) + 150)
    area = floorsImgs[floor][y0:y1, x0:x1]
    for scale in (0.25, 0.5, 1.0, 2.0):
        candidate = cv2.resize(
            quantized, None, fx=scale, fy=scale,
            interpolation=cv2.INTER_NEAREST,
        )
        if (candidate.shape[0] > area.shape[0] or
                candidate.shape[1] > area.shape[1]):
            continue
        mask = (candidate > 0).astype(np.uint8) * 255
        for method, match in (
            ('raw', cv2.matchTemplate(area, candidate, cv2.TM_CCOEFF_NORMED)),
            ('mask', cv2.matchTemplate(
                area, candidate, cv2.TM_CCORR_NORMED, mask=mask,
            )),
        ):
            _, score, _, position = cv2.minMaxLoc(match)
            if np.isfinite(score):
                results.append({
                    'floor': floor,
                    'scale': scale,
                    'method': method,
                    'score': round(float(score), 4),
                    'coordinate': [
                        31744 + x0 + position[0] + candidate.shape[1] // 2,
                        30976 + y0 + position[1] + candidate.shape[0] // 2,
                        floor,
                    ],
                })
print(json.dumps(sorted(results, key=lambda item: item['score'], reverse=True)[:20]))
