#!/usr/bin/env python
# -*- coding: utf-8 -*-
###############################################################################
# $Id $
#
# Project:  GDAL/OGR Test Suite
# Purpose:  Test KEA driver
# Author:   Even Rouault, <even dot rouault at spatialys dot com>
#
###############################################################################
# Copyright (c) 2014, Even Rouault <even dot rouault at spatialys dot com>
#
# Permission is hereby granted, free of charge, to any person obtaining a
# copy of this software and associated documentation files (the "Software"),
# to deal in the Software without restriction, including without limitation
# the rights to use, copy, modify, merge, publish, distribute, sublicense,
# and/or sell copies of the Software, and to permit persons to whom the
# Software is furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included
# in all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
# DEALINGS IN THE SOFTWARE.
###############################################################################

import sys
from osgeo import gdal

sys.path.append('../pymod')

import gdaltest

###############################################################################


def kea_init():
    try:
        gdaltest.kea_driver = gdal.GetDriverByName('KEA')
    except:
        gdaltest.kea_driver = None

    return 'success'

###############################################################################
# Test copying a reference sample with CreateCopy()


def kea_1():
    if gdaltest.kea_driver is None:
        return 'skip'

    tst = gdaltest.GDALTest('KEA', 'byte.tif', 1, 4672, options=['IMAGEBLOCKSIZE=15', 'THEMATIC=YES'])
    return tst.testCreateCopy(check_srs=True, check_gt=1)

###############################################################################
# Test CreateCopy() for various data types


def kea_2():
    if gdaltest.kea_driver is None:
        return 'skip'

    src_files = ['byte.tif',
                 'int16.tif',
                 '../../gcore/data/uint16.tif',
                 '../../gcore/data/int32.tif',
                 '../../gcore/data/uint32.tif',
                 '../../gcore/data/float32.tif',
                 '../../gcore/data/float64.tif']

    for src_file in src_files:
        tst = gdaltest.GDALTest('KEA', src_file, 1, 4672)
        ret = tst.testCreateCopy(check_minmax=1)
        if ret != 'success':
            return ret

    return 'success'

###############################################################################
# Test Create() for various data types


def kea_3():
    if gdaltest.kea_driver is None:
        return 'skip'

    src_files = ['byte.tif',
                 'int16.tif',
                 '../../gcore/data/uint16.tif',
                 '../../gcore/data/int32.tif',
                 '../../gcore/data/uint32.tif',
                 '../../gcore/data/float32.tif',
                 '../../gcore/data/float64.tif']

    for src_file in src_files:
        tst = gdaltest.GDALTest('KEA', src_file, 1, 4672)
        ret = tst.testCreate(out_bands=1, check_minmax=1)
        if ret != 'success':
            return ret

    return 'success'

###############################################################################
# Test Create()/CreateCopy() error cases or limit cases


def kea_4():
    if gdaltest.kea_driver is None:
        return 'skip'

    gdal.PushErrorHandler('CPLQuietErrorHandler')
    ds = gdaltest.kea_driver.Create("/non_existing_path/non_existing_path", 1, 1)
    gdal.PopErrorHandler()
    if ds is not None:
        gdaltest.post_reason('fail')
        return 'fail'

    src_ds = gdaltest.kea_driver.Create('tmp/src.kea', 1, 1, 0)
    if src_ds is None:
        gdaltest.post_reason('fail')
        return 'fail'
    ds = gdaltest.kea_driver.CreateCopy("tmp/out.kea", src_ds)
    if ds is None:
        gdaltest.post_reason('fail')
        return 'fail'
    if ds.RasterCount != 0:
        gdaltest.post_reason('fail')
        return 'fail'
    src_ds = None
    ds = None

    # Test updating a read-only file
    ds = gdaltest.kea_driver.Create('tmp/out.kea', 1, 1)
    ds.GetRasterBand(1).Fill(255)
    ds = None
    ds = gdal.Open('tmp/out.kea')

    gdal.PushErrorHandler('CPLQuietErrorHandler')
    ret = ds.SetProjection('a')
    gdal.PopErrorHandler()
    if ret == 0:
        gdaltest.post_reason('fail')
        return 'fail'

    gdal.PushErrorHandler('CPLQuietErrorHandler')
    ret = ds.SetGeoTransform([1, 2, 3, 4, 5, 6])
    gdal.PopErrorHandler()
    if ret == 0:
        gdaltest.post_reason('fail')
        return 'fail'

    # Disabled for now since some of them cause memory leaks or
    # crash in the HDF5 library finalizer
    if False:
        gdal.PushErrorHandler('CPLQuietErrorHandler')
        ret = ds.SetMetadataItem('foo', 'bar')
        gdal.PopErrorHandler()
        if ret == 0:
            gdaltest.post_reason('fail')
            return 'fail'

        gdal.PushErrorHandler('CPLQuietErrorHandler')
        ret = ds.SetMetadata({'foo': 'bar'})
        gdal.PopErrorHandler()
        if ret == 0:
            gdaltest.post_reason('fail')
            return 'fail'

        gdal.PushErrorHandler('CPLQuietErrorHandler')
        ret = ds.GetRasterBand(1).SetMetadataItem('foo', 'bar')
        gdal.PopErrorHandler()
        if ret == 0:
            gdaltest.post_reason('fail')
            return 'fail'

        gdal.PushErrorHandler('CPLQuietErrorHandler')
        ret = ds.GetRasterBand(1).SetMetadata({'foo': 'bar'})
        gdal.PopErrorHandler()
        if ret == 0:
            gdaltest.post_reason('fail')
            return 'fail'

        gdal.PushErrorHandler('CPLQuietErrorHandler')
        ret = ds.SetGCPs([], "")
        gdal.PopErrorHandler()
        if ret == 0:
            gdaltest.post_reason('fail')
            return 'fail'

    gdal.PushErrorHandler('CPLQuietErrorHandler')
    ret = ds.AddBand(gdal.GDT_Byte)
    gdal.PopErrorHandler()
    if ret == 0:
        gdaltest.post_reason('fail')
        return 'fail'

    ds.GetRasterBand(1).WriteRaster(0, 0, 1, 1, '\0')
    gdal.ErrorReset()
    gdal.PushErrorHandler('CPLQuietErrorHandler')
    ds.FlushCache()
    gdal.PopErrorHandler()
    if ds.GetRasterBand(1).Checksum() != 3:
        gdaltest.post_reason('fail')
        return 'fail'

    ds = None

    gdaltest.kea_driver.Delete('tmp/src.kea')
    gdaltest.kea_driver.Delete('tmp/out.kea')

    return 'success'

###############################################################################
# Test Create() creation options


def kea_5():
    if gdaltest.kea_driver is None:
        return 'skip'

    options = ['IMAGEBLOCKSIZE=15', 'ATTBLOCKSIZE=100', 'MDC_NELMTS=10',
               'RDCC_NELMTS=256', 'RDCC_NBYTES=500000', 'RDCC_W0=0.5',
               'SIEVE_BUF=32768', 'META_BLOCKSIZE=1024', 'DEFLATE=9', 'THEMATIC=YES']
    ds = gdaltest.kea_driver.Create("tmp/out.kea", 100, 100, 3, options=options)
    ds = None
    ds = gdal.Open('tmp/out.kea')
    if ds.GetRasterBand(1).GetBlockSize() != [15, 15]:
        gdaltest.post_reason('fail')
        print(ds.GetRasterBand(1).GetBlockSize())
        return 'fail'
    if ds.GetRasterBand(1).GetMetadataItem('LAYER_TYPE') != 'thematic':
        gdaltest.post_reason('fail')
        print(ds.GetRasterBand(1).GetMetadata())
        return 'fail'
    if ds.GetRasterBand(1).Checksum() != 0:
        gdaltest.post_reason('fail')
        print(ds.GetRasterBand(1).Checksum())
        return 'fail'
    if ds.GetGeoTransform() != (0, 1, 0, 0, 0, -1):
        gdaltest.post_reason('fail')
        print(ds.GetGeoTransform())
        return 'fail'
    if ds.GetProjectionRef() != '':
        gdaltest.post_reason('fail')
        print(ds.GetProjectionRef())
        return 'fail'
    ds = None
    gdaltest.kea_driver.Delete('tmp/out.kea')

    return 'success'

###############################################################################
# Test metadata


def kea_6():
    if gdaltest.kea_driver is None:
        return 'skip'

    ds = gdaltest.kea_driver.Create("tmp/out.kea", 1, 1, 5)
    ds.SetMetadata({'foo': 'bar'})
    ds.SetMetadataItem('bar', 'baw')
    ds.GetRasterBand(1).SetMetadata({'bar': 'baz'})
    ds.GetRasterBand(1).SetDescription('desc')
    ds.GetRasterBand(2).SetMetadata({'LAYER_TYPE': 'any_string_that_is_not_athematic_is_thematic'})
    ds.GetRasterBand(3).SetMetadata({'LAYER_TYPE': 'athematic'})
    ds.GetRasterBand(4).SetMetadataItem('LAYER_TYPE', 'thematic')
    ds.GetRasterBand(5).SetMetadataItem('LAYER_TYPE', 'athematic')
    if ds.SetMetadata({'foo': 'bar'}, 'other_domain') == 0:
        gdaltest.post_reason('fail')
        return 'fail'
    if ds.SetMetadataItem('foo', 'bar', 'other_domain') == 0:
        gdaltest.post_reason('fail')
        return 'fail'
    if ds.GetRasterBand(1).SetMetadata({'foo': 'bar'}, 'other_domain') == 0:
        gdaltest.post_reason('fail')
        return 'fail'
    if ds.GetRasterBand(1).SetMetadataItem('foo', 'bar', 'other_domain') == 0:
        gdaltest.post_reason('fail')
        return 'fail'
    ds = None

    ds = gdal.Open('tmp/out.kea')
    if ds.GetMetadata('other_domain') != {}:
        gdaltest.post_reason('fail')
        print(ds.GetMetadata('other_domain'))
        return 'fail'
    if ds.GetMetadataItem('item', 'other_domain') is not None:
        gdaltest.post_reason('fail')
        return 'fail'
    if ds.GetRasterBand(1).GetMetadata('other_domain') != {}:
        gdaltest.post_reason('fail')
        return 'fail'
    if ds.GetRasterBand(1).GetMetadataItem('item', 'other_domain') is not None:
        gdaltest.post_reason('fail')
        return 'fail'
    md = ds.GetMetadata()
    if md['foo'] != 'bar':
        gdaltest.post_reason('fail')
        print(md)
        return 'fail'
    if ds.GetMetadataItem('foo') != 'bar':
        gdaltest.post_reason('fail')
        print(ds.GetMetadataItem('foo'))
        return 'fail'
    if ds.GetMetadataItem('bar') != 'baw':
        gdaltest.post_reason('fail')
        print(ds.GetMetadataItem('bar'))
        return 'fail'
    if ds.GetRasterBand(1).GetDescription() != 'desc':
        gdaltest.post_reason('fail')
        return 'fail'
    md = ds.GetRasterBand(1).GetMetadata()
    if md['bar'] != 'baz':
        gdaltest.post_reason('fail')
        print(md)
        return 'fail'
    if ds.GetRasterBand(1).GetMetadataItem('bar') != 'baz':
        gdaltest.post_reason('fail')
        print(ds.GetRasterBand(1).GetMetadataItem('bar'))
        return 'fail'
    if ds.GetRasterBand(2).GetMetadataItem('LAYER_TYPE') != 'thematic':
        gdaltest.post_reason('fail')
        print(ds.GetRasterBand(2).GetMetadataItem('LAYER_TYPE'))
        return 'fail'
    if ds.GetRasterBand(3).GetMetadataItem('LAYER_TYPE') != 'athematic':
        gdaltest.post_reason('fail')
        print(ds.GetRasterBand(3).GetMetadataItem('LAYER_TYPE'))
        return 'fail'
    if ds.GetRasterBand(4).GetMetadataItem('LAYER_TYPE') != 'thematic':
        gdaltest.post_reason('fail')
        print(ds.GetRasterBand(4).GetMetadataItem('LAYER_TYPE'))
        return 'fail'
    if ds.GetRasterBand(5).GetMetadataItem('LAYER_TYPE') != 'athematic':
        gdaltest.post_reason('fail')
        print(ds.GetRasterBand(5).GetMetadataItem('LAYER_TYPE'))
        return 'fail'
    out2_ds = gdaltest.kea_driver.CreateCopy('tmp/out2.kea', ds)
    ds = None

    if out2_ds.GetMetadataItem('foo') != 'bar':
        gdaltest.post_reason('fail')
        print(out2_ds.GetMetadataItem('foo'))
        return 'fail'
    if out2_ds.GetRasterBand(1).GetMetadataItem('bar') != 'baz':
        gdaltest.post_reason('fail')
        print(out2_ds.GetRasterBand(1).GetMetadataItem('bar'))
        return 'fail'

    out2_ds = None

    gdaltest.kea_driver.Delete('tmp/out.kea')
    gdaltest.kea_driver.Delete('tmp/out2.kea')

    return 'success'

###############################################################################
# Test georef


def kea_7():
    if gdaltest.kea_driver is None:
        return 'skip'

    # Geotransform
    ds = gdaltest.kea_driver.Create("tmp/out.kea", 1, 1)
    if ds.GetGCPCount() != 0:
        gdaltest.post_reason('fail')
        return 'fail'
    if ds.SetGeoTransform([1, 2, 3, 4, 5, 6]) != 0:
        gdaltest.post_reason('fail')
        return 'fail'
    if ds.SetProjection('foo') != 0:
        gdaltest.post_reason('fail')
        return 'fail'
    ds = None

    ds = gdal.Open('tmp/out.kea')
    out2_ds = gdaltest.kea_driver.CreateCopy('tmp/out2.kea', ds)
    ds = None
    if out2_ds.GetGCPCount() != 0:
        gdaltest.post_reason('fail')
        return 'fail'
    if out2_ds.GetGeoTransform() != (1, 2, 3, 4, 5, 6):
        gdaltest.post_reason('fail')
        print(out2_ds.GetGeoTransform())
        return 'fail'
    if out2_ds.GetProjectionRef() != 'foo':
        gdaltest.post_reason('fail')
        print(out2_ds.GetProjectionRef())
        return 'fail'
    out2_ds = None

    gdaltest.kea_driver.Delete('tmp/out.kea')
    gdaltest.kea_driver.Delete('tmp/out2.kea')

    # GCP
    ds = gdaltest.kea_driver.Create("tmp/out.kea", 1, 1)
    gcp1 = gdal.GCP(0, 1, 2, 3, 4)
    gcp1.Id = "id"
    gcp1.Info = "info"
    gcp2 = gdal.GCP(0, 1, 2, 3, 4)
    gcps = [gcp1, gcp2]
    ds.SetGCPs(gcps, "foo")
    ds = None

    ds = gdal.Open('tmp/out.kea')
    out2_ds = gdaltest.kea_driver.CreateCopy('tmp/out2.kea', ds)
    ds = None

    if out2_ds.GetGCPCount() != 2:
        gdaltest.post_reason('fail')
        return 'fail'
    if out2_ds.GetGCPProjection() != 'foo':
        gdaltest.post_reason('fail')
        return 'fail'
    got_gcps = out2_ds.GetGCPs()
    for i in range(2):
        if got_gcps[i].GCPX != gcps[i].GCPX or got_gcps[i].GCPY != gcps[i].GCPY or \
           got_gcps[i].GCPZ != gcps[i].GCPZ or got_gcps[i].GCPPixel != gcps[i].GCPPixel or \
           got_gcps[i].GCPLine != gcps[i].GCPLine or got_gcps[i].Id != gcps[i].Id or \
           got_gcps[i].Info != gcps[i].Info:
            print(i)
            print(got_gcps[i])
            gdaltest.post_reason('fail')
            return 'fail'
    out2_ds = None

    gdaltest.kea_driver.Delete('tmp/out.kea')
    gdaltest.kea_driver.Delete('tmp/out2.kea')

    return 'success'

###############################################################################
# Test colortable


def kea_8():
    if gdaltest.kea_driver is None:
        return 'skip'

    for i in range(2):
        ds = gdaltest.kea_driver.Create("tmp/out.kea", 1, 1)
        if ds.GetRasterBand(1).GetColorTable() is not None:
            gdaltest.post_reason('fail')
            return 'fail'
        if ds.GetRasterBand(1).SetColorTable(None) == 0:  # not allowed by the driver
            gdaltest.post_reason('fail')
            return 'fail'
        ct = gdal.ColorTable()
        ct.SetColorEntry(0, (0, 255, 0, 255))
        ct.SetColorEntry(1, (255, 0, 255, 255))
        ct.SetColorEntry(2, (0, 0, 255, 255))
        if ds.GetRasterBand(1).SetColorTable(ct) != 0:
            gdaltest.post_reason('fail')
            return 'fail'
        if i == 1:
            # And again
            if ds.GetRasterBand(1).SetColorTable(ct) != 0:
                gdaltest.post_reason('fail')
                return 'fail'
        ds = None

        ds = gdal.Open('tmp/out.kea')
        out2_ds = gdaltest.kea_driver.CreateCopy('tmp/out2.kea', ds)
        ds = None
        got_ct = out2_ds.GetRasterBand(1).GetColorTable()
        if got_ct.GetCount() != 3:
            gdaltest.post_reason('Got wrong color table entry count.')
            return 'fail'
        if got_ct.GetColorEntry(1) != (255, 0, 255, 255):
            gdaltest.post_reason('Got wrong color table entry.')
            return 'fail'

        out2_ds = None

        gdaltest.kea_driver.Delete('tmp/out.kea')
        gdaltest.kea_driver.Delete('tmp/out2.kea')

    return 'success'

###############################################################################
# Test color interpretation


def kea_9():
    if gdaltest.kea_driver is None:
        return 'skip'

    ds = gdaltest.kea_driver.Create("tmp/out.kea", 1, 1, gdal.GCI_YCbCr_CrBand - gdal.GCI_GrayIndex + 1)
    if ds.GetRasterBand(1).GetColorInterpretation() != gdal.GCI_GrayIndex:
        gdaltest.post_reason('fail')
        return 'fail'
    for i in range(gdal.GCI_GrayIndex, gdal.GCI_YCbCr_CrBand + 1):
        ds.GetRasterBand(i).SetColorInterpretation(i)
    ds = None

    ds = gdal.Open('tmp/out.kea')
    out2_ds = gdaltest.kea_driver.CreateCopy('tmp/out2.kea', ds)
    ds = None
    for i in range(gdal.GCI_GrayIndex, gdal.GCI_YCbCr_CrBand + 1):
        if out2_ds.GetRasterBand(i).GetColorInterpretation() != i:
            gdaltest.post_reason('Got wrong color interpretation.')
            print(i)
            print(out2_ds.GetRasterBand(i).GetColorInterpretation())
            return 'fail'

    out2_ds = None

    gdaltest.kea_driver.Delete('tmp/out.kea')
    gdaltest.kea_driver.Delete('tmp/out2.kea')

    return 'success'

###############################################################################
# Test nodata


def kea_10():
    if gdaltest.kea_driver is None:
        return 'skip'

    for (dt, nd, expected_nd) in [(gdal.GDT_Byte, 0, 0),
                                  (gdal.GDT_Byte, 1.1, 1.0),
                                  (gdal.GDT_Byte, 255, 255),
                                  (gdal.GDT_Byte, -1, None),
                                  (gdal.GDT_Byte, 256, None),
                                  (gdal.GDT_UInt16, 0, 0),
                                  (gdal.GDT_UInt16, 65535, 65535),
                                  (gdal.GDT_UInt16, -1, None),
                                  (gdal.GDT_UInt16, 65536, None),
                                  (gdal.GDT_Int16, -32768, -32768),
                                  (gdal.GDT_Int16, 32767, 32767),
                                  (gdal.GDT_Int16, -32769, None),
                                  (gdal.GDT_Int16, 32768, None),
                                  (gdal.GDT_UInt32, 0, 0),
                                  (gdal.GDT_UInt32, 0xFFFFFFFF, 0xFFFFFFFF),
                                  (gdal.GDT_UInt32, -1, None),
                                  (gdal.GDT_UInt32, 0xFFFFFFFF + 1, None),
                                  (gdal.GDT_Int32, -2147483648, -2147483648),
                                  (gdal.GDT_Int32, 2147483647, 2147483647),
                                  (gdal.GDT_Int32, -2147483649, None),
                                  (gdal.GDT_Int32, 2147483648, None),
                                  (gdal.GDT_Float32, 0.5, 0.5),
                                  ]:
        ds = gdaltest.kea_driver.Create("tmp/out.kea", 1, 1, 1, dt)
        if ds.GetRasterBand(1).GetNoDataValue() is not None:
            gdaltest.post_reason('fail')
            return 'fail'
        ds.GetRasterBand(1).SetNoDataValue(nd)
        if ds.GetRasterBand(1).GetNoDataValue() != expected_nd:
            gdaltest.post_reason('Got wrong nodata.')
            print(dt)
            print(ds.GetRasterBand(1).GetNoDataValue())
            return 'fail'
        ds = None

        ds = gdal.Open('tmp/out.kea')
        out2_ds = gdaltest.kea_driver.CreateCopy('tmp/out2.kea', ds)
        ds = None
        if out2_ds.GetRasterBand(1).GetNoDataValue() != expected_nd:
            gdaltest.post_reason('Got wrong nodata.')
            print(dt)
            print(out2_ds.GetRasterBand(1).GetNoDataValue())
            return 'fail'
        out2_ds.GetRasterBand(1).DeleteNoDataValue()
        out2_ds = None

        ds = gdal.Open('tmp/out2.kea')
        if ds.GetRasterBand(1).GetNoDataValue() is not None:
            gdaltest.post_reason('fail')
            return 'fail'
        ds = None

        gdaltest.kea_driver.Delete('tmp/out.kea')
        gdaltest.kea_driver.Delete('tmp/out2.kea')

    return 'success'

###############################################################################
# Test AddBand


def kea_11():
    if gdaltest.kea_driver is None:
        return 'skip'

    ds = gdaltest.kea_driver.Create("tmp/out.kea", 1, 1, 1, gdal.GDT_Byte)
    ds = None

    ds = gdal.Open('tmp/out.kea', gdal.GA_Update)
    if ds.AddBand(gdal.GDT_Byte) != 0:
        gdaltest.post_reason('fail')
        return 'fail'
    if ds.AddBand(gdal.GDT_Int16, options=['DEFLATE=9']) != 0:
        gdaltest.post_reason('fail')
        return 'fail'
    ds = None

    ds = gdal.Open('tmp/out.kea')
    if ds.RasterCount != 3:
        gdaltest.post_reason('fail')
        return 'fail'
    if ds.GetRasterBand(2).DataType != gdal.GDT_Byte:
        gdaltest.post_reason('fail')
        return 'fail'
    if ds.GetRasterBand(3).DataType != gdal.GDT_Int16:
        gdaltest.post_reason('fail')
        return 'fail'
    ds = None

    gdaltest.kea_driver.Delete('tmp/out.kea')

    return 'success'

###############################################################################
# Test RAT


def kea_12():
    if gdaltest.kea_driver is None:
        return 'skip'

    ds = gdaltest.kea_driver.Create("tmp/out.kea", 1, 1, 1, gdal.GDT_Byte)
    if ds.GetRasterBand(1).GetDefaultRAT().GetColumnCount() != 0:
        gdaltest.post_reason('fail')
        return 'fail'
    if ds.GetRasterBand(1).SetDefaultRAT(None) == 0:  # not allowed by the driver
        gdaltest.post_reason('fail')
        return 'fail'
    rat = ds.GetRasterBand(1).GetDefaultRAT()
    rat.CreateColumn('col_real_generic', gdal.GFT_Real, gdal.GFU_Generic)
    if ds.GetRasterBand(1).SetDefaultRAT(rat) != 0:
        gdaltest.post_reason('fail')
        return 'fail'
    rat = ds.GetRasterBand(1).GetDefaultRAT()
    rat.CreateColumn('col_integer_pixelcount', gdal.GFT_Real, gdal.GFU_PixelCount)
    rat.CreateColumn('col_string_name', gdal.GFT_String, gdal.GFU_Name)
    rat.CreateColumn('col_integer_red', gdal.GFT_Integer, gdal.GFU_Red)
    rat.CreateColumn('col_integer_green', gdal.GFT_Integer, gdal.GFU_Green)
    rat.CreateColumn('col_integer_blue', gdal.GFT_Integer, gdal.GFU_Blue)
    rat.CreateColumn('col_integer_alpha', gdal.GFT_Integer, gdal.GFU_Alpha)
    rat.SetRowCount(1)

    rat.SetValueAsString(0, 0, "1.23")
    rat.SetValueAsInt(0, 0, 1)
    rat.SetValueAsDouble(0, 0, 1.23)

    rat.SetValueAsInt(0, 2, 0)
    rat.SetValueAsDouble(0, 2, 0)
    rat.SetValueAsString(0, 2, 'foo')

    rat.SetValueAsString(0, 3, "123")
    rat.SetValueAsDouble(0, 3, 123)
    rat.SetValueAsInt(0, 3, 123)

    cloned_rat = rat.Clone()
    if ds.GetRasterBand(1).SetDefaultRAT(rat) != 0:
        gdaltest.post_reason('fail')
        return 'fail'
    ds = None

    ds = gdal.Open('tmp/out.kea')
    out2_ds = gdaltest.kea_driver.CreateCopy('tmp/out2.kea', ds)
    rat = out2_ds.GetRasterBand(1).GetDefaultRAT()

    for i in range(7):
        if rat.GetColOfUsage(rat.GetUsageOfCol(i)) != i:
            gdaltest.post_reason('fail')
            print(i)
            print(rat.GetColOfUsage(rat.GetUsageOfCol(i)))
            return 'fail'

    if cloned_rat.GetNameOfCol(0) != 'col_real_generic':
        gdaltest.post_reason('fail')
        return 'fail'
    if cloned_rat.GetTypeOfCol(0) != gdal.GFT_Real:
        gdaltest.post_reason('fail')
        return 'fail'
    if cloned_rat.GetUsageOfCol(0) != gdal.GFU_Generic:
        gdaltest.post_reason('fail')
        return 'fail'
    if cloned_rat.GetUsageOfCol(1) != gdal.GFU_PixelCount:
        gdaltest.post_reason('fail')
        return 'fail'
    if cloned_rat.GetTypeOfCol(2) != gdal.GFT_String:
        gdaltest.post_reason('fail')
        return 'fail'
    if cloned_rat.GetTypeOfCol(3) != gdal.GFT_Integer:
        gdaltest.post_reason('fail')
        return 'fail'

    if rat.GetColumnCount() != cloned_rat.GetColumnCount():
        gdaltest.post_reason('fail')
        return 'fail'
    if rat.GetRowCount() != cloned_rat.GetRowCount():
        gdaltest.post_reason('fail')
        return 'fail'
    for i in range(rat.GetColumnCount()):
        if rat.GetNameOfCol(i) != cloned_rat.GetNameOfCol(i):
            gdaltest.post_reason('fail')
            return 'fail'
        if rat.GetTypeOfCol(i) != cloned_rat.GetTypeOfCol(i):
            gdaltest.post_reason('fail')
            return 'fail'
        if rat.GetUsageOfCol(i) != cloned_rat.GetUsageOfCol(i):
            gdaltest.post_reason('fail')
            print(i)
            print(rat.GetUsageOfCol(i))
            print(cloned_rat.GetUsageOfCol(i))
            return 'fail'

    gdal.PushErrorHandler('CPLQuietErrorHandler')

    rat.GetNameOfCol(-1)
    rat.GetTypeOfCol(-1)
    rat.GetUsageOfCol(-1)

    rat.GetNameOfCol(rat.GetColumnCount())
    rat.GetTypeOfCol(rat.GetColumnCount())
    rat.GetUsageOfCol(rat.GetColumnCount())

    rat.GetValueAsDouble(-1, 0)
    rat.GetValueAsInt(-1, 0)
    rat.GetValueAsString(-1, 0)

    rat.GetValueAsDouble(rat.GetColumnCount(), 0)
    rat.GetValueAsInt(rat.GetColumnCount(), 0)
    rat.GetValueAsString(rat.GetColumnCount(), 0)

    rat.GetValueAsDouble(0, -1)
    rat.GetValueAsInt(0, -1)
    rat.GetValueAsString(0, -1)

    rat.GetValueAsDouble(0, rat.GetRowCount())
    rat.GetValueAsInt(0, rat.GetRowCount())
    rat.GetValueAsString(0, rat.GetRowCount())

    gdal.PopErrorHandler()

    if rat.GetValueAsDouble(0, 0) != 1.23:
        gdaltest.post_reason('fail')
        return 'fail'
    if rat.GetValueAsInt(0, 0) != 1:
        gdaltest.post_reason('fail')
        return 'fail'
    if rat.GetValueAsString(0, 0) != '1.23':
        gdaltest.post_reason('fail')
        print(rat.GetValueAsString(0, 0))
        return 'fail'

    if rat.GetValueAsInt(0, 3) != 123:
        gdaltest.post_reason('fail')
        return 'fail'
    if rat.GetValueAsDouble(0, 3) != 123:
        gdaltest.post_reason('fail')
        return 'fail'
    if rat.GetValueAsString(0, 3) != '123':
        gdaltest.post_reason('fail')
        return 'fail'

    if rat.GetValueAsString(0, 2) != 'foo':
        gdaltest.post_reason('fail')
        return 'fail'
    if rat.GetValueAsInt(0, 2) != 0:
        gdaltest.post_reason('fail')
        return 'fail'
    if rat.GetValueAsDouble(0, 2) != 0:
        gdaltest.post_reason('fail')
        return 'fail'

    ds = None
    out2_ds = None

    gdaltest.kea_driver.Delete('tmp/out.kea')
    gdaltest.kea_driver.Delete('tmp/out2.kea')

    return 'success'

###############################################################################
# Test overviews


def kea_13():
    if gdaltest.kea_driver is None:
        return 'skip'

    src_ds = gdal.Open('data/byte.tif')
    ds = gdaltest.kea_driver.CreateCopy("tmp/out.kea", src_ds)
    src_ds = None
    ds.BuildOverviews('NEAR', [2])
    ds = None
    ds = gdal.Open('tmp/out.kea')
    out2_ds = gdaltest.kea_driver.CreateCopy('tmp/out2.kea', ds)  # yes CreateCopy() of KEA copies overviews
    if out2_ds.GetRasterBand(1).GetOverviewCount() != 1:
        gdaltest.post_reason('fail')
        return 'fail'
    if out2_ds.GetRasterBand(1).GetOverview(0).Checksum() != 1087:
        gdaltest.post_reason('fail')
        return 'fail'
    if out2_ds.GetRasterBand(1).GetOverview(0).GetDefaultRAT() is not None:
        gdaltest.post_reason('fail')
        return 'fail'
    if out2_ds.GetRasterBand(1).GetOverview(0).SetDefaultRAT(None) == 0:
        gdaltest.post_reason('fail')
        return 'fail'
    if out2_ds.GetRasterBand(1).GetOverview(-1) is not None:
        gdaltest.post_reason('fail')
        return 'fail'
    if out2_ds.GetRasterBand(1).GetOverview(1) is not None:
        gdaltest.post_reason('fail')
        return 'fail'
    out2_ds = None
    ds = None

    gdaltest.kea_driver.Delete('tmp/out.kea')
    gdaltest.kea_driver.Delete('tmp/out2.kea')

    return 'success'

###############################################################################
# Test mask bands


def kea_14():
    if gdaltest.kea_driver is None:
        return 'skip'

    ds = gdaltest.kea_driver.Create("tmp/out.kea", 1, 1, 1, gdal.GDT_Byte)
    if ds.GetRasterBand(1).GetMaskFlags() != gdal.GMF_ALL_VALID:
        gdaltest.post_reason('fail')
        return 'fail'
    if ds.GetRasterBand(1).GetMaskBand().Checksum() != 3:
        print(ds.GetRasterBand(1).GetMaskBand().Checksum())
        gdaltest.post_reason('fail')
        return 'fail'
    ds.GetRasterBand(1).CreateMaskBand(0)
    if ds.GetRasterBand(1).GetMaskFlags() != 0:
        gdaltest.post_reason('fail')
        return 'fail'
    if ds.GetRasterBand(1).GetMaskBand().Checksum() != 3:
        print(ds.GetRasterBand(1).GetMaskBand().Checksum())
        gdaltest.post_reason('fail')
        return 'fail'
    ds.GetRasterBand(1).GetMaskBand().Fill(0)
    if ds.GetRasterBand(1).GetMaskBand().Checksum() != 0:
        print(ds.GetRasterBand(1).GetMaskBand().Checksum())
        gdaltest.post_reason('fail')
        return 'fail'
    ds = None

    ds = gdal.Open('tmp/out.kea')
    out2_ds = gdaltest.kea_driver.CreateCopy('tmp/out2.kea', ds)  # yes CreateCopy() of KEA copies overviews
    if out2_ds.GetRasterBand(1).GetMaskFlags() != 0:
        gdaltest.post_reason('fail')
        return 'fail'
    if out2_ds.GetRasterBand(1).GetMaskBand().Checksum() != 0:
        print(out2_ds.GetRasterBand(1).GetMaskBand().Checksum())
        gdaltest.post_reason('fail')
        return 'fail'
    out2_ds = None
    ds = None

    gdaltest.kea_driver.Delete('tmp/out.kea')
    gdaltest.kea_driver.Delete('tmp/out2.kea')

    return 'success'


gdaltest_list = [
    kea_init,
    kea_1,
    kea_2,
    kea_3,
    kea_4,
    kea_5,
    kea_6,
    kea_7,
    kea_8,
    kea_9,
    kea_10,
    kea_11,
    kea_12,
    kea_13,
    kea_14
]

if __name__ == '__main__':

    gdaltest.setup_run('kea')

    gdaltest.run_tests(gdaltest_list)

    gdaltest.summarize()
