# -*- coding:utf-8 -*-

# This file is part of BlenderGIS

#  ***** GPL LICENSE BLOCK *****
#
#  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 3 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, see <http://www.gnu.org/licenses/>.
#  All rights reserved.
#  ***** GPL LICENSE BLOCK *****


import os
import numpy as np
from .npimg import NpImage


from ..checkdeps import HAS_GDAL, HAS_PIL, HAS_IMGIO

if HAS_GDAL:
	from osgeo import gdal


class BigTiffWriter():
	'''
	This class is designed to write a bigtif with jpeg compression
	writing a large tiff file without trigger a memory overflow is possible with the help of GDAL library
	jpeg compression allows to maintain a reasonable file size
	transparency or nodata are stored in an internal tiff mask because it's not possible to have an alpha channel when using jpg compression
	'''


	def __del__(self):
		# properly close gdal dataset
		self.ds = None


	def __init__(self, path, w, h, georef, geoTiffOptions={'TFW':'YES', 'TILED':'YES', 'BIGTIFF':'YES', 'COMPRESS':'JPEG', 'JPEG_QUALITY':80, 'PHOTOMETRIC':'YCBCR'}):
		'''
		path = fule system path for the ouput tiff
		w, h = width and height in pixels
		georef : a Georef object used to set georeferencing informations, optional
		geoTiffOptions : GDAL create option for tiff format
		'''

		if not HAS_GDAL:
			raise ImportError("GDAL interface unavailable")


		#control path validity

		self.w = w
		self.h = h
		self.size = (w, h)

		self.path = path
		self.georef = georef

		if geoTiffOptions.get('COMPRESS', None) == 'JPEG':
			#JPEG in tiff cannot have an alpha band, workaround is to use internal tiff mask
			self.useMask = True
			gdal.SetConfigOption('GDAL_TIFF_INTERNAL_MASK', 'YES')
			n = 3 #RGB
		else:
			self.useMask = False
			n = 4 #RGBA
		self.nbBands = n

		options = [str(k) + '=' + str(v) for k, v in geoTiffOptions.items()]

		driver = gdal.GetDriverByName("GTiff")
		gdtype = gdal.GDT_Byte #GDT_UInt16, GDT_Int16, GDT_UInt32, GDT_Int32
		self.dtype = 'uint8'

		self.ds = driver.Create(path, w, h, n, gdtype, options)
		if self.useMask:
			self.ds.CreateMaskBand(gdal.GMF_PER_DATASET)#The mask band is shared between all bands on the dataset
			self.mask = self.ds.GetRasterBand(1).GetMaskBand()
			self.mask.Fill(255)
		elif n == 4:
			self.ds.GetRasterBand(4).Fill(255)

		#Write georef infos
		self.ds.SetGeoTransform(self.georef.toGDAL())
		if self.georef.crs is not None:
			self.ds.SetProjection(self.georef.crs.getOgrSpatialRef().ExportToWkt())
		#self.georef.toWorldFile(os.path.splitext(path)[0] + '.tfw')


	def paste(self, data, x, y):
		'''data = numpy array or NpImg'''
		img = NpImage(data)
		data = img.data
		#Write RGB
		for bandIdx in range(3): #writearray is available only at band level
			bandArray = data[:,:,bandIdx]
			self.ds.GetRasterBand(bandIdx+1).WriteArray(bandArray, x, y)
		#Process alpha
		hasAlpha = data.shape[2] == 4
		if hasAlpha:
			alpha = data[:,:,3]
			if self.useMask:
				self.mask.WriteArray(alpha, x, y)
			else:
				self.ds.GetRasterBand(4).WriteArray(alpha, x, y)
		else:
			pass # replaced by fill method
			'''
			#make alpha band or internal mask fully opaque
			h, w = data.shape[0], data.shape[1]
			alpha = np.full((h, w), 255, np.uint8)
			if self.useMask:
				self.mask.WriteArray(alpha, x, y)
			else:
				self.ds.GetRasterBand(4).WriteArray(alpha, x, y)
			'''



	def __repr__(self):
		return '\n'.join([
		"* Data infos :",
		" size {}".format(self.size),
		" type {}".format(self.dtype),
		" number of bands {}".format(self.nbBands),
		"* Georef & Geometry : \n{}".format(self.georef)
		])