# Path: gbdxtools/images/rda_image.py
# class RDAImage(GeoDaskImage):
#     _default_proj = "EPSG:4326"
# 
#     def __new__(cls, op, **kwargs):
#         cls.__geo__ = RDAGeoAdapter(op.metadata, dfp=cls._default_proj)
#         cls.__geo_transform__ = cls.__geo__.geo_transform
#         cls.__geo_interface__ = cls.__geo__.geo_interface
#         cls._rda_op = op
#         self = super(RDAImage, cls).__new__(cls, op)
#         return rda_image_shift(self)
# 
#     def __getitem__(self, geometry):
#         im = super(RDAImage, self).__getitem__(geometry)
#         if isinstance(im, GeoDaskImage):
#             im._rda_op = self._rda_op
#         return im
# 
#     @property
#     def __daskmeta__(self):
#         return self.rda
# 
#     @property
#     def rda(self):
#         return self._rda_op
# 
#     @property
#     def rda_id(self):
#         return self.rda._rda_id
# 
#     @property
#     def metadata(self):
#         return self.rda.metadata
# 
#     @property
#     def ntiles(self):
#         size = float(self.rda.metadata['image']['tileXSize'])
#         return math.ceil((float(self.shape[-1]) / size)) * math.ceil(float(self.shape[1]) / size)
# 
#     def read(self, bands=None, quiet=True, **kwargs):
#         if not quiet:
#             print('Fetching Image... {} {}'.format(self.ntiles, 'tiles' if self.ntiles > 1 else 'tile'))
#         return super(RDAImage, self).read(bands=bands)
# 
#     def materialize(self, node=None, bounds=None, callback=None, out_format='TIF', **kwargs):
#         """
#           Materializes images into gbdx user buckets in s3.
#           Note: This method is only available to RDA based image classes. 
# 
#           Args:
#             node (str): the node in the graph to materialize
#             bounds (list): optional bbox for cropping what gets materialized in s3
#             out_format (str): VECTOR_TILE, VECTOR, TIF, TILE_STREAM
#             callback (str): a callback url like an `sns://`
#           Returns:
#             job_id (str): the job_id of the materialization 
#         """
#         kwargs.update({
#           "node": node,
#           "bounds": bounds,
#           "callback": callback,
#           "out_format": out_format
#         })
#         return self.rda._materialize(**kwargs)
# 
#     def materialize_status(self, job_id):
#         """
#           Checks the status of an materialize job.
# 
#           Args:
#             job_id (str): the node in the graph to materialize
#           Returns:
#             status (dict): the status of the job  
#         """
#         return self.rda._materialize_status(job_id)
# 
# Path: gbdxtools/rda/interface.py
# class RDA(object):
#     def __getattr__(self, name, **kwargs):
#         return Op(name=name, interface=Auth(), **kwargs)


from gbdxtools.images.rda_image import RDAImage
from gbdxtools.rda.interface import RDA
        src_proj (string): source EPSG string
            Define the source projection if it can't be automatically determined.

    Example:
        >>> img = S3Image('landsat-pds/c1/L8/139/045/LC08_L1TP_139045_20170304_20170316_01_T1/LC08_L1TP_139045_20170304_20170316_01_T1_B3.TIF')'''

    def __new__(cls, path, **kwargs):
        path = '/vsis3/{}'.format(path)
        graph = cls._build_graph(path, kwargs.get("proj", None), kwargs.get("src_proj", None))
        try:
            self = super(S3Image, cls).__new__(cls, graph)
        except KeyError as e:
            print(e)
            raise
        self = self.aoi(**kwargs)
        self._path = path
        self._graph = graph
        return self

    @staticmethod
    def _build_graph(path, proj=None, src_proj=None):
        s3 = rda.S3ImageTemplate(path=path)
        params = {
            "Dest pixel-to-world transform": "",
            "Resampling Kernel": "INTERP_BILINEAR",
            "SourceSRSCode": "",
            "Source pixel-to-world transform": "",
            "DestSRSCode": "",
            "Background Values": "[0]"
        }

# Path: gbdxtools/images/rda_image.py
# class RDAImage(GeoDaskImage):
#     _default_proj = "EPSG:4326"
# 
#     def __new__(cls, op, **kwargs):
#         cls.__geo__ = RDAGeoAdapter(op.metadata, dfp=cls._default_proj)
#         cls.__geo_transform__ = cls.__geo__.geo_transform
#         cls.__geo_interface__ = cls.__geo__.geo_interface
#         cls._rda_op = op
#         self = super(RDAImage, cls).__new__(cls, op)
#         return rda_image_shift(self)
# 
#     def __getitem__(self, geometry):
#         im = super(RDAImage, self).__getitem__(geometry)
#         if isinstance(im, GeoDaskImage):
#             im._rda_op = self._rda_op
#         return im
# 
#     @property
#     def __daskmeta__(self):
#         return self.rda
# 
#     @property
#     def rda(self):
#         return self._rda_op
# 
#     @property
#     def rda_id(self):
#         return self.rda._rda_id
# 
#     @property
#     def metadata(self):
#         return self.rda.metadata
# 
#     @property
#     def ntiles(self):
#         size = float(self.rda.metadata['image']['tileXSize'])
#         return math.ceil((float(self.shape[-1]) / size)) * math.ceil(float(self.shape[1]) / size)
# 
#     def read(self, bands=None, quiet=True, **kwargs):
#         if not quiet:
#             print('Fetching Image... {} {}'.format(self.ntiles, 'tiles' if self.ntiles > 1 else 'tile'))
#         return super(RDAImage, self).read(bands=bands)
# 
#     def materialize(self, node=None, bounds=None, callback=None, out_format='TIF', **kwargs):
#         """
#           Materializes images into gbdx user buckets in s3.
#           Note: This method is only available to RDA based image classes. 
# 
#           Args:
#             node (str): the node in the graph to materialize
#             bounds (list): optional bbox for cropping what gets materialized in s3
#             out_format (str): VECTOR_TILE, VECTOR, TIF, TILE_STREAM
#             callback (str): a callback url like an `sns://`
#           Returns:
#             job_id (str): the job_id of the materialization 
#         """
#         kwargs.update({
#           "node": node,
#           "bounds": bounds,
#           "callback": callback,
#           "out_format": out_format
#         })
#         return self.rda._materialize(**kwargs)
# 
#     def materialize_status(self, job_id):
#         """
#           Checks the status of an materialize job.
# 
#           Args:
#             job_id (str): the node in the graph to materialize
#           Returns:
#             status (dict): the status of the job  
#         """
#         return self.rda._materialize_status(job_id)
# 
# Path: gbdxtools/rda/interface.py
# class RDA(object):
#     def __getattr__(self, name, **kwargs):
#         return Op(name=name, interface=Auth(), **kwargs)


# Path: gbdxtools/images/s3_image.py
from gbdxtools.images.rda_image import RDAImage
from gbdxtools.rda.interface import RDA

        src_proj (string): source EPSG string
            Define the source projection if it can't be automatically determined.

    Example:
        >>> img = S3Image('landsat-pds/c1/L8/139/045/LC08_L1TP_139045_20170304_20170316_01_T1/LC08_L1TP_139045_20170304_20170316_01_T1_B3.TIF')'''

    def __new__(cls, path, **kwargs):
        path = '/vsis3/{}'.format(path)
        graph = cls._build_graph(path, kwargs.get("proj", None), kwargs.get("src_proj", None))
        try:
            self = super(S3Image, cls).__new__(cls, graph)
        except KeyError as e:
            print(e)
            raise
        self = self.aoi(**kwargs)
        self._path = path
        self._graph = graph
        return self

    @staticmethod
    def _build_graph(path, proj=None, src_proj=None):
        s3 = rda.S3ImageTemplate(path=path)
        params = {
            "Dest pixel-to-world transform": "",
            "Resampling Kernel": "INTERP_BILINEAR",
            "SourceSRSCode": "",
            "Source pixel-to-world transform": "",
            "DestSRSCode": "",
            "Background Values": "[0]"
        }

        if proj is not None: