class Easydb4Migration.SyrianWeber extends Easydb4MigrationTool
	name: ->
		"syrian-weber"

	rpad: (s, len, pad) ->
		while s.length < len
			s = pad + s
		return s

	run: (save_payload_func) ->

		all_data = {}

		promises = []

		for _tb in [
			# ortsthesaurus
			"property.RealEstateNo"

			# photos
			"photos.PhotoID"
			"photothematicblocs.PhotoID"
			"photosdetails.PhotoID"
			"propertyrealestatetype.RealEstateNo"

			# art_des_motivs, teilelement
			"realestatestatetbl.ID"  # photos

			# "person"
			"architecttbl.ID"

			# "periode" (automatisch)
			"centurypositiontbl.ID"

			# unused
			"countriestbl.ID"

			# easydb einfaches feld
			"constructionphasestbl.ID"

			# "element"
			"elementstbl.ID"

			# unused
			# filingcodetbl


			# unused
			# monthtbl -> ignorieren

			# art_des_motivs
			"functionofunittbl.ID"

			# bedeutung
			"importancetbl.ID"

			# unused
			"locationtbl.ID"

			# easydb "material", "teilelement", "element", "technik"
			"materialstbl.ID"

			# unused
			"numberoffloorstbl.ID"

			# easydb "epoche", "stilmerkmal"
			"periodtbl.ID"

			# easydb "person", + Pool Switch"!
			"photographertbl.ID"

			# easydb "schlagwort"
			"photoqualitytbl.ID"

			# art_des_motivs, element, szene_der_vorlage
			"photos_to_unit.Unit"

			# easydb feld "quelle" + Pool Switch !
			"photosourcetbl.ID"

			# easydb "material_der_vorlage"
			"phototypestbl.ID"

			# unused
			# "photothematicblocstbl"

			# easydb "ortsthesaurus_ownership"
			"propertyownershiptbl.ID"

			# unused
			# propertyrealestatetype

			# unused
			# "realestatestatetype.ID"

			# action
			"realestatestatetbl.ID"

			# teilelement, art_des_motivs
			"realestatetypestbl.ID"

			# szene_der_vorlage
			"regionstbl.ID"

			# element, material, technik, teilelement
			"specificationtbl.ID"

			# art_des_motivs, ueberschrift
			"thematicblocstbl.ID"

		]

			parts = _tb.split(".")

			do (parts) =>
				tb = parts[0]
				tb_key = parts[1]

				if tb in ["photosWEG"]
					limit = "WHERE PhotographerID = '3'" # LIMIT 1000"
				else
					limit = ""

				promise = @_migration.query('SELECT * FROM "source.'+tb+'.csv" '+limit)
				.done (data) =>
					for row in data.rows
						if not all_data[tb]
							all_data[tb] = {}
						key = row[tb_key]
						if not all_data[tb][key]
							all_data[tb][key] = []
						all_data[tb][key].push(row)

				promises.push(promise)



		# 	FunctionOfUnitId: "functionofunittbl"
		# 	HistoricalPhotograph:


		# MapRefNo wird als source.photo ergänzt in RealEstateNo, PhotoRefNo

		# XXX: "pool:" shortname: weber_db

		target_map =
			ortsthesaurus:
				easydb4_reference:
					type: "text"
					type: "text"
				es_architekt_id:
					table: "person"
					create:
						reference:
							column: "easydb4_reference"
						column: "name"
						type: "l10n"
					lookup:
						column: "easydb4_reference"
					type: "text"
				notes:
					type: "l10n"
				beschreibung:
					type: "l10n"
				es_beschreibung:
					type: "l10n"
				namensnutzungsgeschichte:
					type: "l10n"
				es_datierung_hijri_bereich:
					type: "date_range"
				es_datierung_gregorian_bereich:
					type: "date_range"
				gazetteerid:
					type: "text"
				immobilie_ownership_specs:
					type: "l10n"
				lk_ownership_id:
					table: "ortsthesaurus_ownership"
					create:
						reference:
							column: "easydb4_reference"
						column: "name"
						type: "l10n"
					lookup:
						column: "easydb4_reference"
				action:
					lk_action_id:
						table: "action"
						lookup:
							column: "easydb4_reference"
						create:
							reference:
								column: "easydb4_reference"
							column: "name"
							type: "l10n"
				bedeutung:
					bedeutung_id: # ??? lk_bedeutung_id in DB !!
						table: "bedeutung"
						lookup:
							column: "easydb4_reference"
						create:
							reference:
								column: "easydb4_reference"
							column: "name"
							type: "l10n"
						db_column: "lk_bedeutung_id"

				epoche:
					es_epoche_id: # ??? lk_epoche_id in DB!!
						table: "epoche"
						lookup:
							column: "easydb4_reference"
						create:
							reference:
								column: "easydb4_reference"
							column: "name"
							type: "l10n"
						db_column: "lk_epoche_id"
			pool:
				lk_pool_id:
					type: "pool"

			bilder:
				easydb4_reference:
					type: "text"
				beschreibung:
					type: "text"
				ueberschrift:
					type: "l10n"
				original_datum:
					type: "date"
				quelle:
					type: "text"
				material_der_vorlage_id:
					table: "material_der_vorlage"
					create:
						reference:
							column: "easydb4_reference"
						column: "name"
						type: "l10n"
					lookup:
						column: "easydb4_reference"
				ersteller_der_vorlage_id:
					table: "person"
					create:
						reference:
							column: "easydb4_reference"
						column: "name"
						type: "l10n"
					lookup:
						column: "easydb4_reference"
				lk_schlagwort_id:
					table: "schlagwort"
					create:
						reference:
							column: "easydb4_reference"
						column: "name"
						type: "text"
					lookup:
						column: "easydb4_reference"
				szene_der_vorlage_id:
					table: "szene_der_vorlage"
					create:
						reference:
							column: "easydb4_reference"
						column: "name"
						type: "l10n"
					lookup:
						column: "easydb4_reference"
				art_der_vorlage_id:
					table: "art_der_vorlage"
					create:
						reference:
							column: "easydb4_reference"
						column: "name"
					lookup:
						column: "easydb4_reference"
				art_des_motivs_id:
					table: "art_des_motivs"
					create:
						reference:
							column: "easydb4_reference"
						column: "name"
						type: "l10n"
					lookup:
						column: "easydb4_reference"
				ebene:
					lk_ebene_id:
						table: "ebene"
						create:
							reference:
								column: "easydb4_reference"
								value_template: "weber:%value%"
							column: "name"
							type: "l10n"
						lookup:
							column: "easydb4_reference"
				element:
					lk_element_id:
						table: "element"
						create:
							reference:
								column: "easydb4_reference"
								value_template: "weber:%value%"
							column: "name"
							type: "l10n"
						lookup:
							column: "easydb4_reference"
				technik:
					lk_technik_id:
						table: "technik"
						lookup:
							column: "easydb4_reference"
						create:
							reference:
								column: "easydb4_reference"
							column: "name"
							type: "l10n"
				material:
					lk_material_id:
						table: "material"
						lookup:
							column: "easydb4_reference"
						create:
							reference:
								column: "easydb4_reference"
							column: "name"
							type: "l10n"
				stilmerkmal:
					lk_stilmerkmal_id:
						table: "stilmerkmal"
						lookup:
							column: "easydb4_reference"
						create:
							reference:
								column: "easydb4_reference"
							column: "name"
							type: "text"
				teilelement:
					lk_teilelement_id:
						table: "teilelement"
						lookup:
							column: "easydb4_reference"
						create:
							reference:
								column: "easydb4_reference"
							column: "name"
							type: "l10n"


		# Notes -> Standort
		# RealEstateNo -> beides
		# UseByNameL -> Standort
		# USerSpecification -> Standort
		# RegionID -> null
		# PropertyOwnershipID -> Standort
		# OwnershipSpecification -> Standort
		# EstimatedCadastreNumber -> Standort
		# EstimatedCentury -> Erstellungsphase
		# CenturyID -> Erstellungphase
		# CenturyPositionID -> Erstellungsphase
		# PeriodID -> Erstellungsphase
		# NumberOfFloorsID -> Standort
		# RealEstateStateID -> Standort
		# ConstructionPhases -> Erstellungsphase
		# StructuralFabric -> Standort
		# Importance -> Standort
		# ArchitectID -> Erstellungsphase
		# HijriYear -> Erstellungsphase
		# HijriMonth -> Erstellungsphase
		# HijriDay -> Erstellungsphase
		# GregorianYear -> Erstellungsphase
		# GregorianMonth -> Erstellungsphase
		# GregorianDay -> Erstellungsphase
		# Notes2 -> Erstellungsphase
		# MapRefNo -> null

		# Erstellungsphase Tag: "construction_phase"
		#
		# Photo.erstellungsphase_id <- Erstellungsphase
		# Photo.ort_des_motivs_id <- Standort


		map =
			property:
				construction_phase:
					"Gazetteer ID":
						mapFunc: (source, dest) ->
							dest["lookup:_id_parent"] =
								gazetteerid: source["Gazetteer ID"]

					RealEstateNo:
						mapFunc: (source, dest) =>
							dest.__RealEstateNo = source.RealEstateNo
							dest.name = source.RealEstateNo

						copy:
							table: "ortsthesaurus"
							column: "easydb4_reference"
							value_template: "weber:property:construction_phase:%value%"

					CenturyID:
						mapFunc: (source, dest) =>
							nested = "_nested:ortsthesaurus__periode"
							if not dest[nested]
								dest[nested] = []

							nesobj =
								lk_attribute_zahl_id:
									_objecttype: "attribute"
									_mask: "_all_fields"
									attribute:
										"lookup:_id":
											easydb4_reference: "weber:Century:"+source.CenturyID

							if source.CenturyPositionID in ["2", "3", "4"]
								nesobj.lk_periode_id =
									_objecttype: "periode"
									_mask: "_all_fields"
									periode:
										"lookup:_id":
											easydb4_reference: "weber:CenturyPosition:"+source.CenturyPositionID

							if source.EstimatedCentury == "WAHR"
								nesobj.lk_attribute_id =
									_objecttype: "attribute"
									_mask: "_all_fields"
									attribute:
										"lookup:_id":
											easydb4_reference: "weber:EstimatedCentury:approx"

							dest[nested].push(nesobj)
							return

					CenturyPositionID: null
					EstimatedCentury: null

					PeriodID:
						use_table:
							csv: "periodtbl"
							table: "Table"
							column: "Feld"
							value_column: "Value"
					ArchitectID:
						use_table:
							csv: "architecttbl"
							table: "Table"
							column: "Feld"
							value_column: "Value"
					HijriYear:
						date:
							table: "ortsthesaurus"
							column: "es_datierung_hijri_bereich"
							month: "HijriMonth"
							day: "HijriDay"
					GregorianYear:
						date:
							table: "ortsthesaurus"
							column: "es_datierung_gregorian_bereich"
							month: "GregorianMonth"
							day: "GregorianDay"
					Notes2:
						copy:
							table: "ortsthesaurus"
							column: "beschreibung"
							value_template: "[ Stefan Weber: %value% ]"
					ConstructionPhases:
						use_table:
							csv: "constructionphasestbl"
							table: "Tabelle"
							column: "Feld"
							value_column: "Value"
							value_template: "[ Weber: %value% ]"

				location:
					"Gazetteer ID":
						mapFunc: (source, dest) =>
							# no copy, so that data will not be appended
							dest.gazetteerid = source["Gazetteer ID"]
						# copy:
						# 	table: "ortsthesaurus"
						# 	column: "gazetteerid"
					Notes:
						copy:
							table: "ortsthesaurus"
							column: "notes"
							value_template: "[ SHAP: %value% ]"

					RealEstateNo:
						mapFunc: (source, dest) =>
							if not dest.__RealEstateNo
								dest.__RealEstateNo = []

							dest.__RealEstateNo.push(source.RealEstateNo)
							dest.name = source["Gazetteer ID"]+" ["+dest.__RealEstateNo.join(",")+"]"
							return

					UsedByNameL:
						copy:
							table: "ortsthesaurus"
							column: "namensnutzungsgeschichte"
							value_template: "[ original: %value% ]"

					UserSpecification:
						copy:
							table: "ortsthesaurus"
							column: "namensnutzungsgeschichte"
							value_template: "[ user specification: %value% ]"
						mapFunc: (source, dest) ->
							nested = "_nested:ortsthesaurus__autornamensnutzungsgeschichte_neu"
							if not dest[nested]
								dest[nested] = []
							nesobj =
								autornamensnutzungsgeschichte_id:
									_objecttype: "person"
									_mask: "_all_fields"
									person:
										"lookup:_id":
											easydb4_reference: "weber:Person:Weber"

							dest[nested].push(nesobj)
							dest[nested+":group_mode"] = "append"

					RegionID: null

					PropertyOwnershipID:
						use_table:
							csv: "propertyownershiptbl"
							table: "Table"
							column: "Feld"
							value_column: "Value"

					EstimatedCadastreNumber:
						boolean:
							table: "ortsthesaurus"
							column: "beschreibung"
							value: "[ Weber: estimated cadastral number, becaused vanished or a later division. ]"
					OwnershipSpecification:
						copy:
							table: "ortsthesaurus"
							column: "immobilie_ownership_specs"
							value_template: "[Original: %value%]"

					# NumberOfFloorsID:
					# 	use_field:
					# 		csv: "numberoffloorstbl"
					# 		table: "Mapping ID"
					# 		column: "column_3"
					# 		value: "column_5"

					RealEstateStateID:
						use_table:
							csv: "realestatestatetbl"
							table: "Table"
							column: "Feld"
							value_column: "Value" # action.name
							map:
								registerno: "Value 1" # ?????
								datum: "Value 2"

					StructuralFabric:
						copy:
							table: "ortsthesaurus"
							column: "beschreibung"
							value_template: "[ structual fabric: %value% ]"

					Importance:
						use_table:
							csv: "importancetbl"
							table: "Table"
							column: "Feld"
							value_column: "Value"


					# Importance:
					# 	use_field: "importancetbl"
					# 	table: "Mapping ID"
					# 	column: "column_3"
					#
					# ??????????
					# mapFunc: (source, dest) =>
					# 	nested = "_nested:ortsthesaurus__person"
					# 	if not dest[nested]
					# 		dest[nested] = []
					# 	dest[nested].push(nesobj)
					# 	nesobj =
					# 		lk_person_id:
					# 			_objecttype: "person"
					# 			_mask: "_all_fields"
					# 			person:
					# 				"lookup:_id":
					# 					easydb4_reference: "weber:Person:Weber"

					# 	dest[nested].push(nesobj)


			photos:
				RealEstateNo:
					mapFunc: (source, dest) =>
						gaz_id = all_data.property[source.RealEstateNo]?[0]["Gazetteer ID"]

						if not gaz_id
							@_migration.logerror("Gazetteer ID not found for PhotoID: "+source.PhotoID+" RealEstateNo: "+source.RealEstateNo)
							return

						dest.erstellungsphase_id =
							_objecttype: "ortsthesaurus"
							_mask: "_all_fields"
							ortsthesaurus:
								"lookup:_id":
									easydb4_reference: "weber:property:construction_phase:"+source.RealEstateNo

						dest.ort_des_motivs_id =
							_objecttype: "ortsthesaurus"
							_mask: "_all_fields"
							ortsthesaurus:
								"lookup:_id":
									gazetteerid: gaz_id

						return
				PhotoID:
					copy:
						table: "bilder"
						column: "easydb4_reference"
						value_template: "weber:photos:%value%"
				FunctionOfUnitID:
					use_table:
						csv: "functionofunittbl"
						table: "Table"
						column: "Feld"
						value_column: "Value"
				HistoricalPhotograph:
					boolean:
						table: "bilder"
						column: "art_der_vorlage_id"
						value: "Vintage print"
				MuseumDatabase:
					boolean:
						table: "bilder"
						column: "art_der_vorlage_id"
						value: "[Digital source]"
				Notes:
					copy:
						table: "bilder"
						column: "beschreibung"
						value_template: "[ Weber: %value% ]"
				PhotoYear:
					date:
						table: "bilder"
						column: "original_datum"
						month: "PhotoMonth"
						day: "PhotoDay"
				PhotoQualityID:
					use_table:
						csv: "photoqualitytbl"
						table: "Table"
						column: "Field"
						value_column: "Value"
				PropertyOwnershipID: null
				PhotoSource:
					use_table:
						csv: "photosourcetbl"
						table: "Table"
						column: "Feld"
						pool_column: "Pool > collection id"
						value_column: "Value"
				PhotoRefNo:
					eas:
						column: "bild"
						path: "PhotoRefNo"
						ext: "PhotoRefNoExt"
				MapRefNo:
					eas:
						column: "bild"
						path: "MapRefNo"
						ext: "MapRefNoExt"
				PhotoTypeID:
					use_table:
						csv: "phototypestbl"
						table: "Table"
						column: "Feld"
						value_column: "Value"
				PhotographerID:
					use_table:
						csv: "photographertbl"
						table: "Table"
						column: "Feld"
						value_column: "Value"
						pool_column: "Pool > collection id"
				Unit:
					use_table:
						csv: "photos_to_unit"
						table: "Table"
						column: "Feld"
						value_column: "Value"
				# mapped via propertyrealestatetype
				RealEstateTypeID:
					use_table:
						csv: "realestatetypestbl"
						table: "Table"
						column: "Feld"
						value_column: "Value"

			photosdetails:
				SpecificationID:
					use_table:
						csv: "specificationtbl"
						table: "Table"
						column: "Feld"
						value_column: "Value"
				ElementID:
					use_table:
						csv: "elementstbl"
						table: "Table"
						column: "Feld"
						value_column: "Value"
				MaterialID:
					use_table:
						csv: "materialstbl"
						table: "Table"
						column: "Feld"
						value_column: "Value"
				PeriodID:
					use_table:
						csv: "periodtbl"
						table: "Table"
						column: "Feld"
						value_column: "Value"


		# returns the target info
		get_target = (dest) =>
			target =
				info: null
				nested: null
				ignore: false
				nested_object: {}

			if dest.csv
				row = dest.row
				if not row
					console.warn("Target not found:", dest.csv, "Row:", row)
					return null

				dest_table = row[dest.table]
				table = dest_table?.split(" > ") or []
				dest_column = row[dest.column]

				target.source_table = dest.csv
				target.source_value = row.__source_unique_id

				target.value = row[dest.value_column] # holds the value
				target.pool = row[dest.pool_column]   # holds the value

				if target.pool
					# console.warn "a pool is set!", target
					return target

				if dest_table == "ignore" or
					table[0] != dest.__objecttype or
					(target.value == "ignore" and not dest_table and not dest_column)
						target.ignore = true
						return target


				if not dest_table or not dest_column or CUI.util.isEmpty(target.value)
					console.warn("Target not found:", dest.csv, "Row:", row, "Dest Column:", dest_column, "Dest Table:", dest_table, "Row:", row, "Dest:", dest, "Value:", target.value)
					return null

				if dest.value_template
					target.value = dest.value_template.replace(/%value%/, target.value)

				if dest.map #
					target.nested_object = {}
					for source_col, target_col of dest.map
						target.nested_object[target_col] = row[source_col]

			else
				dest_table = dest.table
				table = dest_table.split(" > ")
				dest_column = dest.column

			if dest.db_column
				target.column = dest.db_colum
			else
				target.column = dest_column

			if not dest_table
				console.warn("Target not found:", dest_table, dest_column)
				return null

			target.table = table[0]

			if table.length == 2 # nested
				target.info = target_map[target.table]?[table[1]]?[dest_column]
				target.nested = "_nested:"+target.table+"__"+table[1]

			else
				target.info = target_map[target.table]?[dest_column]
				target.nested = null

			if not target.info
				console.warn("Target Info not found: Table:", table, "Column:", dest_column)
				return null

			return target


		set_value = (dest, target, value) =>

			info = target.info

			get_value_by_type = (value, type) =>

				switch type
					when "date_range"
						date = value.trim()
						[y, m, d] = date.split("-")
						set =
							from: @parse_date(y, m, d)
							to:  @parse_date(y, m, d)
					when "date"
						date = value.trim()
						[y, m, d] = date.split("-")
						set =
							value: @parse_date(y, m, d)
					when "text"
						set = value.trim()
					when "l10n"
						set = "en-US": value.trim()
					else
						set = value.trim()

				return set

			set = get_value_by_type(value, info?.type)


			if info?.table
				ref = value # reference for lookup

				if info.create
					c = info.create
					# value needs to be created
					pl = payloads[info.table]
					if not pl
						pl = payloads[info.table] = import_type: "db", objecttype: info.table, objects: []

					ref = "weber:"+target.source_table+":"+target.source_value

					found = false
					for obj in pl.objects
						if obj[obj._objecttype][c.reference.column] == ref
							# object already in create
							found = true

					if not found
						# create object in payload

						topobj =
							_objecttype: info.table
							_mask: "_all_fields"

						obj =
							_version: 1

						obj[c.column] = get_value_by_type(value, info.create.type)
						obj[c.reference.column] = ref

						topobj[topobj._objecttype] = obj
						pl.objects.push(topobj)

				if info.lookup
					set =
						_objecttype: info.table
						_mask: "_all_fields"

					set[info.table] = "lookup:_id": {}
					set[info.table]["lookup:_id"][info.lookup.column] =
						(info.lookup.value_template or "%value%").replace(/%value%/, ref)


			if target.nested
				if not dest[target.nested]
					dest[target.nested] = []

				nesobj = target.nested_object
				nesobj[target.column] = set
				dest[target.nested].push(nesobj)


				if dest.__objecttype == "ortsthesaurus"
					dest[target.nested+":group_mode"] = "append"

			else
				if CUI.util.isString(dest[target.column]) # already there
					dest[target.column] = dest[target.column] + "\n" + set
				else
					dest[target.column] = set
			return

		do_map = (source, dest, rules) =>

			# console.debug "do_map:", source, dest, rules

			for key, rule of rules

				value = source[key]
				if value == undefined
					console.error("do_map: Key not in source:", key, rule, source)

				if CUI.util.isEmpty(value)
					continue

				if rule == null
					continue

				# console.debug "rule:", rule, "key:", key

				if rule.mapFunc
					rule.mapFunc(source, dest)

				if rule.use_table
					data = all_data[rule.use_table.csv]
					if not data
						console.warn("CSV ", rule.use_table.csv, "not found: ", source, dest, rule)
						continue

					if value == "0"
						continue

					rows = data[value]
					if rows == undefined
						@_migration.logwarn("Value \""+value+"\" in CSV \""+rule.use_table.csv+"\" not found.")
						continue

					tinfo = rule.use_table
					tinfo.__objecttype = dest.__objecttype

					# if rule.use_table.csv == "photographertbl"
					# 	console.warn("Rule:", rule, "Source:", source, "Dest:", dest, "Data:", data, "Rows:", rows, "Value:", value, "Data:", data)

					for row, idx in rows
						tinfo.row = row
						target = get_target(tinfo)

						if not target
							console.warn("rule:", rule, "key:", key, "value:", value)
							continue

						# if rule.use_table.csv == "elementstbl"
						# 	console.debug "target:", target

						if target.ignore
							continue

						# if rule.use_table.csv == "photographertbl"
						# 	console.debug "value:", value, "data:", data, "idx:", idx, "target:", target, "row:", row, "dest:", dest

						if target.pool
							dest._pool =
								pool:
									"lookup:_id":
										shortname: target.pool
							continue

						set_value(dest, target, target.value)


					continue

				if rule.boolean
					# FALSCH: ignorieren
					# WAHR: setzen

					if value == "FALSCH"
						continue

					target = rule.boolean
					target.info = target_map[target.table]?[target.column]
					target.source_table = "boolean"
					target.source_value = target.value

					set_value(dest, target, target.value)
					continue

				if rule.date
					target = get_target(rule.date)
					if not target
						console.warn("rule:", rule, "key:", key, "value:", value)
						continue

					# column: "original_datum"
					# month: "PhotoMonth"
					# day: "PhotoDay"

					date = value # the Year
					if value == "0"
						continue

					date = @parse_date(
						value
						source[rule.date.month]?.trim()
						source[rule.date.day]?.trim()
					)

					set_value(dest, target, date)
					continue

				if rule.eas
					if not dest[rule.eas.column]
						dest[rule.eas.column] = []

					ext = source[rule.ext] or ""

					dest[rule.eas.column].push
						"eas:url": "http://irgendwo/"+rule.eas.path+"/"+value+"."+ext

					if dest[rule.eas.column].length == 1
						dest[rule.eas.column][0].preferred = true

					continue

				if rule.link
					target = get_target(rule.link)
					if not target
						console.warn("rule:", rule, "key:", key, "value:", value)
						continue

					set_value(dest, target, value)
					continue

				if rule.copy
					target = get_target(rule.copy)
					if not target
						console.warn("rule:", rule, "key:", key, "value:", value)
						continue

					if not rule.copy.value_template
						tmpl = "%value%"
					else
						tmpl = rule.copy.value_template

					set_value(dest, target, tmpl.replace(/%value%/, value))
					continue

				if rule.mapFunc
					continue

				console.error("do_map: Unknown rule:", key, rule, source, dest)

		payloads =
			bilder:
				import_type: "db"
				objecttype: "bilder"
				objects: []
			location:
				import_type: "db"
				objecttype: "ortsthesaurus"
				objects: []
			construction_phase:
				import_type: "db"
				objecttype: "ortsthesaurus"
				objects: []
			person:
				import_type: "db"
				objecttype: "person"
				objects: []
			periode:
				import_type: "db"
				objecttype: "periode"
				objects: []
			attribute:
				import_type: "db"
				objecttype: "attribute"
				objects: []

		payloads.person.objects.push
			_objecttype: "person"
			_mask: "_all_fields"
			person:
				_version: 1
				name:
					"en-US": "Stefan Weber"
				easydb4_reference: "weber:Person:Weber"


		for CenturyPosition, CenturyPositionID in ["early","mid","late"]
			payloads.periode.objects.push
				_objecttype: "periode"
				_mask: "_all_fields"
				periode:
					_version: 1
					name:
						"en-US": CenturyPosition
					easydb4_reference: "weber:CenturyPosition:"+(CenturyPositionID+2)

		for CenturyID in [1..22]
			if CenturyID < 10
				id = "0" + CenturyID
			else
				id = "" + CenturyID

			payloads.attribute.objects.push
				_objecttype: "attribute"
				_mask: "_all_fields"
				attribute:
					_version: 1
					name:
						"en-US": id
					easydb4_reference: "weber:Century:"+CenturyID

		payloads.attribute.objects.push
			_objecttype: "attribute"
			_mask: "_all_fields"
			attribute:
				_version: 1
				name:
					"en-US": "<approx>"
				easydb4_reference: "weber:EstimatedCentury:approx"


		master_dfr = new CUI.Deferred()

		CUI.when(promises)
		.done =>

			isInt = (k) =>
				if CUI.util.getInt(k) == null
					return false
				else
					return true

			console.debug "Loaded all data", all_data, "Target Map:", target_map, "Map:", map

			pl_loc = payloads.location
			pl_con = payloads.construction_phase

			for RealEstateNo, p of all_data.property
				if p.length > 1
					@_migration.logwarn("Property: "+RealEstateNo+" exists "+p.length+" times. Skipping > 1.")
				prop = p[0]
				gaz_id = prop["Gazetteer ID"].trim()

				if not gaz_id
					@_migration.logerror("Property: "+RealEstateNo+" has no Gazetteer ID. Skipping.")
					continue

				# make sure we don't have spaces
				prop["Gazetteer ID"] = gaz_id

				ort_con =
					__objecttype: "ortsthesaurus"
					_version: 1

				pl_con.objects.push
					_objecttype: "ortsthesaurus"
					_mask: "_all_fields"
					_tags: [
						"lookup:_id":
							shortname: "construction_phase"
					]
					ortsthesaurus: ort_con

				do_map(prop, ort_con, map.property.construction_phase)

				ort_loc = null

				# find existing, so we can append
				for ort in pl_loc.objects
					if gaz_id != ort.ortsthesaurus.gazetteerid
						continue
					ort_loc = ort.ortsthesaurus
					console.debug "FOUND gaz_id", gaz_id, ort
					break

				if not ort_loc
					ort_loc =
						__objecttype: "ortsthesaurus"
						_version: 1

					pl_loc.objects.push
						_objecttype: "ortsthesaurus"
						_mask: "_all_fields"
						ortsthesaurus: ort_loc

				# console.debug "property:", p[0]
				do_map(prop, ort_loc, map.property.location)



			pl = payloads.bilder

			for PhotoID, p of all_data.photos

				if p.length > 1
					@_migration.logerror("More than one photo with PhotoID: "+PhotoID)

				for p0 in p
					bild =
						__objecttype: "bilder"
						_version: 1

					# mapped via propertyrealestatetype
					p0.RealEstateTypeID = all_data.propertyrealestatetype[p.RealEstateNo]?.RealEstateTypeID or ""

					do_map(p0, bild, map.photos)

					pdetails = all_data.photosdetails[PhotoID]
					for pdetail in pdetails or []
						# console.debug "pdetail:", pdetail, bild, map.photosdetails
						do_map(pdetail, bild, map.photosdetails)

					if not bild._pool
						bild._pool =
							pool:
								"lookup:_id":
									shortname: "weber_db"

					pl.objects.push
						_objecttype: "bilder"
						_mask: "_all_fields"
						bilder: bild
				;

			# Sort and write out payloads

			console.debug "payloads:", payloads

			names = (name for name of payloads)
			names.sort (a, b) =>
				end = ["location", "construction_phase", "bilder"]
				if a in end
					a = "ZZ"+end.indexOf(a)
				if b in end
					b = "ZZ"+end.indexOf(b)
				return a.localeCompare(b)

			promises = []
			for name in names
				json = payloads[name]
				len = json.objects.length
				if len <= 1000
					promises.push(save_payload_func(name+"-"+json.objects.length+".json", json))
				else
					for idx in [0...len] by 1000
						json_copy = CUI.util.copyObject(json, false)
						json_copy.objects = json.objects.slice(idx, idx+1000)
						from = idx+1
						to = Math.min(len, idx+1000)
						promises.push(save_payload_func(name+"-"+from+"-"+to+".json", json_copy))

			CUI.when(promises)
			.done(master_dfr.resolve)
			.fail(master_dfr.reject)

		return master_dfr.promise()

	parse_date: (year, month, day) ->
		days_per_month = [0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]

		date = @rpad(year, 4, "0")

		if month == "0" or !month
			month = ""

		if day == "0" or !day
			day = ""

		if month.length > 0
			if month.length == 1
				date = date+"-0"+month
			if month.length == 2
				date = date+"-"+month

			if day.length > 0
				day_int = parseInt(day)
				month_int = parseInt(month)

				if day_int > days_per_month[month_int]
					@_migration.logwarn("Corrected date: "+year+"-"+month+"-"+day)
					day = days_per_month[month_int]+""

				if day.length == 1
					date = date+"-0"+day
				if day.length == 2
					date = date+"-"+day



		return date



ez5.session_ready =>
	Easydb4Migration.tools.registerPlugin(Easydb4Migration.SyrianWeber)
