=begin
TIG (c) 2015 
All rights reserved.
TIG-LayerWatcher_code...
=end
###
module TIG
 module LayerWatcher
	###
	unless file_loaded?(__FILE__)
		UI.add_context_menu_handler{|menu|
			menu.add_item("Selected-Geometry-To-Layer0"){ self.to_layer0() } if self.geometry?()
		}
		file_loaded(__FILE__)
	end
	###
	def self.geometry?()
		@ss = Sketchup.active_model.selection
		geom = @ss.grep(Sketchup::Edge) + @ss.grep(Sketchup::Face)
		@geometry = geom.select{|e| e.layer.name != "Layer0" }
		@nested_geometry = []
		@processed_defns = []
		self.nested_geometry?(@ss.grep(Sketchup::Group) + @ss.grep(Sketchup::ComponentInstance))
		@nested_geometry.flatten!
		@nested_geometry.compact!
		@nested_geometry.uniq!
		if @geometry[0] || @nested_geometry[0]
			return true
		else
			return false
		end
	end
	###
	def self.nested_geometry?(ents=[])
		return unless ents[0]
		###
		geometry = []
		geom = ents.grep(Sketchup::Edge)
		geom << ents.grep(Sketchup::Face)
		geom.flatten!
		geometry << geom.select{|e| e.layer.name != "Layer0" }
		geometry.flatten!
		geometry.compact!
		###
		gps = ents.grep(Sketchup::Group)
		gps.each{|gp|
			next if @processed_defns.include?(gp.entities.parent)
			@processed_defns << gp.entities.parent
			geom = gp.entities.grep(Sketchup::Edge)
			geom << gp.entities.grep(Sketchup::Face)
			geom.flatten!
			geom.compact!
			geometry << geom.select{|e| e.layer.name != "Layer0" }
			geometry.flatten!
			geometry.compact!
			ngps = gp.entities.grep(Sketchup::Group)
			ngps.each{|e| self.nested_geometry?(e.entities.to_a) }
			nins = gp.entities.grep(Sketchup::ComponentInstance)
			nins.each{|e| self.nested_geometry?(e.definition.entities.to_a) }
		}
		ins = ents.grep(Sketchup::ComponentInstance)
		ins.each{|i|
			next if @processed_defns.include?(i.definition)
			@processed_defns << i.definition
			geom = i.definition.entities.grep(Sketchup::Edge)
			geom << i.definition.entities.grep(Sketchup::Face)
			geom.flatten!
			geom.compact!
			geometry << geom.select{|e| e.layer.name != "Layer0" }
			geometry.flatten!
			geometry.compact!
			ngps = i.definition.entities.grep(Sketchup::Group)
			ngps.each{|e| self.nested_geometry?(e.entities.to_a) }
			nins = i.definition.entities.grep(Sketchup::ComponentInstance)
			nins.each{|e| self.nested_geometry?(e.definition.entities.to_a) }
		}
		###
		@nested_geometry << geometry if geometry[0]
		###
	end
	###
	def self.to_layer0()
		if @nested_geometry[0]
			UI.beep
			yn = UI.messagebox("Assign \"Layer0\" to All Nested Geometry in the Selection ?", MB_YESNO)
			if yn == 6
				@geometry = @geometry + @nested_geometry
				@geometry.flatten!
				@geometry.compact!
				@geometry.uniq!
			end
		else
			yn = -1
		end
		model = Sketchup.active_model
		layers = model.layers
		model.start_operation("Selected-Geometry-To-Layer0", true)
		  @geometry.each{|e| e.layer = layers[0] }
		model.commit_operation
		if @geometry[0]
			es = @geometry.grep(Sketchup::Edge).length
			ess="s"
			ess="" if es==1
			fs = @geometry.grep(Sketchup::Face).length
			fss="s"
			fss="" if fs==1
			msg = "Reassigned \"Layer0\" to #{es} Edge#{ess} and #{fs} Face#{fss}."
			if @nested_geometry[0]
				es = @nested_geometry.grep(Sketchup::Edge).length
				ess="s"
				ess="" if es==1
				fs = @nested_geometry.grep(Sketchup::Face).length
				fss="s"
				fss="" if fs==1
				ds = @processed_defns.length
				dss="s"
				dss="" if ds==1
				if yn == 6
					msg << "\nIncluding #{es} Edge#{ess} and #{fs} Face#{fss}\nfound Nested within the #{ds} Selected Object#{dss}."
				else
					msg << "\nSkipped #{es} Edge#{ess} and #{fs} Face#{fss}\nfound Nested within the #{ds} Selected Object#{dss}."
				end
			end
			UI.messagebox(msg)
		end
	end
	###
	class LayersObserver < Sketchup::LayersObserver
		def onCurrentLayerChanged(layers, layer)
			begin
				model = layer.model
			rescue
				return
			end
			return if model.tools.active_tool_name == "RubyTool" ### if inside Plugin skip
			return if layer.name == "Camera_FOV_Lines" || layer.name == "Camera_FOV_Volume" ### ACT trap
			unless layer.name == "Layer0"
				UI.beep
				if UI.messagebox("You should normally model with the 'current-layer' set as 'Layer0' !\nDo you really want to change it to '#{layer.name}' ?", MB_YESNO) == 7
					UI.start_timer(0.1, false){ 
						model.start_operation("Layer0", true, false, true)
							model.active_layer = layers[0]
						model.commit_operation
					}
				end
			end
		end
  end
	###
	LO = LayersObserver.new()
  @model = Sketchup.active_model
	@layers = @model.layers
	@layers.remove_observer(LO)
	@layers.add_observer(LO)
	###
	class EntitiesObserver < Sketchup::EntitiesObserver
		def onElementAdded(entities, entity)
			return unless entity.valid?
			model = entity.model
			#p model.tools.active_tool_name
			return if model.tools.active_tool_name == "RubyTool" ### if inside Plugin skip
			if entity.is_a?(Sketchup::Edge) || entity.is_a?(Sketchup::Face)
				model.start_operation("Layer0", true, false, true)
				  entity.layer = model.layers[0]
				model.commit_operation
			end
		end
  end
	###
	EO = EntitiesObserver.new()
	@model = Sketchup.active_model
	@ents = @model.entities
	@ents.remove_observer(EO)
	@ents.add_observer(EO)
	###
	@model = Sketchup.active_model
	@definitions = @model.definitions
	### process existing entities
	@definitions.each{|definition|
		next if ! definition.valid? || definition.image?
		definition.entities.remove_observer(EO)
		definition.entities.add_observer(EO)
	}
	### trap for future definitions added...
	class DefinitionsObserver < Sketchup::DefinitionsObserver
		include LayerWatcher
		def onComponentAdded(definitions, definition)
			return unless definition.valid?
			unless definition.image?
				definition.entities.remove_observer(EO)
				definition.entities.add_observer(EO)
			end
		end
		def onComponentTypeChanged(definitions, definition)
			return unless definition.valid?
			unless definition.image?
				definition.entities.remove_observer(EO)
				definition.entities.add_observer(EO)
			end
		end
	end
	### add initially
	DO = DefinitionsObserver.new()
	@definitions.remove_observer(DO)
	@definitions.add_observer(DO)
	###
	class AppObserver < Sketchup::AppObserver
		include LayerWatcher
		def onNewModel(model)
			model.definitions.remove_observer(DO)
			model.definitions.add_observer(DO)
			ents = model.entities
			ents.remove_observer(EO)
			ents.add_observer(EO)
			model.definitions.each{|definition|
				next if ! definition.valid? || definition.image?
				definition.entities.remove_observer(EO)
				definition.entities.add_observer(EO)
			}
			Sketchup.remove_observer(AO)
			Sketchup.add_observer(AO)
		end
		def onOpenModel(model)
			model.definitions.remove_observer(DO)
			model.definitions.add_observer(DO)
			ents = model.entities
			ents.remove_observer(EO)
			ents.add_observer(EO)
			model.definitions.each{|definition|
				next if ! definition.valid? || definition.image?
				definition.entities.remove_observer(EO)
				definition.entities.add_observer(EO)
			}
			Sketchup.remove_observer(AO)
			Sketchup.add_observer(AO)
		end
		def onActivateModel(model) ### MAC 
			model.definitions.remove_observer(DO)
			model.definitions.add_observer(DO)
			ents = model.entities
			ents.remove_observer(EO)
			ents.add_observer(EO)
			model.definitions.each{|definition|
				next if ! definition.valid? || definition.image?
				definition.entities.remove_observer(EO)
				definition.entities.add_observer(EO)
			}
			Sketchup.remove_observer(AO)
			Sketchup.add_observer(AO)
		end
    end
	### add App observer to SketchUp initially
	AO = AppObserver.new()
	Sketchup.remove_observer(AO)
  Sketchup.add_observer(AO)
	###
 end#module
end#module
