from django.contrib.gis.geos import Polygon
import os
from osgeo import osr, gdal
from . import Driver, RASTER
from pandas import DataFrame, Panel


class GeotiffDriver(Driver):
    @classmethod
    def datatype(cls):
        return RASTER

    @classmethod
    def supports_related(cls):
        return False

    def ready_data_resource(self, **kwargs):
        """Other keyword args get passed in as a matter of course, like BBOX, time, and elevation, but this basic driver
        ignores them"""

        changed = self.cache_data_file(freshen='fresh' in kwargs and kwargs['fresh'])
    
        if changed:
            ds = gdal.Open(self.cached_basename + '.tif')
            nx = ds.RasterXSize
            ny = ds.RasterYSize
            x0, dx, _, y0, _, dy = ds.GetGeoTransform()
            xmin, xmax, ymin, ymax = (
                x0,
                x0+dx*nx,
                y0 if dy > 0 else y0 + dy*ny,
                y0 + dy*ny if dy > 0 else y0
            )

            crs = osr.SpatialReference()
            crs.ImportFromWkt(ds.GetProjection())

            self.resource.spatial_metadata.native_srs = crs.ExportToProj4()
            e4326 = osr.SpatialReference()
            e4326.ImportFromEPSG(4326)
            crx = osr.CoordinateTransformation(crs, e4326)
            x04326, y04326, _ = crx.TransformPoint(xmin, ymin)
            x14326, y14326, _ = crx.TransformPoint(xmax, ymax)
            self.resource.spatial_metadata.bounding_box = Polygon.from_bbox((x04326, y04326, x14326, y14326))
            self.resource.spatial_metadata.native_bounding_box = Polygon.from_bbox((xmin, ymin, xmax, ymax))
            self.resource.spatial_metadata.save()
            self.resource.save()

        return self.cache_path, (self.resource.slug, self.resource.spatial_metadata.native_srs, {
            'type': 'gdal',
            "file": self.cached_basename + '.tif'
        })

    def compute_spatial_metadata(self, **kwargs):
        """Other keyword args get passed in as a matter of course, like BBOX, time, and elevation, but this basic driver
        ignores them"""

        self.cache_data_file(True)

        ds = gdal.Open(self.cached_basename + '.tif')
        nx = ds.RasterXSize
        ny = ds.RasterYSize
        x0, dx, _, y0, _, dy = ds.GetGeoTransform()
        xmin, xmax, ymin, ymax = (
            x0,
            x0+dx*nx,
            y0 if dy > 0 else y0 + dy*ny,
            y0 + dy*ny if dy > 0 else y0
        )

        crs = osr.SpatialReference()
        crs.ImportFromWkt(ds.GetProjection())

        self.resource.spatial_metadata.native_srs = crs.ExportToProj4()
        e4326 = osr.SpatialReference()
        e4326.ImportFromEPSG(4326)
        crx = osr.CoordinateTransformation(crs, e4326)
        x04326, y04326, _ = crx.TransformPoint(xmin, ymin)
        x14326, y14326, _ = crx.TransformPoint(xmax, ymax)
        self.resource.spatial_metadata.bounding_box = Polygon.from_bbox((x04326, y04326, x14326, y14326))
        self.resource.spatial_metadata.native_bounding_box = Polygon.from_bbox((xmin, ymin, xmax, ymax))
        self.resource.spatial_metadata.save()
        self.resource.save()

    def get_data_fields(self, **kwargs):
        dtypes = {
            gdal.GDT_Byte : 'unsigned 8-bit integer',
            gdal.GDT_Int16 : '16-bit integer',
            gdal.GDT_Int32 : '32-bit integer',
            gdal.GDT_Float64 : 'long double-precision float',
            gdal.GDT_Unknown : 'string or other',
            gdal.GDT_UInt32 : 'unsigned 32-bit integer (sometimes used for RGB in broken files)'
        }

        _, (_, _, result) = self.ready_data_resource(**kwargs)