########################################################################
#	Hello Worlds - Libre 3D RPG game.
#	Copyright (C) 2020  CYBERDEViL
#
#	This file is part of Hello Worlds.
#
#	Hello Worlds 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.
#
#	Hello Worlds 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 <https://www.gnu.org/licenses/>.
#
########################################################################


from panda3d.core import AmbientLight, DirectionalLight
from panda3d.core import Fog
from panda3d.core import Vec3

from panda3d.bullet import BulletTriangleMesh
from panda3d.bullet import BulletTriangleMeshShape

from panda3d.bullet import BulletRigidBodyNode

from core.db import Maps

from direct.showbase import DirectObject
class MapLoader(DirectObject.DirectObject):
	def __init__(self, world, worldNP):
		"""	Map values
			- file
			- background color
			- fog
			- lightning

			
		"""
		self._world = world
		self._world.setGravity(Vec3(0, 0, -9.81))

		self._worldNP = worldNP

		self._currentId = -1;
		self._loadingId = -1;
		self._map = None
		self._fog = None
		self._np = None

		self._finisehdLoadingCallback = None

		# TODO create list/dict for lights with options to set per map
		self._ambientLight = None
		self._directionalLight = None

	@property
	def currentId(self):
		return self._currentId

	@property
	def currentMap(self):
		return Maps[self.currentId]

	def unload(self):
		if not self._map:
			print("Tried to unload a map, but no loaded.");
			return

		loader.unloadModel(self._map)
		self._map.removeNode()
		del self._map
		self._map = None

		self._world.remove(self._np.node())
		self._np.removeNode()
		self._np = None

		if self._fog:
			#self._fog.detachNode()
			#self._fog.removeNode()
			self._fog = None
			render.clearFog()

		if self._ambientLight:
			#self._ambientLight.detachNode()
			#self._ambientLight.removeNode()
			self._ambientLight = None

		if self._directionalLight:
			#self._directionalLight.detachNode()
			#self._directionalLight.removeNode()
			self._directionalLight = None

			render.clearLight()

		self._currentId = -1;

	def _finisehdLoading(self, loadedMap):
		print("_finisehdLoading")
		self._map = loadedMap

		# Create a new node point for our Enviroment.
		self._np = self._worldNP.attachNewNode(BulletRigidBodyNode('Enviroment'))

		# Go over all objects in the PandaNode loaded from a file.
		for match in self._map.findAllMatches('**/+GeomNode'):
			# If in blender under game properties a property with the name
			# `m_collide` is set and is a True value then add a collision
			# mesh.
			if match.node().getTag('m_collide'):
				mesh = BulletTriangleMesh()
				mesh.addGeom(match.node().getGeom(0))
				shape = BulletTriangleMeshShape(mesh, dynamic=False)

				t = match.node().getTransform()
				self._np.node().addShape(shape, t)

			match.clearModelNodes()
			match.reparentTo(self._np)

		self._world.attach(self._np.node())

		# TODO Setup per map.
		# Fog
		self._fog = Fog('mapFog')
		fogColor = (0.25, 0.25, 0.25)
		# 0.3, 0.3, 0.4, 1
		self._fog.setColor(*fogColor)
		#self._fog.setExpDensity(.015)
		self._fog.setExpDensity(.01)
		#self._fog.setColor(*fogColor)

		#self._fog.setLinearRange(0,320)
		#self._fog.setLinearFallback(45,160,320)

		#base.setBackgroundColor(*fogColor)
		render.setFog(self._fog)

		# Create some lighting
		self._ambientLight = AmbientLight("ambientLight")
		self._ambientLight.setColor((.3, .3, .3, 1))
		self._directionalLight = DirectionalLight("directionalLight")
		self._directionalLight.setDirection((-5, -5, -5))
		self._directionalLight.setColor((1, 1, 1, 1))
		self._directionalLight.setSpecularColor((1, 1, 1, 1))
		render.setLight(render.attachNewNode(self._ambientLight))
		render.setLight(render.attachNewNode(self._directionalLight))

		# Additional lights
		self._directionalLight2 = DirectionalLight("directionalLight")
		self._directionalLight2.setDirection((-200, 400, -25))
		self._directionalLight2.setColor((1, 1, 1, 1))
		self._directionalLight2.setSpecularColor((1, 1, 1, 1))
		render.setLight(render.attachNewNode(self._directionalLight2))

		self._currentId = self._loadingId
		self._loadingId = -1
		if self._finisehdLoadingCallback:
			self._finisehdLoadingCallback()
			self._finisehdLoadingCallback = None

	def load(self, id, callback=None):
		if self._currentId != -1:
			print("Already a map loaded, please unload that first.");
			return

		map = Maps[id]
		if not map:
			print("Map with id: `{0}` not found.".format(id));
			return

		self._finisehdLoadingCallback = callback
		self._loadingId = id

		# Load file into PandaNode.
		loader.loadModel(
			map.filePath,
			callback = self._finisehdLoading,
		);
