-----------------------------------------------------------------------
--
-- Copyright (c) 2010 Pierre Racine <pierre.racine@sbf.ulaval.ca>
--
-- This program is free software; you can redistribute it and/or
-- modify it under the terms of the GNU General Public License
-- as published by the Free Software Foundation; either version 2
-- of the License, or (at your option) any later version.
--
-- This program is distributed in the hope that it will be useful,
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-- GNU General Public License for more details.
--
-- You should have received a copy of the GNU General Public License
-- along with this program; if not, write to the Free Software Foundation,
-- Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
-----------------------------------------------------------------------

-----------------------------------------------------------------------
--
-- Copyright (c) 2009 Pierre Racine <pierre.racine@sbf.ulaval.ca>
--
-- This is free software; you can redistribute and/or modify it under
-- the terms of the GNU General Public Licence. See the COPYING file.
-----------------------------------------------------------------------

-----------------------------------------------------------------------
--- Test of "Get" functions for properties of the raster.
-----------------------------------------------------------------------

CREATE TABLE rt_band_properties_test (
    id numeric,
    description text,
    nbband integer,
    b1pixeltype text,
    b1hasnodatavalue boolean,
    b1nodatavalue float4,
    b1val float4,
    b2pixeltype text,
    b2hasnodatavalue boolean,
    b2nodatavalue float4,
    b2val float4,
    geomtxt text,
    rast raster
);

INSERT INTO rt_band_properties_test
VALUES ( 1, '1x1, nbband:2 b1pixeltype:4BUI b1hasnodatavalue:true b1nodatavalue:3 b2pixeltype:16BSI b2hasnodatavalue:false b2nodatavalue:13',
        2, --- nbband
        '4BUI', true, 3, 2,   --- b1pixeltype, b1hasnodatavalue, b1nodatavalue, b1val
        '16BSI', false, 13, 4, --- b2pixeltype, b2hasnodatavalue, b2nodatavalue, b2val
        'POLYGON((782325.5 26744042.5,782330.5 26744045.5,782333.5 26744040.5,782328.5 26744037.5,782325.5 26744042.5))',
(
'01' -- big endian (uint8 xdr)
||
'0000' -- version (uint16 0)
||
'0200' -- nBands (uint16 2)
||
'0000000000001440' -- scaleX (float64 5)
||
'00000000000014C0' -- scaleY (float64 -5)
||
'00000000EBDF2741' -- ipX (float64 782325.5)
||
'000000A84E817941' -- ipY (float64 26744042.5)
||
'0000000000000840' -- skewX (float64 3)
||
'0000000000000840' -- skewY (float64 3)
||
'27690000' -- SRID (int32 26919 - UTM 19N)
||
'0100' -- width (uint16 1)
||
'0100' -- height (uint16 1)
||
'4' -- hasnodatavalue set to true
||
'2' -- first band type (4BUI)
||
'03' -- novalue==3
||
'02' -- pixel(0,0)==2
||
'0' -- hasnodatavalue set to false
||
'5' -- second band type (16BSI)
||
'0D00' -- novalue==13
||
'0400' -- pixel(0,0)==4
)::raster
);

INSERT INTO rt_band_properties_test
VALUES ( 2, '1x1, nbband:2 b1pixeltype:4BUI b1hasnodatavalue:true b1nodatavalue:3 b2pixeltype:16BSI b2hasnodatavalue:false b2nodatavalue:13',
        2, --- nbband
        '4BUI', true, 3, 2,   --- b1pixeltype, b1hasnodatavalue, b1nodatavalue, b1val
        '16BSI', false, 13, 4, --- b2pixeltype, b2hasnodatavalue, b2nodatavalue, b2val
        'POLYGON((-75.55333285370983 49.28245855055764,-75.55252688847578 49.2826703629415,-75.55231507609193 49.28186439770746,-75.55312104132598 49.2816525853236,-75.55333285370983 49.28245855055764))',
(
'01' -- little endian (uint8 ndr)
||
'0000' -- version (uint16 0)
||
'0200' -- nBands (uint16 0)
||
'17263529ED684A3F' -- scaleX (float64 0.000805965234044584)
||
'F9253529ED684ABF' -- scaleY (float64 -0.00080596523404458)
||
'1C9F33CE69E352C0' -- ipX (float64 -75.5533328537098)
||
'718F0E9A27A44840' -- ipY (float64 49.2824585505576)
||
'ED50EB853EC32B3F' -- skewX (float64 0.000211812383858707)
||
'7550EB853EC32B3F' -- skewY (float64 0.000211812383858704)
||
'E6100000' -- SRID (int32 4326)
||
'0100' -- width (uint16 1)
||
'0100' -- height (uint16 1)
||
'4' -- hasnodatavalue set to true
||
'2' -- first band type (4BUI)
||
'03' -- novalue==3
||
'02' -- pixel(0,0)==2
||
'0' -- hasnodatavalue set to false
||
'5' -- second band type (16BSI)
||
'0D00' -- novalue==13
||
'0400' -- pixel(0,0)==4
)::raster
);

INSERT INTO rt_band_properties_test
VALUES ( 3, '1x1, nbband:2 b1pixeltype:4BUI b1hasnodatavalue:true b1nodatavalue:3 b2pixeltype:16BSI b2hasnodatavalue:false b2nodatavalue:13',
        2, --- nbband
        '4BUI', true, 3, 3,   --- b1pixeltype, b1hasnodatavalue, b1nodatavalue, b1val
        '16BSI', false, 13, 4, --- b2pixeltype, b2hasnodatavalue, b2nodatavalue, b2val
        'POLYGON((-75.55333285370983 49.28245855055764,-75.55252688847578 49.2826703629415,-75.55231507609193 49.28186439770746,-75.55312104132598 49.2816525853236,-75.55333285370983 49.28245855055764))',
(
'01' -- little endian (uint8 ndr)
||
'0000' -- version (uint16 0)
||
'0200' -- nBands (uint16 0)
||
'17263529ED684A3F' -- scaleX (float64 0.000805965234044584)
||
'F9253529ED684ABF' -- scaleY (float64 -0.00080596523404458)
||
'1C9F33CE69E352C0' -- ipX (float64 -75.5533328537098)
||
'718F0E9A27A44840' -- ipY (float64 49.2824585505576)
||
'ED50EB853EC32B3F' -- skewX (float64 0.000211812383858707)
||
'7550EB853EC32B3F' -- skewY (float64 0.000211812383858704)
||
'E6100000' -- SRID (int32 4326)
||
'0100' -- width (uint16 1)
||
'0100' -- height (uint16 1)
||
'6' -- hasnodatavalue and isnodata set to true
||
'2' -- first band type (4BUI)
||
'03' -- novalue==3
||
'03' -- pixel(0,0)==3 (same that nodata)
||
'0' -- hasnodatavalue set to false
||
'5' -- second band type (16BSI)
||
'0D00' -- novalue==13
||
'0400' -- pixel(0,0)==4
)::raster
);

INSERT INTO rt_band_properties_test
VALUES ( 4, '1x1, nbband:2 b1pixeltype:4BUI b1hasnodatavalue:true b1nodatavalue:3 b2pixeltype:16BSI b2hasnodatavalue:false b2nodatavalue:13',
        2, --- nbband
        '4BUI', true, 3, 3,   --- b1pixeltype, b1hasnodatavalue, b1nodatavalue, b1val
        '16BSI', false, 13, 4, --- b2pixeltype, b2hasnodatavalue, b2nodatavalue, b2val
        'POLYGON((-75.55333285370983 49.28245855055764,-75.55252688847578 49.2826703629415,-75.55231507609193 49.28186439770746,-75.55312104132598 49.2816525853236,-75.55333285370983 49.28245855055764))',
(
'01' -- little endian (uint8 ndr)
||
'0000' -- version (uint16 0)
||
'0200' -- nBands (uint16 0)
||
'17263529ED684A3F' -- scaleX (float64 0.000805965234044584)
||
'F9253529ED684ABF' -- scaleY (float64 -0.00080596523404458)
||
'1C9F33CE69E352C0' -- ipX (float64 -75.5533328537098)
||
'718F0E9A27A44840' -- ipY (float64 49.2824585505576)
||
'ED50EB853EC32B3F' -- skewX (float64 0.000211812383858707)
||
'7550EB853EC32B3F' -- skewY (float64 0.000211812383858704)
||
'E6100000' -- SRID (int32 4326)
||
'0100' -- width (uint16 1)
||
'0100' -- height (uint16 1)
||
'4' -- hasnodatavalue set to true and isnodata set to false (should be updated)
||
'2' -- first band type (4BUI)
||
'03' -- novalue==3
||
'03' -- pixel(0,0)==3 (same that nodata)
||
'0' -- hasnodatavalue set to false
||
'5' -- second band type (16BSI)
||
'0D00' -- novalue==13
||
'0400' -- pixel(0,0)==4
)::raster
);

-----------------------------------------------------------------------
-- Test 1 - st_value(rast raster, band integer, x integer, y integer)
-----------------------------------------------------------------------

SELECT 'test 1.1', id
    FROM rt_band_properties_test
    WHERE st_value(rast, 1, 1, 1, TRUE) != b1val;

SELECT 'test 1.2', id
    FROM rt_band_properties_test
    WHERE st_value(rast, 2, 1, 1, TRUE) != b2val;

SELECT 'test 1.3', id
    FROM rt_band_properties_test
    WHERE st_value(rast, 1, 1, 1, FALSE) != b1val;

SELECT 'test 1.4', id
    FROM rt_band_properties_test
    WHERE st_value(rast, 1, 1, 1, NULL) != b1val;

SELECT 'test 1.5', id
    FROM rt_band_properties_test
    WHERE NOT st_value(rast, 1, 1, NULL, NULL) IS NULL;

SELECT 'test 1.6', id
    FROM rt_band_properties_test
    WHERE NOT st_value(rast, 1, NULL, 1, NULL) IS NULL;

SELECT 'test 1.7', id
    FROM rt_band_properties_test
    WHERE NOT st_value(st_setbandnodatavalue(rast, b1val), 1, 1, 1, NULL) IS NULL;

SELECT 'test 1.8', id
    FROM rt_band_properties_test
    WHERE NOT st_value(st_setbandnodatavalue(rast, b1val), 1, 1, 1, TRUE) IS NULL;

SELECT 'test 1.9', id
    FROM rt_band_properties_test
    WHERE st_value(st_setbandnodatavalue(rast, b1val), 1, 1, 1, FALSE) != b1val;

-- Make sure we return only a warning when getting value with out of range pixel coordinates
SELECT 'test 1.10', id
    FROM rt_band_properties_test
    WHERE NOT st_value(rast, -1, -1) IS NULL;

-----------------------------------------------------------------------
-- Test 2 - st_value(rast raster, band integer, pt geometry)
--        - st_value(rast raster, band integer, pt geometry,
--                   boolean exclude_nodata_value=true, text resample)
-----------------------------------------------------------------------

SELECT 'test 2.1', id
    FROM rt_band_properties_test
    WHERE st_value(rast, 1, st_makepoint(st_upperleftx(rast), st_upperlefty(rast))) != b1val;

SELECT 'test 2.2', id
    FROM rt_band_properties_test
    WHERE st_value(rast, 2, st_makepoint(st_upperleftx(rast), st_upperlefty(rast))) != b2val;

SELECT 'test 2.3', id, st_value(rast, 1,
	ST_Centroid(rast::geometry),
		 true, 'bilinear') AS val
    FROM rt_band_properties_test
    WHERE id = 1;

SELECT '#5410', id, st_value(
		ST_SetBandNoDataValue(rast,1,NULL), 1,
		ST_Centroid(rast::geometry),
		 true, 'bilinear') As val
	FROM rt_band_properties_test
	WHERE id = 1;
-----------------------------------------------------------------------
-- Test 3 - st_pixelaspolygon(rast raster, x integer, y integer)
-----------------------------------------------------------------------

SELECT 'test 3.1', id
    FROM rt_band_properties_test
    WHERE st_astext(st_pixelaspolygon(rast, 1, 1)) != geomtxt;

-----------------------------------------------------------------------
-- Test 4 - st_setvalue(rast raster, band integer, x integer, y integer, val float8)
-----------------------------------------------------------------------

SELECT 'test 4.1', id
    FROM rt_band_properties_test
    WHERE st_value(st_setvalue(rast, 1, 1, 1, 5), 1, 1, 1) != 5;

SELECT 'test 4.2', id
    FROM rt_band_properties_test
    WHERE NOT st_value(st_setvalue(rast, 1, 1, 1, NULL), 1, 1, 1) IS NULL;

SELECT 'test 4.3', id
    FROM rt_band_properties_test
    WHERE st_value(st_setvalue(rast, 1, 1, 1, NULL), 1, 1, 1, FALSE) != st_bandnodatavalue(rast, 1);

SELECT 'test 4.4', id
    FROM rt_band_properties_test
    WHERE st_value(st_setvalue(st_setbandnodatavalue(rast, NULL), 1, 1, 1, NULL), 1, 1, 1) != b1val;

DROP TABLE rt_band_properties_test;

-----------------------------------------------------------------------
-- Test 5 - st_setvalue(rast raster, band integer, geometry, resample)
-----------------------------------------------------------------------

WITH r AS (
SELECT
ST_SetValues(
  ST_AddBand(
    ST_MakeEmptyRaster(width => 2, height => 2,
      upperleftx => 0, upperlefty => 2,
      scalex => 1.0, scaley => -1.0,
      skewx => 0, skewy => 0, srid => 4326),
    index => 1, pixeltype => '16BSI',
    initialvalue => 0,
    nodataval => -999),
  1,1,1,
  newvalueset =>ARRAY[ARRAY[10.0::float8, 50.0::float8], ARRAY[40.0::float8, 20.0::float8]]) AS rast
)
SELECT
'Test 5',
round(ST_Value(rast, 1, 'SRID=4326;POINT(1.5 1.5)'::geometry, resample => 'nearest')) as nearest_15_15,
round(ST_Value(rast, 1, 'SRID=4326;POINT(0.5 0.5)'::geometry, resample => 'nearest')) as nearest_05_05,
round(ST_Value(rast, 1, 'SRID=4326;POINT(1.0 1.0)'::geometry, resample => 'bilinear')) as nearest_10_10,
round(ST_Value(rast, 1, 'SRID=4326;POINT(1.0 0.1)'::geometry, resample => 'bilinear')) as nearest_10_00,
round(ST_Value(rast, 1, 'SRID=4326;POINT(1.0 1.9)'::geometry, resample => 'bilinear')) as nearest_10_20
FROM r;

WITH r AS (
SELECT
ST_SetValues(
  ST_AddBand(
    ST_MakeEmptyRaster(width => 2, height => 2,
      upperleftx => 0, upperlefty => 2,
      scalex => 1.0, scaley => -1.0,
      skewx => 0, skewy => 0, srid => 4326),
    index => 1, pixeltype => '16BSI',
    initialvalue => 0,
    nodataval => -999),
  1,1,1,
  newvalueset =>ARRAY[ARRAY[10.0::float8, 50.0::float8], ARRAY[40.0::float8, 20.0::float8]]) AS rast
)
SELECT
'#2116',
round(ST_Value(rast, 1, 'SRID=4326;POINT(1.0 1.0)'::geometry, resample => 'nearest-ul')) as nearest_ul,
round(ST_Value(rast, 1, 'SRID=4326;POINT(1.0 1.0)'::geometry, resample => 'nearest-ur')) as nearest_ur,
round(ST_Value(rast, 1, 'SRID=4326;POINT(1.0 1.0)'::geometry, resample => 'nearest-ll')) as nearest_ll,
round(ST_Value(rast, 1, 'SRID=4326;POINT(1.0 1.0)'::geometry, resample => 'nearest-lr')) as nearest_lr,
round(ST_Value(rast, 1, 'SRID=4326;POINT(1.0 1.0)'::geometry, resample => 'nearest')) as nearest_default
FROM r;

WITH r AS (
SELECT
ST_SetValues(
  ST_AddBand(
    ST_MakeEmptyRaster(width => 2, height => 2,
      upperleftx => 0, upperlefty => 2,
      scalex => 1.0, scaley => -1.0,
      skewx => 0, skewy => 0, srid => 4326),
    index => 1, pixeltype => '16BSI',
    initialvalue => 0,
    nodataval => -999),
  1,1,1,
  newvalueset =>ARRAY[ARRAY[10.0::float8, 50.0::float8], ARRAY[40.0::float8, 20.0::float8]]) AS rast
)
SELECT
'#2116.snap',
round(ST_Value(rast, 1, 'SRID=4326;POINT(1.0000000000000004 0.9999999999999996)'::geometry, resample => 'nearest-ul')) as nearest_ul,
round(ST_Value(rast, 1, 'SRID=4326;POINT(0.9999999999999997 1.0000000000000002)'::geometry, resample => 'nearest-lr')) as nearest_lr
FROM r;

WITH r AS (
SELECT ST_AddBand(ST_MakeEmptyRaster(1, 1, 0, 1, 1, -1, 0, 0, 4326), '16BSI'::text, 1, -999) AS rast
)
SELECT ST_Value(rast, 1, 'SRID=4326;POINT(0.5 0.5)'::geometry, resample => 'nearest-foo') FROM r;

WITH r AS (
SELECT ST_AddBand(ST_MakeEmptyRaster(1, 1, 0, 1, 1, -1, 0, 0, 4326), '16BSI'::text, 1, -999) AS rast
)
SELECT ST_Value(rast, 1, 'SRID=4326;POINT(0.5 0.5)'::geometry, resample => 'bilinearXYZ') FROM r;
