package com.alternativagame.engine3d.object {
	import com.alternativagame.engine3d.View3D;
	import com.alternativagame.engine3d.engine3d;
	import com.alternativagame.engine3d.material.HelperMaterial;
	import com.alternativagame.engine3d.material.Material;
	import com.alternativagame.engine3d.object.light.Light3D;
	import com.alternativagame.engine3d.skin.DummySkin;
	import com.alternativagame.engine3d.skin.Skin;
	import com.alternativagame.type.RGB;
	import com.alternativagame.type.Vector;
	
	import flash.display.DisplayObject;
	import flash.utils.Dictionary;

	use namespace engine3d;
	
	public class SkinObject3D extends Object3D {
		
		use namespace engine3d;
		
		// Отображение объекта в камере
		protected var skin:Skin = null;
		private var _material:Material;
		
		// Список цветов источников с учетом силы
		private var lights:Dictionary;
		
		// Текущее освещение
		private var _lightColor:RGB = null;
		
		// Нормаль всех скин-объектов
		static private var normal:Vector = new Vector(0, -1, 0);
		
		public function SkinObject3D(material:Material = null) {
			super();
			this.material = material;
			lights = new Dictionary();
		}

		override protected function updateTransform():void { 
			// Обновить глубину скина и добавить его в список сортировки
			if (skin != null) {
				skin.depth = transform.h;
				view.addToDepth(skin);
			
				// Если изменилась геометрия
				if (geometryChanged) {
					view.addToDraw(skin);
				} else {
					if (positionChanged) {
						// Если изменилась позиция
						view.addToPosition(skin);
					}
				}
			}
		}
		
		// Обновиться после освещения
		override protected function updateLight():void {
			// Флаг на добавление в список освещения
			var toLight:Boolean = false;
			
			// Если есть источники на пересчёт, обновляем список
			if (lightChanged.length > 0) {
				
				var color:RGB;
				
				for each (var light:Light3D in lightChanged) {
					// Расчот производим, только если в одной солид-группе
					if (light.solidParent == solidParent) {
						// Мои координаты
						var coords:Vector = new Vector(transform.d, transform.h, transform.l);
						
						// Получаем освещение от источника
						color = light.getLightColor(coords, normal);
						
						if (color == null) {
							delete lights[light];
						} else {
							lights[light] = color;
						}
					} else {
						delete lights[light];
					}
				}

				// Расчёт общего света
				var newLightColor:RGB = new RGB();
				for each (color in lights) {
					newLightColor.add(color);
				}

				// Если свет новый, добавляем на освещение
				if (lightColor == null || !newLightColor.equals(lightColor)) {
					_lightColor = newLightColor;
					toLight = true;
				}
			} else {
				// Если освещения ещё не было, установить по умолчанию и добавить на освещение
				if (lightColor == null) {
					_lightColor = new RGB();
					toLight = true;
				}
			}
			// Если добавляем на освещение, есть скин и камера, то отправляем на освещение в камеру
			if (toLight && skin != null && view != null) {
				view.addToLight(skin);
			}
		}
		
		override engine3d function setView(value:View3D):void {
			if (value == null) {
				if (skin != null) {
					view.removeSkin(skin);
					_lightColor = null;
					skin = null;
				}
			} else {
				if (material != null) {
					skin = createSkin();
					if (skin != null) value.addSkin(skin);
				}
			}
			super.setView(value);
		}
		
		protected function createSkin():Skin {
			return null;
		}
		
		// Обновление скина при смене каких-либо параметров объекта
		protected function updateSkin():void {
			if (view != null && skin != null) {
				view.addToDraw(skin);
				view.addToLight(skin);
			}
		}

		public function get lightColor():RGB {
			return _lightColor;
		}
		
		// Установить новый материал
		public function set material(value:Material):void {
			// Если объект в камере
			if (view != null) {
				// Устанавливаем материал
				if (value != null) {
					if (skin == null) {
						skin = createSkin();
						if (skin != null) view.addSkin(skin);
					}
					// Обновляем скин
					updateSkin();
				// Сбрасываем материал
				} else {
					if (skin != null) {
						view.removeSkin(skin);
						skin = null;
					}
				}
			}
			// Сохраняем значение материала
			_material = value;
		}

		public function get material():Material {
			return _material;
		}
		
		// При смене параметров обновляем скин
		override public function set solid(value:Boolean):void {
			super.solid = value;
			updateSkin();
		}		

		override engine3d function setSolidParent(value:Object3D):void {
			super.setSolidParent(value);
			updateSkin();
		}		

		override engine3d function setParent(value:Object3D):void {
			super.setParent(value);
			updateSkin();
		}		

		override public function set name(value:String):void {
			super.name = value;
			updateSkin();
		}
		
		// Клон
		override public function clone():Object3D {
			var res:SkinObject3D = new SkinObject3D();
			cloneParams(res);
			return res;
		}
		
		// Клонировать параметры
		override protected function cloneParams(object:*):void {
			var obj:SkinObject3D = SkinObject3D(object);
			super.cloneParams(obj);
			obj.material = material;
		}

	}
}