#!/usr/bin/env python
# Author: Sascha Silbe
# "License": Public Domain
import base64
import ConfigParser
import os
import sys
import httplib
import xml.dom.minidom
import xml.xpath
from convcommon import *

apiHost       = "api.openstreetmap.org"
apiPort       = 80
apiBasePath   = "/api/0.5"
apiUploadPath = apiBasePath+"/%(type_)s/%(id_)d"


def uploadHttp(path, content) :
  global cfg

  authInfo = "Basic "+(cfg.get('global', 'username')+":"+cfg.get('global', 'password')).encode("base64").rstrip()
  hdrs = {
    "Authorization": authInfo,
    "Content-Length": len(content),
  }
  conn = httplib.HTTPConnection(apiHost, apiPort)
  conn.request("PUT", path, headers = hdrs, body = content.encode('utf-8'))
  resp = conn.getresponse()
  if (resp.status != 200) :
    raise IOError("API returned HTTP code %d: %s" % (resp.status, resp.reason))

def uploadSingle(rootNode, xmlNode, type_) :
  id_ = int(xmlNode.attributes['id'].nodeValue)
  newRootNode = rootNode.cloneNode(deep=False)
  newRootNode.appendChild(xmlNode)
  uploadHttp(apiUploadPath % locals(), newRootNode.toxml())

def uploadMulti(rootNode, type_) :
  for entry in xml.xpath.Evaluate("/osm/"+type_, rootNode) :
    uploadSingle(rootNode, entry, type_)

def uploadOsm(rootNode) :
  uploadMulti(rootNode, "node")
  uploadMulti(rootNode, "way")
  uploadMulti(rootNode, "relation")


def printSyntax(myName) :
  print "Syntax: "+myName+" <osmFile>"
  print "Sample: "+myName+" is_in_fixed.osm"
  print
  print "<osmFile> needs to be an XML file in the format used by OSM API 0.5."
  print "No merging or input validation is done, so please BE CAREFUL."
  print "Creation of new objects is NOT supported."
  print
  print "osmbulkupload.ini (in current directory) must contain the following:"
  print "[global]"
  print "username=<yourOsmUserName>"
  print "password=<yourOsmPassword>"
  return 100

def main(myName, args) :
  global cfg

  if len(args) != 1 :
    return printSyntax(myName)

  osmFName = args[0]

  cfg = ConfigParser.SafeConfigParser()
  cfg.read("osmbulkupload.ini")

  uploadOsm(xml.dom.minidom.parse(file(osmFName)).documentElement)

  return 0


sys.exit(main(sys.argv[0], sys.argv[1:]))
