import math
import os
import re
from glob import glob
from pathlib import Path

from PIL import Image

from . import DUMP, MAP_FILE, MAPS


# Obtains area maps in the US to overlay radar images on.
class AreaMap:
    # Max latitude of US map in a linear form.
    LAT_MAX = 1.0799224683069641
    # Reference latitude in linear form.
    REF_LAT = 0.7380009964270406

    def __init__(self):
        # Coordinates of area.
        self.lat1 = None
        self.lon1 = None
        self.lat2 = None
        self.lon2 = None
        # Area ID.
        self.area_id = None
        # The area map.
        self.map = None

    # Get map configuration information.
    def get_config(self):
        """

        :return: True if successful, False if not
        """
        # Look for any radar map config files.
        files = glob(os.path.join(DUMP, '*DWRI*'))
        if not files:
            return False
        # Extract info from first file.
        file = open(files[0], 'r')
        for line in file:
            if 'DWR_Area_ID' in line:
                self.area_id = re.findall(r'\"(.+?)\"', line)[0]
            elif 'Coordinates' in line:
                coords = re.findall(r"[-+]?\d*\.\d+|\d+", line)
                self.lat1, self.lon1, self.lat2, self.lon2 = (float(x) for x in coords)
        return True

    # Checks if a config file has been received.
    def has_config(self):
        return self.area_id is not None

    # Render an area map from the US map.
    def render(self):
        # Open US map.
        us_map = Image.open(MAP_FILE)
        # Convert latitudes to a linear form.
        self.lat1 = AreaMap.LAT_MAX - math.asinh(math.tan(math.radians(self.lat1)))
        self.lat2 = AreaMap.LAT_MAX - math.asinh(math.tan(math.radians(self.lat2)))
        # Calculate x-coords using a ratio of a known location on the map.
        x1 = (self.lon1 + 130.781250) * 7162 / 39.34135
        x2 = (self.lon2 + 130.781250) * 7162 / 39.34135
        # Use another ratio of a known location to find the latitudes.
        den = AreaMap.LAT_MAX - AreaMap.REF_LAT
        y1 = self.lat1 * 3565 / den
        y2 = self.lat2 * 3565 / den
        # Crop the map.
        cropped = us_map.crop((
            int(x1),
            int(y1),
            int(x2),
            int(y2)
        ))
        # Resize to 900x900, convert to right format, and save.
        self.map = cropped.resize((900, 900))
        self.map = self.map.convert('RGBA')
        name = '{0}.png'.format(self.area_id)
        self.map.save(os.path.join(MAPS, name))

    # Get an area map for the predefined area.
    def get_map(self):
        # If already in memory, just return it.
        if self.map is not None:
            return self.map
        # Check if an area map has already been rendered.
        name = '{0}.png'.format(self.area_id)
        file = Path(os.path.join(MAPS, name))
        if file.is_file():
            # Open and return image.
            self.map = Image.open(file.absolute()).convert('RGBA')
            return self.map
        else:
            # Else, render it and return.
            self.render()
            return self.map