#!/usr/bin/env python3.2
# -*- coding: utf-8 -*-

# Copyright 2012, Svavar Kjarrval Lúthersson
# Released under the CC0 license.
# I can be contacted at svavar@kjarrval.is.

# This program performs changes according to pretermined formulas to .osm files
# and outputs a single .osc file which in turn can either be submitted automatically
# by another program (which is not implemented here) or manually with an editor.

# To use it, you must have:
# 1 - An .osm file of the area in question.
# 2 - An Osmosis binary set up and ready to use.

# The reason the script filters instead of working directly on the original file
# is to reduce memory consumption of programs which need to load the complete .osm file into memory.
# If, despite having done proper filtering, the .osm file is still too big to fit into memory,
# please consider splitting the area further.

import os
import xml.etree.cElementTree as etree

# Change the value of DEBUG to 0 when you don't want extra debug messages to appear on screen.
DEBUG = 0

# Get the current working directory
pwd = os.getcwd() + '/'

# Location of the osmosis binary.
osmosis_bin = '/home/kjarrval/bin/osmosis'

# A recently-updated .osm file with an extract of the area of interest from OpenStreetMap.
# This script does not change this file.
original_osm_file = 'iceland.osm'

# Name of the filtered .osm file. It will be completely overwritten each time the script runs.
filtered_osm_file = 'osmosis_filtered.osm'

# Name of the finished .osm file. It will be completely overwritten each time the script runs
finished_osm_file = 'osmosis_finished.osm'

# The finished .osc file. It will be completely overwritten each time the script runs.
finished_osc_file = 'osmosis_finished.osc'

# The filter to use on the original file.
# See https://wiki.openstreetmap.org/wiki/Osmosis/Detailed_Usage#--tag-filter_.28--tf.29 for usage.
# The Osmosis filter is processed in order
osmosis_filter_to_use = ' --tf accept-relations götuskrá:id=*'
osmosis_filter_to_use += ' --tf reject-ways'
osmosis_filter_to_use += ' --tf reject-nodes'

# Run the osmosis command
osmosis_command = osmosis_bin
if DEBUG == 0:
	osmosis_command += ' -q'
osmosis_command += ' --read-xml ' + pwd + original_osm_file + ' ' + osmosis_filter_to_use
osmosis_command += ' --write-xml ' + pwd + filtered_osm_file

# Debug
if DEBUG == 1:
	print(osmosis_command)

# Let's run the Osmosis command
os.system(osmosis_command)
# Now we should have a filtered .osm file

# Now let's work on running whatever script on the data we want.
# The if condition is to simplify for people where the data processing starts and ends.
# 'götuskrá:id' is a reference to the entry ID in the postcode file from the Icelandic Postal Service.
if 1:
	osm_xml = etree.parse(pwd + filtered_osm_file)
	postcodes_xml = etree.parse(pwd + 'gotuskra.xml')

	# Process the postcodes file into a dictionary
	street = {}
	for element in postcodes_xml.iter("Gata"):
#		print(element[0].text)
		street[element[0].text] = [element[1].text,element[2].text,element[3].text]
#	print(repr(street))

	# Go through every relation
	for element in osm_xml.iter("relation"):
		tags_arr = {}
		tags = element.iterfind('tag')
		# All tags put into a dictionary which can be referenced by key name.
		for tag in tags:
			tags_arr[tag.get('k')] = tag.get('v')

		# Check if the relation has the key götuskrá:id.
		# If it doesn't have it, skip to the next relation.
		if 'götuskrá:id' not in tags_arr:
			continue

		# Verify that the street names match.
		# If they don't, the götuskrá:id has a typo or the streetname.
		# In which case, it should be left alone instead of populating 
		# the relation with potentially wrong data.
		if tags_arr['name'] == street[tags_arr['götuskrá:id']][1]:
			# The götuskrá:id and streetname match
			# Now we only need to check what needs to be changed and change it.

			# Check if there is a tag with addr:postcode. If not, add it.
			if 'addr:postcode' not in tags_arr:
				attrib = {'k':'addr:postcode','v':street[tags_arr['götuskrá:id']][0]}
				etree.SubElement(element,'tag',attrib)
			else:
				# Finds the occurance of the tag where addr:postcode is.
				ele = element.find("tag/[@k='addr:postcode']")
				# Change the value to the one according to the postcode file.
				ele.set('v',street[tags_arr['götuskrá:id']][0])

			# We want the noun case inflection of the street names as an alternative names.
			# But we don't want to overwrite any other alternative names
			# so we leave it alone if one exists.
			if 'alt_name' not in tags_arr:
				attrib = {'k':'alt_name','v':street[tags_arr['götuskrá:id']][2]}
				etree.SubElement(element,'tag',attrib)

	# Open a file handler to write the new .osm file and write it.
	osm_xml.write(pwd + finished_osm_file)

# Now we have written a finished .osm file and all that's left is to make Osmosis
# compare it to the filtered file and generate an .osc file which only has the changes.
osmosis_command = osmosis_bin
if DEBUG == 0:
	osmosis_command += ' -q'
osmosis_command += ' --read-xml file="' + pwd + finished_osm_file + '"'
osmosis_command += ' --read-xml file="' + pwd + filtered_osm_file + '"'
osmosis_command += ' --dc --write-xml-change file="' + pwd + finished_osc_file + '"'

# Debug
if DEBUG == 1:
	print(osmosis_command)
os.system(osmosis_command)
