import re
from akara import logger
from akara import response
from akara.services import simple_service
from amara.thirdparty import json
from dplaingestion.selector import getprop, setprop, exists
from dplaingestion.utilities import iterify

@simple_service('POST', 'http://purl.org/la/dp/harvard_enrich_location',
                'harvard_enrich_location', 'application/json')
def harvard_enrich_location(body, ctype, action="harvard_enrich_location",
                            prop="sourceResource/spatial"):
    """
    Service that accepts a Harvard JSON document and enriches the "spatial" field by translating 
    any MARC country codes contained within the originalDocument place element into their names, 
    for better geocoding accuracy.     
    """
    try:
        data = json.loads(body)
    except:
        response.code = 500
        response.add_header('content-type', 'text/plain')
        return "Unable to parse body as JSON"

    if (exists(data, "originalRecord/metadata/mods/originInfo/place")):
        places = getprop(data, "originalRecord/metadata/mods/originInfo/place")
        country = ""
        countryCode = ""
        name = ""

        # Add non-country terms 
        for place in iterify(places):
            placeTerm = getprop(place, "placeTerm", True)
            if (isinstance(placeTerm, basestring)): 
                name += " " + placeTerm
            elif (not exists(placeTerm, "authority")):
                name += " " + getprop(placeTerm, "#text", True)

        # Add country 
        for place in iterify(places):
            placeTerm = getprop(place, "placeTerm", True)
            if (exists(placeTerm, "authority") \
                and "marccountry" == getprop(placeTerm, "authority", True)):
                countryCode = getprop(placeTerm, "#text", True)
                country = get_country_from_marccode(countryCode)
                if (country): 
                    name += ", " + country

        spatial = {"name": re.sub("[\[\]]", "", name.strip(", "))}
        if (country \
            and (2 == len(countryCode) \
                 or countryCode.startswith("xx"))): 
            spatial["country"] = country

        setprop(data, prop, [spatial])

    return json.dumps(data)

def get_country_from_marccode(code):
    """
    Replace MARC country abbreviations with full names.
    """
    MARC_CODES = {
        "aa":	"Albania",
        "abc":	"Alberta",
        "-ac":	"Ashmore and Cartier Islands",
        "aca":	"Australian Capital Territory",
        "ae":	"Algeria",
        "af":	"Afghanistan",
        "ag":	"Argentina",
        "-ai":	"Anguilla",
        "ai":	"Armenia (Republic)",
        "-air":	"Armenian S.S.R.",
        "aj":	"Azerbaijan",
        "-ajr":	"Azerbaijan S.S.R.",
        "aku":	"Alaska",
        "alu":	"Alabama",
        "am":	"Anguilla",
        "an":	"Andorra",
        "ao":	"Angola",
        "aq":	"Antigua and Barbuda",
        "aru":	"Arkansas",
        "as":	"American Samoa",
        "at":	"Australia",
        "au":	"Austria",
        "aw":	"Aruba",
        "ay":	"Antarctica",
        "azu":	"Arizona",
        "ba":	"Bahrain",
        "bb":	"Barbados",
        "bcc":	"British Columbia",
        "bd":	"Burundi",
        "be":	"Belgium",
        "bf":	"Bahamas",
        "bg":	"Bangladesh",
        "bh":	"Belize",
        "bi":	"British Indian Ocean Territory",
        "bl":	"Brazil",
        "bm":	"Bermuda Islands",
        "bn":	"Bosnia and Hercegovina",
        "bo":	"Bolivia",
        "bp":	"Solomon Islands",
        "br":	"Burma",
        "bs":	"Botswana",
        "bt":	"Bhutan",
        "bu":	"Bulgaria",
        "bv":	"Bouvet Island",
        "bw":	"Belarus",
        "-bwr":	"Byelorussian S.S.R.",
        "bx":	"Brunei",
        "ca":	"Caribbean Netherlands",
        "cau":	"California",
        "cb":	"Cambodia",
        "cc":	"China",
        "cd":	"Chad",
        "ce":	"Sri Lanka",
        "cf":	"Congo (Brazzaville)",
        "cg":	"Congo (Democratic Republic)",
        "ch":	"China (Republic : 1949- )",
        "ci":	"Croatia",
        "cj":	"Cayman Islands",
        "ck":	"Colombia",
        "cl":	"Chile",
        "cm":	"Cameroon",
        "-cn":	"Canada",
        "co":	"Cura\'e7ao",
        "cou":	"Colorado",
        "-cp":	"Canton and Enderbury Islands",
        "cq":	"Comoros",
        "cr":	"Costa Rica",
        "-cs":	"Czechoslovakia",
        "ctu":	"Connecticut",
        "cu":	"Cuba",
        "cv":	"Cape Verde",
        "cw":	"Cook Islands",
        "cx":	"Central African Republic",
        "cy":	"Cyprus",
        "-cz":	"Canal Zone",
        "dcu":	"District of Columbia",
        "deu":	"Delaware",
        "dk":	"Denmark",
        "dm":	"Benin",
        "dq":	"Dominica",
        "dr":	"Dominican Republic",
        "ea":	"Eritrea",
        "ec":	"Ecuador",
        "eg":	"Equatorial Guinea",
        "em":	"Timor-Leste",
        "enk":	"England",
        "er":	"Estonia",
        "-err":	"Estonia",
        "es":	"El Salvador",
        "et":	"Ethiopia",
        "fa":	"Faroe Islands",
        "fg":	"French Guiana",
        "fi":	"Finland",
        "fj":	"Fiji",
        "fk":	"Falkland Islands",
        "flu":	"Florida",
        "fm":	"Micronesia (Federated States)",
        "fp":	"French Polynesia",
        "fr":	"France",
        "fs":	"Terres australes et antarctiques fran\'e7aises",
        "ft":	"Djibouti",
        "gau":	"Georgia",
        "gb":	"Kiribati",
        "gd":	"Grenada",
        "-ge":	"Germany (East)",
        "gh":	"Ghana",
        "gi":	"Gibraltar",
        "gl":	"Greenland",
        "gm":	"Gambia",
        "-gn":	"Gilbert and Ellice Islands",
        "go":	"Gabon",
        "gp":	"Guadeloupe",
        "gr":	"Greece",
        "gs":	"Georgia (Republic)",
        "-gsr":	"Georgian S.S.R.",
        "gt":	"Guatemala",
        "gu":	"Guam",
        "gv":	"Guinea",
        "gw":	"Germany",
        "gy":	"Guyana",
        "gz":	"Gaza Strip",
        "hiu":	"Hawaii",
        "-hk":	"Hong Kong",
        "hm":	"Heard and McDonald Islands",
        "ho":	"Honduras",
        "ht":	"Haiti",
        "hu":	"Hungary",
        "iau":	"Iowa",
        "ic":	"Iceland",
        "idu":	"Idaho",
        "ie":	"Ireland",
        "ii":	"India",
        "ilu":	"Illinois",
        "inu":	"Indiana",
        "io":	"Indonesia",
        "iq":	"Iraq",
        "ir":	"Iran",
        "is":	"Israel",
        "it":	"Italy",
        "-iu":	"Israel-Syria Demilitarized Zones",
        "iv":	"C\'f4te d'Ivoire",
        "-iw":	"Israel-Jordan Demilitarized Zones",
        "iy":	"Iraq-Saudi Arabia Neutral Zone",
        "ja":	"Japan",
        "ji":	"Johnston Atoll",
        "jm":	"Jamaica",
        "-jn":	"Jan Mayen",
        "jo":	"Jordan",
        "ke":	"Kenya",
        "kg":	"Kyrgyzstan",
        "-kgr":	"Kirghiz S.S.R.",
        "kn":	"Korea (North)",
        "ko":	"Korea (South)",
        "ksu":	"Kansas",
        "ku":	"Kuwait",
        "kv":	"Kosovo",
        "kyu":	"Kentucky",
        "kz":	"Kazakhstan",
        "-kzr":	"Kazakh S.S.R.",
        "lau":	"Louisiana",
        "lb":	"Liberia",
        "le":	"Lebanon",
        "lh":	"Liechtenstein",
        "li":	"Lithuania",
        "-lir":	"Lithuania",
        "-ln":	"Central and Southern Line Islands",
        "lo":	"Lesotho",
        "ls":	"Laos",
        "lu":	"Luxembourg",
        "lv":	"Latvia",
        "-lvr":	"Latvia",
        "ly":	"Libya",
        "mau":	"Massachusetts",
        "mbc":	"Manitoba",
        "mc":	"Monaco",
        "mdu":	"Maryland",
        "meu":	"Maine",
        "mf":	"Mauritius",
        "mg":	"Madagascar",
        "-mh":	"Macao",
        "miu":	"Michigan",
        "mj":	"Montserrat",
        "mk":	"Oman",
        "ml":	"Mali",
        "mm":	"Malta",
        "mnu":	"Minnesota",
        "mo":	"Montenegro",
        "mou":	"Missouri",
        "mp":	"Mongolia",
        "mq":	"Martinique",
        "mr":	"Morocco",
        "msu":	"Mississippi",
        "mtu":	"Montana",
        "mu":	"Mauritania",
        "mv":	"Moldova",
        "-mvr":	"Moldavian S.S.R.",
        "mw":	"Malawi",
        "mx":	"Mexico",
        "my":	"Malaysia",
        "mz":	"Mozambique",
        "-na":	"Netherlands Antilles",
        "nbu":	"Nebraska",
        "ncu":	"North Carolina",
        "ndu":	"North Dakota",
        "ne":	"Netherlands",
        "nfc":	"Newfoundland and Labrador",
        "ng":	"Niger",
        "nhu":	"New Hampshire",
        "nik":	"Northern Ireland",
        "nju":	"New Jersey",
        "nkc":	"New Brunswick",
        "nl":	"New Caledonia",
        "-nm":	"Northern Mariana Islands",
        "nmu":	"New Mexico",
        "nn":	"Vanuatu",
        "no":	"Norway",
        "np":	"Nepal",
        "nq":	"Nicaragua",
        "nr":	"Nigeria",
        "nsc":	"Nova Scotia",
        "ntc":	"Northwest Territories",
        "nu":	"Nauru",
        "nuc":	"Nunavut",
        "nvu":	"Nevada",
        "nw":	"Northern Mariana Islands",
        "nx":	"Norfolk Island",
        "nyu":	"New York (State)",
        "nz":	"New Zealand",
        "ohu":	"Ohio",
        "oku":	"Oklahoma",
        "onc":	"Ontario",
        "oru":	"Oregon",
        "ot":	"Mayotte",
        "pau":	"Pennsylvania",
        "pc":	"Pitcairn Island",
        "pe":	"Peru",
        "pf":	"Paracel Islands",
        "pg":	"Guinea-Bissau",
        "ph":	"Philippines",
        "pic":	"Prince Edward Island",
        "pk":	"Pakistan",
        "pl":	"Poland",
        "pn":	"Panama",
        "po":	"Portugal",
        "pp":	"Papua New Guinea",
        "pr":	"Puerto Rico",
        "-pt":	"Portuguese Timor",
        "pw":	"Palau",
        "py":	"Paraguay",
        "qa":	"Qatar",
        "qea":	"Queensland",
        "quc":	"Qu\'e9bec (Province)",
        "rb":	"Serbia",
        "re":	"R\'e9union",
        "rh":	"Zimbabwe",
        "riu":	"Rhode Island",
        "rm":	"Romania",
        "ru":	"Russia (Federation)",
        "-rur":	"Russian S.F.S.R.",
        "rw":	"Rwanda",
        "-ry":	"Ryukyu Islands, Southern",
        "sa":	"South Africa",
        "-sb":	"Svalbard",
        "sc":	"Saint-Barth\'e9lemy",
        "scu":	"South Carolina",
        "sd":	"South Sudan",
        "sdu":	"South Dakota",
        "se":	"Seychelles",
        "sf":	"Sao Tome and Principe",
        "sg":	"Senegal",
        "sh":	"Spanish North Africa",
        "si":	"Singapore",
        "sj":	"Sudan",
        "-sk":	"Sikkim",
        "sl":	"Sierra Leone",
        "sm":	"San Marino",
        "sn":	"Sint Maarten",
        "snc":	"Saskatchewan",
        "so":	"Somalia",
        "sp":	"Spain",
        "sq":	"Swaziland",
        "sr":	"Surinam",
        "ss":	"Western Sahara",
        "st":	"Saint-Martin",
        "stk":	"Scotland",
        "su":	"Saudi Arabia",
        "-sv":	"Swan Islands",
        "sw":	"Sweden",
        "sx":	"Namibia",
        "sy":	"Syria",
        "sz":	"Switzerland",
        "ta":	"Tajikistan",
        "-tar":	"Tajik S.S.R.",
        "tc":	"Turks and Caicos Islands",
        "tg":	"Togo",
        "th":	"Thailand",
        "ti":	"Tunisia",
        "tk":	"Turkmenistan",
        "-tkr":	"Turkmen S.S.R.",
        "tl":	"Tokelau",
        "tma":	"Tasmania",
        "tnu":	"Tennessee",
        "to":	"Tonga",
        "tr":	"Trinidad and Tobago",
        "ts":	"United Arab Emirates",
        "-tt":	"Trust Territory of the Pacific Islands",
        "tu":	"Turkey",
        "tv":	"Tuvalu",
        "txu":	"Texas",
        "tz":	"Tanzania",
        "ua":	"Egypt",
        "uc":	"United States Misc. Caribbean Islands",
        "ug":	"Uganda",
        "-ui":	"United Kingdom Misc. Islands",
        "uik":	"United Kingdom Misc. Islands",
        "-uk":	"United Kingdom",
        "un":	"Ukraine",
        "-unr":	"Ukraine",
        "up":	"United States Misc. Pacific Islands",
        "-ur":	"Soviet Union",
        "-us":	"United States",
        "utu":	"Utah",
        "uv":	"Burkina Faso",
        "uy":	"Uruguay",
        "uz":	"Uzbekistan",
        "-uzr":	"Uzbek S.S.R.",
        "vau":	"Virginia",
        "vb":	"British Virgin Islands",
        "vc":	"Vatican City",
        "ve":	"Venezuela",
        "vi":	"Virgin Islands of the United States",
        "vm":	"Vietnam",
        "-vn":	"Vietnam, North",
        "vp":	"Various places",
        "vra":	"Victoria",
        "-vs":	"Vietnam, South",
        "vtu":	"Vermont",
        "wau":	"Washington (State)",
        "-wb":	"West Berlin",
        "wea":	"Western Australia",
        "wf":	"Wallis and Futuna",
        "wiu":	"Wisconsin",
        "wj":	"West Bank of the Jordan River",
        "wk":	"Wake Island",
        "wlk":	"Wales",
        "ws":	"Samoa",
        "wvu":	"West Virginia",
        "wyu":	"Wyoming",
        "xa":	"Christmas Island (Indian Ocean)",
        "xb":	"Cocos (Keeling) Islands",
        "xc":	"Maldives",
        "xd":	"Saint Kitts-Nevis",
        "xe":	"Marshall Islands",
        "xf":	"Midway Islands",
        "xga":	"Coral Sea Islands Territory",
        "xh":	"Niue",
        "-xi":	"Saint Kitts-Nevis-Anguilla",
        "xj":	"Saint Helena",
        "xk":	"Saint Lucia",
        "xl":	"Saint Pierre and Miquelon",
        "xm":	"Saint Vincent and the Grenadines",
        "xn":	"Macedonia",
        "xna":	"New South Wales",
        "xo":	"Slovakia",
        "xoa":	"Northern Territory",
        "xp":	"Spratly Island",
        "xr":	"Czech Republic",
        "xra":	"South Australia",
        "xs":	"South Georgia and the South Sandwich Islands",
        "xv":	"Slovenia",
        "xx":	"No place, unknown, or undetermined",
        "xxc":	"Canada",
        "xxk":	"United Kingdom",
        "-xxr":	"Soviet Union",
        "xxu":	"United States",
        "ye":	"Yemen",
        "ykc":	"Yukon Territory",
        "-ys":	"Yemen (People's Democratic Republic)",
        "-yu":	"Serbia and Montenegro",
        "za":	"Zambia"
    }

    if (code in MARC_CODES): 
        return MARC_CODES[code]

    return None
