from PIL import Image
from datetime import datetime
from urllib.parse import parse_qs, urlparse, unquote

import constants
import cv2
import numpy as np
import re

def cv2_to_pil(cv_image: np.ndarray) -> Image.Image:
    """
    cv2.MatLike (BGR/RGB/Grayscale) → PIL.Image
    """
    if len(cv_image.shape) == 3 and cv_image.shape[2] == 3:
        cv_image = cv2.cvtColor(cv_image, cv2.COLOR_BGR2RGB)
    return Image.fromarray(cv_image)

def image_to_numpy(self, image: Image.Image) -> np.ndarray:
    """Конвертирует PIL Image в numpy array для OpenCV"""
    return np.array(image)

def get_normals(H: np.ndarray, R: np.ndarray, T: np.ndarray) -> np.ndarray:
    n = cv2.decomposeHomographyMat(H, constants.K, R, T)
    return n

def estimate_transformation_matrix(src_pts: np.ndarray, dst_pts: np.ndarray) -> tuple[np.ndarray, np.ndarray]:
    """Оценивает матрицу трансформации на основе сопоставленных точек"""
    # Используем RANSAC для оценки матрицы гомографии
    return cv2.findHomography(src_pts, dst_pts, cv2.RANSAC, 3.0, maxIters=1000)

def calc_camera_matrix(w: float, h: float):
    f = constants._K_FOCUS_DISTANCE
    return np.array([
        [f, 0, w / 2],
        [0, f, h / 2],
        [0, 0, 1]
    ])


def generate_folder_name():
    """
    Генерирует название для папки с текущей датой и временем до секунд.
    Формат: YYYY-MM-DD_HH-MM-SS
    """
    now = datetime.now()
    folder_name = now.strftime("%Y-%m-%d_%H-%M-%S")
    return folder_name








def parse_yandex_maps_url(url):
    """
    Парсит URL Яндекс.Карт и извлекает lat, lon и zoom
    Формат: ?ll=lon,lat&z=zoom
    """
    # Декодируем URL (на случай %2C вместо запятых)
    url = unquote(url)
    
    # Парсим URL
    parsed_url = urlparse(url)
    params = parse_qs(parsed_url.query)
    
    if 'll' in params and 'z' in params:
        # ll содержит "lon,lat"
        ll_value = params['ll'][0]
        lat, lon = map(float, ll_value.split(','))
        zoom = int(params['z'][0])
        
        return {
            'lat': lat,
            'lon': lon,
            'zoom': zoom
        }
    return None

def parse_google_maps_url(url):
    """
    Парсит URL Google Maps и извлекает lat, lon и zoom
    Формат: /@lat,lon,zoom[m|z]
    """
    pattern = r'/@([-\d.]+),([-\d.]+),(\d+)([mz])'
    match = re.search(pattern, url)
    
    if match:
        lon = float(match.group(1))
        lat = float(match.group(2))
        zoom_value = int(match.group(3))
        zoom_unit = match.group(4)
        
        return {
            'lat': lat,
            'lon': lon,
            'zoom': zoom_value,
            'zoom_unit': zoom_unit
        }
    return None

def google_map_js_move_script(dx, dy) -> str:
    return """
async function sleep(ms) {
    return new Promise((resolve, reject) => {
        setTimeout(() => resolve(), ms);
    });
}

async function simulateDrag(element, offsetX, offsetY) {
    const rect = element.getBoundingClientRect();
    const startX = rect.left + rect.width / 2;
    const startY = rect.top + rect.height / 2;
    const step = 10
    const endX = startX + offsetX + step;
    const endY = startY + offsetY + step;

    element.dispatchEvent(new MouseEvent('mousedown', {
        view: window,
        bubbles: true,
        cancelable: true,
        clientX: startX,
        clientY: startY,
        button: 0
    }));
    
    let currentX = startX;
    let currentY = startY;

    function move(stepX, stepY) {
        currentX += stepX;
        currentY += stepY;

        document.dispatchEvent(new MouseEvent('mousemove', {
            view: window,
            bubbles: true,
            cancelable: false,
            clientX: currentX,
            clientY: currentY
        }));
    }

    await sleep(50);
    move(step, step)

    while (currentX != endX || currentY != endY) {
        await sleep(50);
        const stepX = Math.min(step, Math.max(-step, endX - currentX));
        const stepY = Math.min(step, Math.max(-step, endY - currentY));
        move(stepX, stepY);
    }

    await sleep(50)
    document.dispatchEvent(new MouseEvent('mouseup', {
        view: window,
        bubbles: true,
        cancelable: false,
        clientX: endX,
        clientY: endY,
        button: 0
    }));
}

{
    const canvas = document.querySelector('canvas.H1VXrf.JRr1M.DnOnV');
""" + f"simulateDrag(canvas, {int(-dx)}, {int(dy)});" + """
}
"""