import numpy as np

from packaging.version import parse
import pytest

import rasterio
from rasterio.enums import Resampling
from rasterio.windows import Window

# Rasterio exposes GDAL's resampling/decimation on I/O. These are the tests
# that it does this correctly.
#
# Rasterio's test dataset is 718 rows by 791 columns.

def test_read_out_shape_resample_down():
    with rasterio.open('tests/data/RGB.byte.tif') as s:
        out = np.zeros((8, 8), dtype=rasterio.ubyte)
        data = s.read(1, out=out)
        expected = np.array([
            [  0,   0,  20,  15,   0,   0,   0,   0],
            [  0,   6, 193,   9, 255, 127,  23,  39],
            [  0,   7,  27, 255, 193,  14,  28,  34],
            [  0,  31,  29,  44,  14,  22,  43,   0],
            [  0,   9,  69,  49,  17,  22, 255,   0],
            [ 11,   7,  13,  25,  13,  29,  33,   0],
            [  8,  10,  88,  27,  20,  33,  25,   0],
            [  0,   0,   0,   0,  98,  23,   0,   0]], dtype=np.uint8)
        assert (data == expected).all()  # all True.


def test_read_out_shape_resample_up():
    # Instead of testing array items, test statistics. Upsampling by an even
    # constant factor shouldn't change the mean.
    with rasterio.open('tests/data/RGB.byte.tif') as s:
        out = np.zeros((7180, 7910), dtype=rasterio.ubyte)
        data = s.read(1, out=out, masked=True)
        assert data.shape == (7180, 7910)
        assert data.mean() == s.read(1, masked=True).mean()


def test_read_downsample_alpha():
    with rasterio.Env(GTIFF_IMPLICIT_JPEG_OVR=False):
        with rasterio.open('tests/data/alpha.tif') as src:
            out = np.zeros((100, 100), dtype=rasterio.ubyte)
            assert src.width == 1223
            assert src.height == 1223
            assert src.count == 4
            assert src.read(1, out=out, masked=False).shape == out.shape
            # attempt decimated read of alpha band
            src.read(4, out=out, masked=False)


@pytest.mark.skipif(
    parse(rasterio.__gdal_version__) < parse('2.0dev'),
    reason="Extra resampling algorithms require GDAL>2.0")
def test_resample_alg():
    """default (nearest) and cubic produce different results"""
    with rasterio.open('tests/data/RGB.byte.tif') as s:
        out_shape = (s.height // 2, s.width // 2)
        nearest = s.read(1, out_shape=out_shape)
        cubic = s.read(1, out_shape=out_shape, resampling=Resampling.cubic)
        assert np.any(nearest != cubic)


@pytest.mark.skipif(
    parse(rasterio.__gdal_version__) < parse('2.0dev'),
    reason="Floating point windows require GDAL>2.0")
def test_float_window():
    """floating point windows work"""
    with rasterio.open('tests/data/RGB.byte.tif') as s:
        out_shape = (401, 401)
        window = Window(300.5, 300.5, 200.5, 200.5)
        s.read(1, window=window, out_shape=out_shape)
