import json
import os
import warnings

from pyproj import Transformer

if __name__ == "__main__":
    from coords_dict import COORDS
else:
    from earthnet.coords_dict import COORDS

EXTREME_TILES = ["32UMC", "32UNC", "32UPC", "32UQC"]


def get_coords_from_cube(
    cubename: str, return_meso: bool = False, ignore_warning=False
):
    """

    Get the coordinates for a Cube in Lon-Lat-Grid.

    Args:
        cubename (str): cubename (has format tile_startyear_startmonth_startday_endyear_endmonth_endday_hrxmin_hrxmax_hrymin_hrymax_mesoxmin_mesoxmax_mesoymin_mesoymax.npz)
        return_meso (bool, optional): If True returns also the coordinates for the Meso-scale variables in the cube. Defaults to False.

    Returns:
        tuple: Min-Lon, Min-Lat, Max-Lon, Max-Lat or Min-Lon-HR, Min-Lat-HR, Max-Lon-HR, Max-Lat-HR, Min-Lon-Meso, Min-Lat-Meso, Max-Lon-Meso, Max-Lat-Meso
    """

    if not ignore_warning:
        warnings.warn(
            "Getting coordinates to a cube is experimental. The resulting coordinates on Lon-Lat-Grid will never be pixel perfect. Under certain circumstances, the whole bounding box might shifted by up to 0.02° in either direction. Use with caution. EarthNet2021 does not provide geo-referenced data."
        )

    (
        cubetile,
        _,
        _,
        hr_x_min,
        hr_x_max,
        hr_y_min,
        hr_y_max,
        meso_x_min,
        meso_x_max,
        meso_y_min,
        meso_y_max,
    ) = os.path.splitext(cubename)[0].split("_")

    tile = COORDS[cubetile]

    transformer = Transformer.from_crs(tile["EPSG"], 4326, always_xy=True)

    tile_x_min, tile_y_max = transformer.transform(
        tile["MinLon"], tile["MaxLat"], direction="INVERSE"
    )

    if cubetile in EXTREME_TILES:
        hr_x_min = int(hr_x_min) + 57
        hr_x_max = int(hr_x_max) + 57

    cube_x_min = tile_x_min + 20 * float(hr_y_min)
    cube_x_max = tile_x_min + 20 * float(hr_y_max)
    cube_y_min = tile_y_max - 20 * float(hr_x_min)
    cube_y_max = tile_y_max - 20 * float(hr_x_max)

    cube_lon_min, cube_lat_min = transformer.transform(cube_x_min, cube_y_max)
    cube_lon_max, cube_lat_max = transformer.transform(cube_x_max, cube_y_min)

    if return_meso:
        meso_x_min = tile_x_min + 20 * float(meso_x_min)
        meso_x_max = tile_x_min + 20 * float(meso_x_max)
        meso_y_min = tile_y_max - 20 * float(meso_y_min)
        meso_y_max = tile_y_max - 20 * float(meso_y_max)

        meso_lon_min, meso_lat_min = transformer.transform(meso_x_min, meso_y_max)
        meso_lon_max, meso_lat_max = transformer.transform(meso_x_max, meso_y_min)

        return (
            cube_lon_min,
            cube_lat_min,
            cube_lon_max,
            cube_lat_max,
            meso_lon_min,
            meso_lat_min,
            meso_lon_max,
            meso_lat_max,
        )

    else:
        return cube_lon_min, cube_lat_min, cube_lon_max, cube_lat_max


def get_coords_from_tile(tilename: str):
    """
    Get the Coordinates for a Tile in Lon-lat-grid.

    Args:
        tilename (str): 5 Letter MGRS tile

    Returns:
        tuple: Min-Lon, Min-Lat, Max-Lon, Max-Lat
    """
    tile = COORDS[tilename]

    return tile["MinLon"], tile["MinLat"], tile["MaxLon"], tile["MaxLat"]


if __name__ == "__main__":
    import fire

    fire.Fire()
