# -*- coding: utf-8 -*-

from __future__ import division
import hashlib 
import os
import urllib2
from urllib import urlencode
import Image

from oxlib.cache import getUrl, getUrlUnicode
from oxlib.text import findRe

flags = [
    # pass
    ["CH", "Switzerland", "pass()"],
    # ["CH-AG", "Aargau", "pass()"],
    ["CH-GE", "Canton of Geneva", "pass()"],
    ["VA", "Holy See", "pass()"],
    # crop
    ["AL", "Albania", "crop()"],
    ["AM", "Armenia", "crop()"],
    ["AN", "Netherlands Antilles", "crop()"],
    ["AO", "Angola", "crop()"],
    ["AR", "Argentina", "crop()"],
    ["AT", "Austria", "crop()"],
    ["BF", "Burkina Faso", "crop()"],
    ["BG", "Bulgaria", "crop()"],
    ["BN", "Brunei Darussalam", "crop()"],
    ["BO", "Bolivia", "crop()"],
    ["BW", "Botswana", "crop()"],
    ["BZ", "Belize", "crop()"],
    ["CO", "Colombia", "crop()"],
    ["CY", "Cyprus", "crop()"],
    ["DE", "Germany", "crop()"],
    ["DM", "Dominica", "crop()"],
    ["DO", "Dominican Republic", "crop()"],
    ["DZ", "Algeria", "crop()"],
    ["EA", "Ceuta and Melilla", "crop()"],
    ["EC", "Ecuador", "crop()"],
    ["EE", "Estonia", "crop()"],
    ["EG", "Egypt", "crop()"],
    ["ET", "Ethiopia", "crop()"],
    ["EU", "European Union", "crop()"],
    ["FM", "Micronesia", "crop()"],
    ["GA", "Gabon", "crop()"],
    ["GF", "French Guiana", "crop()"],
    ["GG", "Guernsey", "crop()"],
    ["GH", "Ghana", "crop()"],
    ["GI", "Gibraltar", "crop()"],
    ["GM", "Gambia", "crop()"],
    ["HK", "Hong Kong", "crop()"],
    ["HN", "Honduras", "crop()"],
    ["HR", "Croatia", "crop()"],
    ["HT", "Haiti", "crop()"],
    ["HU", "Hungary", "crop()"],
    ["ID", "Indonesia", "crop()"],
    ["IL", "Israel", "crop()"],
    ["IM", "Isle of Man", "crop()"],
    ["IN", "India", "crop()"],
    ["IQ", "Iraq", "crop()"],
    ["IR", "Iran", "crop()"],
    ["JP", "Japan", "crop()"],
    ["KE", "Kenya", "crop()"],
    ["KG", "Kyrgyzstan", "crop()"],
    ["KH", "Cambodia", "crop()"],
    ["KI", "Kiribati", "crop()"],
    ["KN", "Saint Kitts and Nevis", "crop()"],
    ["LA", "Laos", "crop()"],
    ["LB", "Lebanon", "crop()"],
    ["LC", "Saint Lucia", "crop()"],
    ["LS", "Lesotho", "crop()"],
    ["LT", "Lithuania", "crop()"],
    ["LU", "Luxembourg", "crop()"],
    ["LV", "Latvia", "crop()"],
    ["LY", "Libya", "crop()"],
    ["MA", "Morocco", "crop()"],
    ["MC", "Monaco", "crop()"],
    ["MO", "Macau", "crop()"],
    ["MP", "Northern Mariana Islands", "crop()"],
    ["MR", "Mauritania", "crop()"],
    ["MU", "Mauritius", "crop()"],
    ["MW", "Malawi", "crop()"],
    ["NE", "Niger", "crop()"],
    ["NI", "Nicaragua", "crop()"],
    ["NL", "Netherlands", "crop()"],
    ["PF", "French Polynesia", "crop()"],
    ["PL", "Poland", "crop()"],
    ["PY", "Paraguay", "crop()"],
    ["RU", "Russia", "crop()"],
    ["SA", "Saudi Arabia", "crop()"],
    ["SL", "Sierra Leone", "crop()"],
    ["SM", "San Marino", "crop()"],
    ["SO", "Somalia", "crop()"],
    ["SR", "Suriname", "crop()"],
    ["SV", "El Salvador", "crop()"],
    ["TH", "Thailand", "crop()"],
    ["TJ", "Tajikistan", "crop()"],
    ["TN", "Tunisia", "crop()"],
    ["UA", "Ukraine", "crop()"],
    ["UG", "Uganda", "crop()"],
    ["VN", "Vietnam", "crop()"],
    ["YE", "Yemen", "crop()"],
    ["CSXX", "Serbia and Montenegro", "crop()"],
    ["DDDE", "East Germany", "crop()"],
    ["HVBF", "Upper Volta", "crop()"],
    ["NHVU", "New Hebrides", "crop()"],
    ["NTHH", "Neutral Zone", "crop()"],
    ["PCHH", "Pacific Islands", "crop()"],
    ["PZPA", "Panama Canal Zone", "crop()"],
    ["YUCS", "Yugoslavia", "crop()"],
    ["ZRCD", "Zaire", "crop()"],
    ["SITH-", "Siam", "crop()"],
    # ["AT-1", "Burgenland", "crop()"], # interlaced
    # ["AT-2", "Carinthia", "crop()"],
    # ["AT-3", "Lower Austria", "crop()"],
    # ["AT-4", "Upper Austria", "crop()"],
    # ["AT-5", "Salzburg", "crop()"],
    # ["AT-6", "Styria", "crop()"],
    # ["AT-7", "Tyrol", "crop()"],
    # ["AT-8", "Vorarlberg", "crop()"],
    # ["AT-9", "Vienna", "crop()"],
    ["BA-SRP", "Republika Srpska", "crop()"],
    ["BE-V", "Flemish Region", "crop()"],
    ["BE-W", "Walloon Region", "crop()"],
    ["BO-C", "Cochabamba", "crop()"],
    ["CA-AB", "Alberta", "crop()"],
    ["CA-NS", "Nova Scotia", "crop()"],
    ["CA-NU", "Nunavut", "crop()"], # wrong
    ["CO-HUI", "Huila Department", "crop()"],
    ["CZ-10", "Prague", "crop()"],
    ["DE-BB", "Brandenburg", "crop()"],
    ["DE-BW", "Baden-Württemberg", "crop()"],
    ["DE-BY", "Bavaria", "crop()"],
    ["DE-HE", "Hesse", "crop()"],
    ["DE-HH", "Hamburg", "crop()"],
    ["DE-MV", "Mecklenburg-Vorpommern", "crop()"],
    ["DE-NW", "North Rhine-Westphalia", "crop()"],
    ["DE-SH", "Schleswig-Holstein", "crop()"],
    ["DE-SL", "Saarland", "crop()"],
    ["DE-SN", "Saxony", "crop()"],
    ["DE-ST", "Saxony-Anhalt", "crop()"],
    ["DE-TH", "Thuringia", "crop()"],
    ["EC-S", "Morona-Santiago Province", "crop()"],
    ["EE-74", "Saare County", "crop()"],
    ["ES-AN", "Andalucía", "crop()"],
    ["ES-CT", "Catalonia", "crop()"],
    ["ES-GA", "Galicia", "crop()"],
    ["ES-LO", "La Rioja", "crop()"],
    ["ES-ML", "Melilla", "crop()"],
    ["ES-NA", "Navarre", "crop()"],
    ["ES-S", "Cantabria", "crop()"],
    ["FM-KSA", "Kosrae", "crop()"],
    ["FM-PNI", "Pohnpei", "crop()"],
    ["FM-TRK", "Chuuk", "crop()"],
    ["FM-YAP", "Yap", "crop()"],
    ["FR-C", "Auvergne", "crop()"],
    ["FR-P", "Lower Normandy", "crop()"],
    ["GB-ENG", "England", "crop()"],
    ["GB-NIR", "Northern Ireland", "crop()"],
    ["GE-SO", "South Ossetia", "crop()"],
    ["IE-L", "Leinster", "crop()"],
    ["IE-U", "Ulster", "crop()"],
    ["IT-23", "Aosta Valley", "crop()"],
    ["IT-25", "Lombardy", "crop()"],
    ["IT-32", "Trentino-Alto Adige", "crop()"],
    ["IT-36", "Friuli-Venezia Giulia", "crop()"],
    ["IT-45", "Emilia Romagna", "crop()"],
    ["IT-52", "Tuscany", "crop()"],
    ["IT-55", "Umbria", "crop()"],
    ["IT-57", "Marche", "crop()"],
    ["IT-65", "Abruzzo", "crop()"],
    ["IT-67", "Molise", "crop()"],
    ["IT-72", "Campania", "crop()"],
    ["IT-77", "Basilicata", "crop()"],
    ["IT-78", "Calabria", "crop()"],
    ["IT-82", "Sicily", "crop()"],
    ["JP-01", "Hokkaido Prefecture", "crop()"],
    ["JP-03", "Iwate Prefecture", "crop()"],
    ["JP-04", "Miyagi Prefecture", "crop()"],
    ["JP-08", "Ibaraki Prefecture", "crop()"],
    ["JP-09", "Tochigi Prefecture", "crop()"],
    ["JP-10", "Gunma Prefecture", "crop()"],
    ["JP-11", "Saitama Prefecture", "crop()"],
    ["JP-12", "Chiba Prefecture", "crop()"],
    ["JP-13", "Tokyo Prefecture", "crop()"],
    ["JP-14", "Kanagawa Prefecture", "crop()"],
    ["JP-15", "Niigata Prefecture", "cut(7, 4, 7, 4); crop()"],
    ["JP-16", "Toyama Prefecture", "crop()"],
    ["JP-18", "Fukui Prefecture", "crop()"],
    ["JP-21", "Gifu Prefecture", "crop()"],
    ["JP-22", "Shizuoka Prefecture", "crop()"],
    ["JP-23", "Aichi Prefecture", "crop()"],
    ["JP-26", "Kyoto Prefecture", "crop()"],
    ["JP-27", "Osaka Prefecture", "crop()"],
    ["JP-29", "Nara Prefecture", "crop()"],
    ["JP-30", "Wakayama Prefecture", "crop()"],
    ["JP-32", "Shimane Prefecture", "crop()"],
    ["JP-33", "Okayama Prefecture", "crop()"],
    ["JP-34", "Hiroshima Prefecture", "crop()"],
    ["JP-35", "Yamaguchi Prefecture", "crop()"], # ?
    ["JP-37", "Kagawa Prefecture", "crop()"],
    ["JP-39", "Kochi Prefecture", "crop()"],
    ["JP-40", "Fukuoka Prefecture", "crop()"],
    ["JP-41", "Saga Prefecture", "crop()"],
    ["JP-42", "Nagasaki Prefecture", "crop()"],
    ["JP-44", "Oita Prefecture", "crop()"],
    ["JP-46", "Kagoshima Prefecture", "crop()"],
    ["JP-47", "Okinawa Prefecture", "crop()"],
    ["KM-A", "Anjouan", "crop()"],
    ["MD-TR", "Transnistria", "crop()"],
    ["MX-AGU", "Aguascalientes", "crop()"],
    ["MX-BCN", "Baja California", "crop()"],
    ["MX-BCS", "Baja California Sur", "crop()"],
    ["MX-CAM", "Campeche", "crop()"],
    ["MX-CHH", "Chihuahua", "crop()"],
    ["MX-CHP", "Chiapas", "crop()"],
    ["MX-COA", "Coahuila", "crop()"],
    ["MX-COL", "Colima", "crop()"],
    ["MX-DUR", "Durango", "crop()"],
    ["MX-GRO", "Guerrero", "crop()"],
    ["MX-GUA", "Guanajuato", "crop()"],
    ["MX-JAL", "Jalisco", "crop()"],
    ["MX-MEX", "State of Mexico", "crop()"],
    ["MX-MIC", "Michoacán", "crop()"],
    ["MX-MOR", "Morelos", "crop()"],
    ["MX-NAY", "Nayarit", "crop()"],
    ["MX-NLE", "Nuevo León", "crop()"],
    ["MX-OAX", "Oaxaca", "crop()"],
    ["MX-PUE", "Puebla", "crop()"],
    ["MX-QUE", "Querétaro", "crop()"],
    ["MX-ROO", "Quintana Roo", "crop()"],
    ["MX-SIN", "Sinaloa", "crop()"],
    ["MX-SLP", "San Luis Potosí", "crop()"],
    ["MX-SON", "Sonora", "crop()"],
    ["MX-TAB", "Tabasco", "crop()"],
    ["MX-TAM", "Tamaulipas", "crop()"],
    ["MX-TLA", "Tlaxcala", "crop()"],
    ["MX-VER", "Veracruz", "crop()"],
    ["MX-YUK", "Yucatán", "crop()"],
    ["MX-ZAC", "Zacatecas", "crop()"],
    ["NL-GE", "Gelderland", "crop()"],
    ["NL-GR", "Groningen", "crop()"],
    ["NL-NH", "North Holland", "crop()"],
    ["NL-OV", "Overijssel", "crop()"],
    ["NL-ZE", "Zeeland", "crop()"],
    ["PL-PM", "Pomeranian Voivodeship", "crop()"],
    ["RS-KM", "Kosovo", "crop()"],
    ["RS-VO", "Vojvodina", "crop()"],
    ["RU-AL", "Altai", "crop()"], # spelling?
    ["RU-AST", "Astrakhan Oblast", "crop()"],
    ["RU-AMU", "Amur Oblast", "crop()"],
    ["RU-BA", "Bashkortostan", "crop()"],
    ["RU-CHE", "Chelyabinsk Oblast", "crop()"],
    ["RU-CU", "Chuvashia", "crop()"],
    ["RU-DA", "Dagestan", "crop()"],
    ["RU-IN", "Ingushetia", "crop()"],
    ["RU-KB", "Kabardino-Balkaria", "crop()"],
    ["RU-KC", "Karachay-Cherkessia", "crop()"],
    ["RU-KGN", "Kurgan Oblast", "crop()"],
    ["RU-KL", "Kalmykia", "crop()"],
    ["RU-KO", "Komi", "crop()"],
    ["RU-KR", "Karelia", "crop()"],
    ["RU-KYA", "Krasnoyarsk Krai", "crop()"],
    ["RU-ME", "Mari El", "crop()"],
    ["RU-MO", "Mordovia", "crop()"],
    ["RU-MOW", "Moscow", "crop()"],
    ["RU-NIZ", "Nizhni Novgorod Oblast", "crop()"], 
    ["RU-RYA", "Ryazan Oblast", "crop()"], 
    ["RU-SA", "Sakha", "crop()"],
    ["RU-SAK", "Sakhalin Oblast", "crop()"],
    ["RU-SAM", "Samara Oblast", "crop()"],
    ["RU-SE", "North Ossetia-Alania", "crop()"],
    ["RU-SPE", "Saint Petersburg", "crop()"],
    ["RU-SVE", "Sverdlovsk Oblast", "crop()"],
    ["RU-TA", "Tatarstan", "crop()"],
    ["RU-TAM", "Tambov Oblast", "crop()"],
    ["RU-TUL", "Tula Oblast", "crop()"],
    ["RU-ULY", "Ulyanovsk Oblast", "crop()"],
    ["RU-YAR", "Yaroslavl Oblast", "crop()"],
    ["RU-YEV", "Jewish Autonomous Oblast", "crop()"],
    ["SK-PV", "Prešov Region", "crop()"],
    ["SK-TC", "Trenčín Region", "crop()"],
    ["SK-TR", "Trnava Region", "crop()"],
    ["SM-03", "Domagnano", "crop()"], # ?
    ["SO-SO-", "Somaliland", "crop()"],
    ["SV-SO", "Sonsonate", "crop()"],
    ["TW-TPE", "Taipei", "crop()"],
    ["UM-95", "Palmyra Atoll", "crop()"],
    ["US-AZ", "Arizona", "crop()"],
    ["US-ID", "Idaho", "crop()"],
    ["US-IL", "Illinois", "cut(2, 2, 2, 2); crop()"],
    ["US-KS", "Kansas", "crop()"],
    ["US-KY", "Kentucky", "crop()"],
    ["US-MA", "Massachusetts", "crop()"],
    ["US-ME", "Maine", "crop()"],
    ["US-MI", "Michigan", "crop()"],
    ["US-MN", "Minnesota", "crop()"],
    ["US-MO", "Missouri", "crop()"],
    ["US-NE", "Nebraska", "crop()"],
    ["US-NH", "New Hampshire", "crop()"],
    ["US-NJ", "New Jersey", "crop()"],
    ["US-NJ", "New Mexico", "crop()"],
    ["US-NJ", "New York", "crop()"],
    ["US-OK", "Oklahoma", "crop()"],
    ["US-RI", "Rhode Island", "crop()"],
    ["US-SD", "South Dakota", "crop()"],
    ["US-UT", "Utah", "crop()"],
    ["US-VA", "Virginia", "crop()"],
    ["US-VT", "Vermont", "crop()"],
    ["US-WA", "Washington", "crop()"],
    ["US-WI", "Wisconsin", "crop()"],
    # crop (scandinavia)
    ["AX", "Åland Islands", "crop(525)"],
    ["DK", "Denmark", "crop(left)"],
    ["FI", "Finland", "crop(650)"],
    ["IS", "Iceland", "crop(left)"],
    ["FO", "Faroe Islands", "crop(400)"],
    ["NO", "Norway", "crop(left)"],
    ["SE", "Sweden", "crop(600)"],
    # crop (left)
    ["AW", "Aruba", "crop(left)"],
    ["BY", "Belarus", "crop(left)"],
    ["CL", "Chile", "crop(left)"],
    ["CR", "Costa Rica", "crop(left)"],
    ["ES", "Spain", "crop(left)"],
    ["GR", "Greece", "crop(left)"],
    ["LR", "Liberia", "crop(left)"],
    ["MG", "Madagascar", "crop(left)"],
    ["NR", "Nauru", "crop(left)"],
    ["PH", "Philippines", "crop(left)"],
    ["SI", "Slovenia", "crop(left)"],
    ["TG", "Togo", "crop(left)"],
    ["TM", "Turkmenistan", "crop(left)"],
    ["UY", "Uruguay", "crop(left)"],
    ["UZ", "Uzbekistan", "crop(left)"],
    ["DE-HB", "Bremen", "crop(left)"],
    ["ES-O", "Asturias", "crop(left)"],
    ["ES-VC", "Valencian Community", "crop(left)"],
    ["IT-34", "Veneto", "crop(left); copy(0, 0, 214, 217, 217, 217, 0, 0)"],
    ["JP-20", "Nagano Prefecture", "crop(left)"],
    ["KM-G", "Grande Comore", "crop(left)"], # ?
    ["NL-FL", "Flevoland", "crop(left)"], # ?
    # ["NL-LI", "Limburg", "crop(left)"],
    ["NL-NB", "North Brabant", "crop(left)"], # ?
    ["NL-UT", "Utrecht", "crop(left)"],
    ["NL-ZH", "South Holland", "crop(left)"], # wrong
    ["RU-KGD", "Kaliningrad Oblast", "crop(left)"],
    ["RU-BU", "Buryatia", "crop(left)"],
    ["RU-CE", "Chechnya", "crop(left)"],
    ["RU-KHA", "Khabarovsk Krai", "crop(left)"],
    ["RU-KK", "Khakassia", "crop(left)"],
    ["RU-MOS", "Moscow Oblast", "crop(left)"],
    ["RU-TU", "Tuva", "crop(left)"],
    ["RU-VOR", "Voronezh Oblast", "crop(left)"],
    ["SK-BC", "Banská Bystrica Region", "crop(left)"],
    ["SK-BL", "Bratislava Region", "crop(left)"],
    ["SK-KI", "Košice Region", "crop(left)"],
    ["SK-NI", "Nitra Region", "crop(left)"],
    ["SK-ZI", "Žilina Region", "crop(left)"],
    ["US-GA", "Georgia ", "crop(left)"],
    ["US-MS", "Mississippi", "crop(left)"],
    ["US-NC", "North Carolina", "crop(left)"],
    ["US-NV", "Nevada", "crop(left)"],
    ["US-TX", "Texas", "crop(left)"],
    # crop (right)
    ["RW", "Rwanda", "crop(right)"],
    ["ZM", "Zambia", "crop(right)"],
    ["US-TN", "Tennessee", "crop(right); copy(100, 0, 362, 300, 262, 300, 0, 0)"],
    # crop (irregular)
    ["AE", "United Arab Emirates", "crop(400)"],
    ["AZ", "Azerbaijan", "crop(583)"], # same padding
    ["BA", "Bosnia and Herzegovina", "crop(515)"],
    ["BD", "Bangladesh", "crop(450)"],
    ["BH", "Bahrain", "crop(325)"],
    ["BJ", "Benin", "crop(600)"],
    ["CN", "China", "crop(757)"], # same padding
    ["CV", "Cape Verde", "crop(191)"],
    ["GL", "Greenland", "crop(350)"],
    ["KP", "North Korea", "crop(480)"],
    ["NC", "New Caledonia", "crop(300)"],
    ["PS", "Palestine", "crop(300)"],
    ["PT", "Portugal", "crop(240)"],
    ["PW", "Palau", "crop(350)"],
    ["QA", "Qatar", "crop(243)"],
    ["RE", "Réunion", "crop(281)"], # same padding
    ["RS", "Serbia", "crop(320)"],
    ["PM", "Saint Pierre and Miquelon", "crop(668)"],
    ["SG", "Singapore", "crop(788)"], # same padding
    ["TR", "Turkey", "crop(406)"],
    ["MIUM", "Midway Islands", "crop(456)"],
    ["YDYE", "South Yemen", "crop(600)"],
    ["CY-NC", "Northern Cyprus", "crop(406)"], # same padding
    ["DE-BE", "Berlin", "crop(416)"], # fixme: this is just a guess, check coat of arms
    ["DE-NI", "Lower Saxony", "crop(420)"],
    ["ES-AR", "Aragón", "crop(321)"],
    ["ES-EX", "Extremadura", "crop(251)"],
    ["JP-07", "Fukushima Prefecture", "crop(189)"],
    ["JP-31", "Tottori Prefecture", "crop(480)"],
    ["JP-38", "Ehime Prefecture", "crop(161)"],
    ["PT-20", "Azores ", "crop(299); copy(0, 49, 140, 140, 140, 91, 0, 49)"],
    ["US-CO", "Colorado", "crop(760)"],
    # extend
    ["AD", "Andorra", "extend()"],
    ["AF", "Afghanistan", "extend()"],
    ["AQ", "Antarctica", "extend()"],
    ["BB", "Barbados", "extend()"],
    ["BE", "Belgium", "extend()"],
    ["BL", "Saint Barthélemy", "extend()"],
    ["BR", "Brazil", "extend()"],
    ["CA", "Canada", "extend()"],
    ["CC", "Cocos Islands", "extend()"],
    ["CI", "Côte d'Ivoire", "extend()"],
    ["CM", "Cameroon", "extend()"],
    ["FR", "France", "extend()"],
    ["GN", "Guinea", "extend()"],
    ["GT", "Guatemala", "extend()"],
    ["IC", "Canary Islands", "extend()"],
    ["IE", "Ireland", "extend()"],
    ["IT", "Italy", "extend()"],
    ["KR", "South Korea", "extend()"],
    ["MD", "Moldova", "extend()"],
    ["ML", "Mali", "extend()"],
    ["MN", "Mongolia", "extend()"],
    ["MX", "Mexico", "cut(2, 0, 2, 0); extend()"],
    ["NF", "Norfolk Island", "extend()"],
    ["NG", "Nigeria", "extend()"],
    ["PE", "Peru", "extend()"],
    ["PK", "Pakistan", "extend()"],
    ["RO", "Romania", "extend()"],
    ["SN", "Senegal", "extend()"],
    ["SZ", "Swaziland", "extend()"],
    ["TD", "Chad", "extend()"],
    ["YT", "Mayotte", "cut(2, 2, 2, 2); extend()"],
    ["VC", "Saint Vincent and the Grenadines", "extend()"],
    ["VI", "United States Virgin Islands", "extend()"],
    ["JTUM", "Johnston Island", "extend()"],
    ["RHZW", "Rhodesia", "cut(0, 1, 0, 1); extend()"],
    ["KOHH-", "Korea", "extend()"],
    ["AU-ACT", "Australian Capital Territory", "extend()"], # ?
    ["AU-NT", "Northern Territory", "extend()"], # ?
    ["BA-BIH", "Federation of Bosnia and Herzegovina", "cut(2, 3, 2, 3); extend()"],
    ["BR-PE", "Pernambuco", "extend()"],
    ["CA-NB", "New Brunswick", "cut(0, 1, 0, 1); extend()"],
    ["CA-PE", "Prince Edward Island", "extend()"], # wrong
    ["CA-NT", "Northwest Territories", "extend()"],
    ["CA-YT", "Yukon", "extend()"],
    ["ES-CM", "Castile-La Mancha", "extend()"],
    ["ES-CN", "Canary Islands", "extend()"],
    ["ES-M", "Community of Madrid", "extend()"],
    ["FR-B", "Aquitaine", "cut(0, 2, 0, 2); extend()"],
    ["FR-J", "Île-de-France", "cut(0, 1, 0, 1); extend()"],
    ["FR-H", "Corsica", "extend()"],
    ["GB-WLS", "Wales", "extend()"],
    ["IE-C", "Connacht", "cut(0, 1, 0, 1); extend()"],
    ["IE-M", "Munster", "extend()"],
    ["IT-42", "Liguria", "extend()"],
    # ["IT-62", "Lazio", "extend()"], # fixme: interlaced
    ["IT-75", "Apulia", "extend()"],
    ["JP-02", "Aomori Prefecture", "extend()"],
    ["JP-05", "Akita Prefecture", "extend()"],
    ["JP-06", "Yamagata Prefecture", "extend()"],
    ["JP-17", "Ishikawa Prefecture", "extend()"],
    ["JP-19", "Yamanashi Prefecture", "extend()"],
    ["JP-25", "Shiga Prefecture", "cut(0, 1, 0, 1); extend()"],
    ["JP-28", "Hyogo Prefecture", "extend()"],
    ["JP-36", "Tokushima Prefecture", "extend()"],
    ["JP-45", "Miyazaki Prefecture", "extend()"],
    ["MX-HID", "Hidalgo", "extend()"],
    ["NL-DR", "Drenthe", "extend()"],
    ["PT-30", "Madeira", "extend()"],
    ["RU-AD", "Adygeya", "extend()"],
    ["UM-76", "Navassa Island", "extend()"],
    ["UA-05", "Vinnytsia Oblast", "extend()"],
    ["US-AK", "Alaska", "extend()"],
    ["US-AR", "Arkansas", "extend()"],
    ["US-CA", "California", "extend()"],
    ["US-CT", "Connecticut", "extend()"],
    ["US-DC", "District of Columbia", "extend()"],
    ["US-DE", "Delaware", "extend()"],
    ["US-IA", "Iowa", "cut(2, 2, 2, 2); extend()"],
    ["US-IN", "Indiana", "extend()"],
    ["US-LA", "Lousiana", "extend()"],
    ["US-MT", "Montana", "extend()"],
    ["US-ND", "North Dakota", "extend()"], # check (subjective)...
    ["US-OR", "Oregon", "extend()"],
    ["US-PA", "Pennsylvania", "extend()"],
    ["US-SC", "South Carolina", "extend()"],
    # ["UY-DU", "Durazno", "extend()"], # interlaced
    # extend (commonwealth)
    ["AI", "Anguilla", "extend(right, left)"],
    ["AU", "Australia", "extend(right, left)"],
    ["BM", "Bermuda", "extend(right, left)"],
    ["CK", "Cook Islands", "extend(right, left)"],
    ["FJ", "Fiji", "extend(right, left)"],
    ["FK", "Falkland Islands", "extend(right, left)"],
    ["GS", "South Georgia and the South Sandwich Islands", "extend(right, left)"],
    ["IO", "British Indian Ocean Territory", "extend(right, left)"],
    ["KY", "Cayman Islands", "extend(right, left)"],
    ["MS", "Montserrat", "extend(right, left)"],
    ["NZ", "New Zealand", "extend(right, left)"],
    ["NU", "Niue", "extend(right, left)"],
    ["PN", "Pitcairn", "extend(right, left)"],
    ["SH", "Saint Helena", "extend(right, left)"],
    ["TA", "Tristan da Cunha", "extend(right, left)"],
    ["TC", "Turks and Caicos Islands", "extend(right, left)"],
    ["TF", "French Southern Territories", "extend(right, left); copy(0, 158, 242, 162, 242, 4, 0, 96)"],
    ["TV", "Tuvalu", "extend(right, left)"],
    ["VG", "British Virgin Islands", "extend(right, left)"],
    ["WF", "Wallis and Futuna", "extend(right, left); copy(0, 395, 605, 405, 605, 10, 0, 240)"],
    ["BQAQ", "British Antarctic Territory", "extend(right, left)"],
    ["GEHH", "Gilbert and Ellice Islands", "extend(right, left)"],
    ["AU-NSW", "New South Wales", "extend(right, left)"],
    ["AU-QLD", "Queensland", "extend(right, left)"],
    ["AU-SA", "South Australia", "extend(right, left)"],
    ["AU-TAS", "Tasmania", "extend(right, left)"],
    ["AU-VIC", "Victoria", "extend(right, left)"],
    ["CA-MB", "Manitoba", "extend(right, left)"],
    ["CA-ON", "Ontario", "extend(right, left)"],
    ["US-HI", "Hawaii", "extend(); copy(1200, 160, 1280, 240, 1280, 320, 0, 0); copy(1200, 160, 1280, 240, 1280, 320, 0, 960)"],
    # extend (irregular)
    ["BT", "Bhutan", "extend(left, right)"],
    ["CX", "Christmas Island", "cut(1, 1, 1, 1); extend(right, left)"],
    ["PG", "Papua New Guinea", "extend(right, left)"],
    # resize
    ["CG", "Republic of the Congo", "resize()"],
    ["CZ", "Czech Republic", "resize()"],
    ["GY", "Guyana", "resize()"],
    ["JM", "Jamaica", "resize()"],
    ["SC", "Seychelles", "resize()"],
    ["TT", "Trinidad and Tobago", "resize()"],
    ["TZ", "Tanzania", "resize()"],
    ["ZA", "South Africa", "resize()"],
    ["AZ-NK", "Nagorno-Karabakh", "resize()"],
    ["CA-BC", "British Columbia", "resize()"],
    ["CA-NL", "Newfoundland and Labrador", "resize()"], # wrong
    ["FR-A", "Alsace", "resize()"], # ?
    ["GB-SCT", "Scotland", "resize()"],
    ["NL-FR", "Friesland", "resize()"], # ?
    ["US-AL", "Alabama", "resize()"],
    # cut, resize
    ["BS", "Bahamas", "cut(0, 0, 100, 0); resize()"],
    ["KW", "Kuwait", "cut(0, 0, 300, 0); resize()"],
    ["SD", "Sudan", "cut(0, 0, 200, 0); resize()"],
    # resize, circle
    ["BI", "Burundi", "resize(); copy(265, 105, 535, 375, 272, 272, 104, 104, circle)"],
    ["MK", "Macedonia", "resize(); copy(329, 129, 471, 271, 142, 142, 129, 129, circle)"],
    ["US-FL", "Florida", "cut(0, 1, 0, 1); resize(); copy(246, 120, 504, 378, 258, 258, 120, 120, circle)"],
    # border
    ["GU", "Guam", "border(37)"],
    ["ME", "Montenegro", "border(16)"],
    ["MT", "Malta", "border(210)"],
    ["MV", "Maldives", "border(120)"],
    ["SKIN", "Sikkim", "border(54)"],
    ["IT-21", "Piedmont", "border(40)"],
    ["RU-PNZ", "Penza Oblast", "border(125)"], # wrong
    ["US-WV", "West Virginia", "border(44)"],
    ["US-WY", "Wyoming", "border(75)"],
    # corner
    ["GW", "Guinea-Bissau", "corner(200)"],
    ["LI", "Liechtenstein", "corner(200)"],
    ["MM", "Myanmar", "corner(195)"],
    ["PA", "Panama", "corner(112)"],
    ["SY", "Syria", "corner(240)"],
    ["TO", "Tonga", "corner(200)"],
    ["TW", "Taiwan", "corner(225)"],
    ["WS", "Samoa", "corner(216)"],
    ["SUHH", "Soviet Union", "corner(100)"],
    ["CA-SK", "Saskatchewan", "corner(189)"], # check ...
    ["ES-CL", "Castile and León", "corner(162)"],
    ["ES-MU", "Region of Murcia", "corner(125)"],
    # cross
    ["GB", "United Kingdom", "cross(200, resize, 400)"],
    ["GE", "Georgia", "cross(120, crop)"],
    ["MQ", "Martinique", "cross(74, crop)"],
    ["CA-QC", "Quebec", "cross(100, crop)"],
    ["ES-BA", "Basque Country", "resize(); copy(457, 0, 543, 560, 86, 560, 237, 0)"],
    ["IT-88", "Sardinia", "cut(0, 0, 1, 1); cross(80, crop)"], # check if correct
    ["RU-BEL", "Belgorod Oblast", "cross(44, crop)"],
    # ["ES-BA", "Basque Country", "cross(86, resize, 420)"], # fixme: the 420 are just an estimate, there must be a formula
    # symbol (rectangle)
    ["MY", "Malaysia", "crop(416); copy(0, 0, 64, 64, 256, 256, 0, 0); copy(88, 32, 358, 224, 203, 144, 26, 56)"], # *3/4
    ["US", "United States", "crop(469); copy(134, 0, 484, 350, 350, 350, 0, 0); copy(0, 0, 10, 10, 10, 350, 0, 0)"],
    ["ES-IB", "Balearic Islands", "resize(); copy(1, 1, 374, 249, 248, 166, 1, 42)"], # *2/3
    ["GE-AB", "Abkhazia", "crop(233); copy(0, 0, 40, 40, 120, 120, 0, 0); copy(0, 0, 212, 120, 120, 68, 0, 26)"],
    # symbol (triangle)
    ["CU", "Cuba", "cut(0, 0, 108, 0); resize(); copy(0, 120, 40, 260, 70, 140, 20, 120); copy(57, 140, 173, 260, 86, 90, 33, 157)"], # *3/4
    ["DJ", "Djibouti", "resize(); copy(77, 160, 154, 233, 77, 73, 51, 160)"], # *1 ... wrong
    ["ER", "Eritrea", "resize(); copy(0, 104, 50, 392, 144, 288, 50, 104); copy(100, 104, 388, 392, 216, 216, 50, 142)"], # *3/4,
    ["JO", "Jordan", "resize(); copy(71, 128, 114, 170, 43, 42, 35, 128)"], # *1
    ["KM", "Comoros", "resize(); copy(0, 80, 8, 220, 60, 140, 8, 80); copy(16, 82, 112, 218, 72, 102, 16, 99)"], # * 3/4
    ["MZ", "Mozambique", "cut(0, 0, 112, 0); resize(); copy(290, 290, 310, 310, 180, 300, 0, 150, circle); copy(0, 160, 280, 440, 210, 210, 0, 195, circle)"], # *3/4
    ["PR", "Puerto Rico", "resize(); copy(0, 200, 78, 391, 128, 191, 52, 200); copy(78, 200, 269, 391, 143, 143, 52, 228)"], # *3/4 ... wrong
    ["TL", "Timor-Leste", "resize(); copy(0, 290, 20, 310, 110, 200, 20, 200); copy(45, 200, 246, 400, 100, 100, 30, 250)"], # *1/2
    ["VU", "Vanuatu", "cut(0, 0, 50, 0); resize(); copy(0, 270, 30, 300, 90, 180, 30, 195); copy(50, 185, 210, 385, 120, 150, 30, 210)"], # *3/4
    ["ZW", "Zimbabwe", "cut(0, 0, 336, 0); resize()"], # *1/2 ... still wrong
    ["WKUM", "Wake Island", "crop(left)"], # still wrong
    # ["YDYE", "South Yemen", "resize(); copy(0, 550, 100, 650, 200, 300, 92, 450); copy(139, 450, 439, 750, 226, 226, 92, 487)"], # * 3/4
    # symbol (diagonal)
    ["CD", "Democratic Republic of the Congo", "resize(); copy(0, 0, 100, 100, 180, 240, 20, 20); copy(36, 41, 252, 257, 162, 162, 41, 41)"], # *3/4
    ["MH", "Marshall Islands", "resize(); copy(0, 0, 50, 50, 97, 185, 9, 17, circle); copy(17, 17, 202, 202, 139, 139, 17, 17, circle)"], # *3/4
    ["SB", "Solomon Islands", "resize(); copy(0, 0, 10, 10, 143, 275, 16, 8); copy(35, 8, 315, 283, 210, 206, 18, 18)"], # *3/4
    ["NA", "Namibia", "resize(); copy(0, 65, 50, 265, 140, 200, 50, 65); copy(80, 65, 280, 265, 200, 200, 33, 33)"],
    # symbol (other)
    ["AG", "Antigua and Barbuda", "resize(); copy(147, 0, 603, 196, 304, 131, 98, 65); copy(147, 0, 603, 20, 304, 80, 98, 0)"],
    ["CF", "Central African Republic", "crop(); copy(50, 0, 350, 200, 300, 200, 0, 0)"],
    ["EH", "Western Sahara", "resize(); copy(340, 134, 460, 266, 120, 132, 140, 134)"], # *1
    ["GQ", "Equatorial Guinea", "resize(); copy(312, 168, 438, 332, 126, 164, 187, 168)"],
    ["JE", "Jersey", "resize(); copy(234, 357, 366, 589, 132, 232, 234, 11, circle); copy(392, 11, 608, 243, 162, 174, 219, 11, circle)"], # *3/4
    ["KZ", "Kazakhstan", "border(180); copy(670, 0, 1490, 1000, 820, 1000, 180, 0)"],
    ["OM", "Oman", "crop(400); copy(0, 300, 200, 600, 200, 300, 0, 0); copy(60, 32, 238, 206, 132, 132, 34, 34)"], # *3/4
    ["SK", "Slovakia", "crop(left); copy(0, 140, 540, 460, 540, 320, 30, 140)"],
    ["ST", "São Tomé and Príncipe", "resize(); copy(884, 296, 1164, 728, 210, 324, 407, 350); copy(1396, 296, 1676, 728, 210, 324, 663, 350)"], # *3/4
    ["VE", "Venezuela", "crop(); copy(0, 0, 200, 200, 200, 200, 0, 0)"],
    ["BYAA", "Byelorussian Soviet Socialist Republic", "crop(left); copy(92, 0, 209, 200, 117, 200, 66, 0)"], # like soviet union
    ["DE-RP", "Rhineland-Palatinate", "crop(left); copy(0, 0, 250, 400, 250, 400, 10, 0)"],
    ["JP-24", "Mie Prefecture", "extend(); copy(0, 0, 506, 400, 506, 400, 47, 100)"],
    ["JP-43", "Kumamoto Prefecture", "extend(); copy(0, 0, 720, 600, 720, 600, 90, 150); copy(0, 0, 90, 90, 90, 900, 0, 0)"],
    # other
    ["AS", "American Samoa", "special()"], # *3/4
    ["GD", "Grenada", "border(42); copy(215, 115, 285, 185, 70, 70, 115, 115, circle); copy(59, 120, 99, 180, 40, 60, 50, 120); copy(54, 0, 170, 42, 116, 42, 0, 0); copy(330, 0, 446, 42, 116, 42, 184, 0); copy(54, 258, 170, 300, 116, 42, 0, 258); copy(330, 258, 446, 300, 116, 42, 184, 258)"],
    ["GP", "Guadeloupe", "crop(right); copy(0, 70, 292, 330, 292, 260, 54, 70)"],
    ["LK", "Sri Lanka", "cut(359, 0, 0, 0); border(108); copy(112, 100, 528, 398, 416, 298, 42, 100)"],
    ["NP", "Nepal", "resize(); copy(27, 744, 28, 745, 770, 770, 0, 0); copy(27, 743, 28, 744, 726, 726, 22, 22); copy(27, 742, 28, 743, 724, 724, 23, 23); copy(53, 232, 262, 354, 209, 122, 280, 232); copy(45, 446, 270, 670, 225, 224, 272, 446, circle)"],
    ["TK", "Tokelau", "cut(0, 0, 0, 2); resize(); copy(0, 0, 100, 100, 150, 400, 0, 0); copy(44, 41, 287, 361, 182, 240, 44, 41)"], # *3/4
    ["MF", "Saint Martin", "construct()"],
    ["US-MD", "Maryland", "resize(); copy(375, 0, 450, 250, 75, 250, 250, 0); copy(375, 0, 450, 250, 75, 250, 0, 250); copy(515, 0, 610, 250, 95, 250, 328, 0); copy(515, 0, 610, 250, 95, 250, 77, 250); copy(675, 0, 750, 250, 75, 250, 425, 0); copy(675, 0, 750, 250, 75, 250, 175, 250)"],
    ["US-OH", "Ohio", "crop(left); copy(59, 149, 61, 151, 300, 300, 0, 0); copy(0, 0, 300, 300, 300, 300, 0, 0)"], # wrong
    # other flag
    ["AC", "Ascension Island", "United Kingdom"],
    ["BV", "Bouvet Island", "Norway"],
    ["CP", "Clipperton Island", "France"],
    ["DG", "Diego Garcia", "British Indian Ocean Territory"],
    ["HM", "Heard Island and McDonald Islands", "Australia"],
    ["SJ", "Svalbard and Jan Mayen", "Norway"],
    ["UK", "United Kingdom", "United Kingdom"],
    ["UM", "United States Minor Outlying Islands", "United States"],
    ["AIDJ", "French Afar and Issas", "France"],
    ["BUMM", "Burma", "Myanmar"],
    ["CSHH", "Czechoslovakia", "Czech Republic"],
    ["CTKI", "Canton and Enderbury Islands", "Gilbert and Ellice Islands"],
    ["DYBJ", "Dahomey", "Benin"],
    ["FQHH", "French Southern and Antarctic Territories", "French Southern Territories"],
    ["FXFR", "France, Metropolitan", "France"],
    ["NQAQ", "Dronning Maud Land", "Norway"],
    ["PUUM", "United States Miscellaneous Pacific Islands", "United States"],
    ["TPTL", "East Timor", "Timor-Leste"],
    ["VDVN", "North Vietnam", "Vietnam"],
    ["ES-CE", "Ceuta", "Ceuta and Melilla"],
    ["FR-CP", "Clipperton", "France"]
]

translate = {
    "Ceuta and Melilla": "Ceuta",
    "China": "People's Republic of China",
    "Congo": "Republic of the Congo",
    "Holy See": "Vatican City",
    "Neutral Zone": "United Nations",
    "Pacific Islands": "Trust Territory of the Pacific Islands",
    "Taiwan": "Republic of China",
    "Yugoslavia": "Socialist Federal Republic of Yugoslavia"
}
flags_ = {
    "Åland Islands": "Flag of %C5land", # unicode bug in getUrlUnicode ... sha.sha(url).hexdigest() doesn't take unicode urls
    "Altai": "Flag of Altai Republic",
    "Aquitaine": "Aquitaine flag",
    "Arizona": "Flag of Arizona",
    "Australian Capital Territory": "Flag of the Australian Capital Territory",
    "Auvergne": "Auvergne flag",
    "Baden-Württemberg": "Flag of Baden-W%FCrttemberg", # see Åland
    "Basque Country": "Flag of the Basque Country",
    "Burgenland": "Burgenland_Landesflagge.PNG",
    "Castile and León": "Bandera de Castilla y Le%F3n", # see Åland
    "Chechnya": "Flag of the Chechen Republic",
    "Cochabamba": "Flag of cochabamba",
    "Domagnano": "Castello_di_Domagnano.jpg",
    "Durazno": "Flag_of_Durazno_Department.png",
    "European Union": "Flag of Europe",
    "Federation of Bosnia and Herzegovina": "Flag of the Federation of Bosnia and Herzegovina",
    "French Guiana": "Flag of French Guiana",
    "Georgia ": "Flag of Georgia (U.S. state)", # fix this...
    "Guadeloupe": "Flag of Guadeloupe (UPLG)",
    "Guanajuato": "Mexico_stateflags_Guanajuato.png",
    "Hokkaido Prefecture": "Flag of Hokkaido Prefecture", # fix this ...
    "Honduras": "Flag of Honduras", # someone temporarily linked to a JPEG, so this exception can hopefully be removed later
    "Île-de-France": "%CEle-de-France flag", # see Åland
    "Ishikawa Prefecture": "Flag of Ishikawa", # fix this ...
    "Jewish Autonomous Oblast": "Flag of the Jewish Autonomous Oblast",
    "Johnston Island": "Flag of Johnston Atoll (local)",
    "Kagoshima Prefecture": "Flag of Kagoshima.png", # fix this ...
    "Kanagawa Prefecture": "Flag of Kanagawa", # fix this ...
    "Kochi Prefecture": "Flag of Kochi", # fix this ...
    "Korea": "Flag of Korea 1882",
    "Kosovo": "Flag of Kosovo",
    "Kosrae": "Flag of Kosrae.png",
    "Krasnoyarsk Krai": "KrasnoyarskKray-Flag",
    "La Rioja": "Flag of La Rioja (with coat of arms)",
    "Lower Normandy": "Normandy-flag.gif",
    "Mayotte": "Flag of Mayotte (local)",
    "Midway Islands": "Flag of the Midway Islands (local)",
    "Miyagi Prefecture": "Flag of Miyagi", # fix this ...
    "Morona-Santiago Province": "Morona-Santiago Flag.png",
    "Moscow Oblast": "Flag of Moscow Oblast.png",
    "Navassa Island": "Flag of Navassa Island (local)",
    "New Caledonia": "Kanak flag",
    "New Hebrides": "Flag of Anglo-French Joint Naval Commission",
    "Niigata Prefecture": "Prefectural_Logo_of_Niigata.png",
    "Nizhni Novgorod Oblast": "Flag of Nizhny Novgorod Region",
    "North Ossetia-Alania": "Flag of North Ossetia",
    "Northern Ireland": "Ulster banner",
    "Northern Territory": "Flag of the Northern Territory",
    "Northwest Territories": "Flag of the Northwest Territories",
    "Oita Prefecture": "Flag of Oita", # fix this ...
    "Okayama Prefecture": "Flag of Okayama", # fix this ...
    "Osaka Prefecture": "Flag of Osaka", # fix this ...
    "Palmyra Atoll": "Flag of Palmyra Atoll (local)",
    "Penza Oblast": "Flag of Penza Oblast.png",
    "Pohnpei": "Flag of Pohnpei.png",
    "Pomeranian Voivodeship": "POL wojew%F3dztwo pomorskie flag alt", # see Åland
    "Réunion": "Drapo nasion.jpg",
    "Ryazan Oblast": "Flag of Ryazan Oblast.png",
    "Saarland": "Flag of Saarland.png",
    "Saga Prefecture": "Flag of Saga", # fix this ...
    "Saint Barthélemy": "Flag of Saint Barthelemy (local)",
    "Saint Martin": "StMartinCoat.png",
    "Saint Petersburg": "Flag of Saint Petersburg Russia",
    "Sikkim": "Sikkimflag",
    "Shimane Prefecture": "Flag of Shimane", # fix this ...
    "Shizuoka Prefecture": "Flag of Shizuoka", # fix this ...
    "Sonsonate": "Flag of Sonsonate.png",
    "State of Mexico": "Mexico_stateflags_Estado_de_Mexico.png",
    "Tochigi Prefecture": "Flag of Tochigi", # fix this ...
    "Tokushima Prefecture": "Flag of Tokushima", # fix this ...
    "Tottori Prefecture": "Flag of Tottori", # fix this ...
    "Toyama Prefecture": "Flag of Toyama", # fix this ...
    "Tokelau": "Flag of Tokelau", # someone linked a JPEG
    "Ulyanovsk Oblast": "Flag of Ulyanovsk Oblast.png",
    "Utrecht": "Utrecht (province)-Flag",
    "Victoria": "Flag of Victoria (Australia)",
    "Wake Island": "Flag of Wake Island",
    "Yamanashi Prefecture": "Flag of Yamanashi prefecture.png",
    "Yaroslavl Oblast": "Flag of Yaroslavl Oblast.png"
}

def getFlagUrl(country):
    if flags_.has_key(country):
        flag = flags_[country]
        if flags_[country][-4] != ".":
            flag = "%s.svg" % flag
    else:
        if translate.has_key(country):
            country = translate[country]
        # country = country.replace("Å", "A").replace("é", "e")
        url = "http://en.wikipedia.org/wiki/%s" % country.replace(" ", "_")
        print "reading", url
        html = getUrlUnicode(url)
        country = findRe(html, "<h1 .*?>(.*?)</h1?>").encode("utf-8")
        url = "http://en.wikipedia.org/w/index.php?title=%s&action=edit" % country.replace(" ", "_")
        print "reading", url
        html = getUrlUnicode(url)
        flag = findRe(html, "image_flag\s*?=\s*?(.*?\.svg)") # Gilbert and Ellice Islands has an empty "flag =" entry, so we can't just find "flag" 
        if not flag:
            flag = findRe(html, "flag\s*?=\s*?(.*?\.svg)")
        if not flag:
            flag = findRe(html, "flag\s*?=\s*?(.*?\.png)") # Panama Canal Zone has a PNG
        if not flag:
            no_flag.append(country)
            flag = "Flag of %s.svg" % country
    url = "http://en.wikipedia.org/wiki/File:%s" % flag.replace(" ", "_")
    print "reading", url
    html = getUrlUnicode(url)
    url = findRe(html, "<img.*?\"(http://.*?\.svg\.png)\"")
    if flag[-3:] == "svg":
        actually = findRe(url, "\.svg/(.*?)px")
        nominally = findRe(html, "nominally (.*?) ").replace(",", "")
        if country == "Liberia":
            nominally = "627"
        elif country == "Sikkim":
            nominally = "648"
        elif country == "Uzbekistan":
            nominally = "1000"
        url = url.replace(actually, nominally)
    else:
        url = findRe(html, "<img.*?\"(http://upload.wikimedia.org/wikipedia/.*?\." + flag[-3:] + ")\"")
    return url


def square(code, functions):
    if len(code) > 2 and code[2] == "-":
        targetFile = "../png/square/%s/%s.png" % (code[:2], code) 
    else:
        targetFile = "../png/square/%s.png" % code
    if not os.path.exists(targetFile):
        sourceFile = targetFile.replace("/square/", "/originals/")
        sourceImage = Image.open(sourceFile)
        for function in functions.split("; "):
            pos = function.find("(")
            args = function[pos + 1:-1].split(", ")
            function = function[:pos]
            if function == "border":
                targetImage = borderImage(sourceImage, args)
            elif function == "construct":
                targetImage = constructImage(sourceImage, args)
            elif function == "copy":
                targetImage = copyImage(sourceImage, targetImage, args)
            elif function == "corner":
                targetImage = cornerImage(sourceImage, args)
            elif function == "crop":
                targetImage = cropImage(sourceImage, args)
            elif function == "cross":
                targetImage = crossImage(sourceImage, args)
            elif function == "cut":
                targetImage = cutImage(sourceImage, args)
                sourceImage = targetImage
            elif function == "extend":
                targetImage = extendImage(sourceImage, args)
            elif function == "pass":
                targetImage = sourceImage
            elif function == "resize":
                targetImage = resizeImage(sourceImage, args)
            elif function == "special":
                targetImage = specialImage(sourceImage, args)
        writeImage(targetFile, targetImage)
        targetImage = targetImage.resize((16, 16), Image.ANTIALIAS)
        writeImage(targetFile.replace("/square/", "/16/"), targetImage)

def borderImage(image, args):
    args = map(lambda x: int(x), args)
    if len(args) == 1:
        args.append(args[0])
    new = Image.new("RGBA", (image.size[1], image.size[1]))
    left = int((image.size[0] - image.size[1] + args[0] + args[1]) / 2)
    right = left + image.size[1] - args[0] - args[1]
    cropLeft = image.crop((0, 0, args[0], image.size[1]))
    cropCenter = image.crop((left, 0, right, image.size[1]))
    cropRight = image.crop((image.size[0] - args[1], 0, image.size[0], image.size[1]))
    new.paste(cropLeft, (0, 0))
    new.paste(cropCenter, (args[0], 0))
    new.paste(cropRight, (image.size[1] - args[1], 0))
    return new

def constructImage(image, args):
    new = Image.new("RGBA", (256, 256))
    for y in range(256):
        for x in range(256):
            new.putpixel((x, y), (255, 255, 255))
    new.paste(image.resize((128, 160), Image.ANTIALIAS), (64, 56))
    return new

def copyImage(image, new, args):
    for i in range(8):
        args[i] = int(args[i])
    if len(args) == 8:
        args.append("rect")
    image = image.crop((args[0], args[1], args[2], args[3]))
    image = image.resize((args[4], args[5]), Image.ANTIALIAS)
    if args[8] == "rect":
        new.paste(image, (args[6], args[7]))
    else:
        if args[8] == "circle":
            mask_ = Image.open("../png/maskCircle.png")
            mask = Image.new("L", (mask_.size[0], mask_.size[1]))
            mask.paste(mask_, (0, 0))
        mask = mask.resize((image.size[0], image.size[1]), Image.ANTIALIAS)
        new.paste(image, (args[6], args[7]), mask)
    return new

def cornerImage(image, args):
    args[0] = int(args[0])
    new = Image.new("RGBA", (image.size[1], image.size[1]))
    width = int(image.size[1] / 2)
    left = int(args[0] - width / 2)
    right = int(args[0] + width / 2)
    cropLeft = image.crop((left, 0, right, image.size[1]))
    cropRight = image.crop((image.size[0] - right, 0, image.size[0] - left, image.size[1]))
    new.paste(cropLeft, (0, 0))
    new.paste(cropRight, (width, 0))
    return new

def cropImage(image, args):
    new = Image.new("RGBA", (image.size[1], image.size[1]))
    if args[0] == "":
        left = int((image.size[0] - image.size[1]) / 2)
    elif args[0] == "left":
        left = 0
    elif args[0] == "right":
        left = image.size[0] - image.size[1]
    else:
        left = int(args[0]) - int(image.size[1] / 2)
    new.paste(image.crop((left, 0, left + image.size[1], image.size[1])), (0, 0))
    return new

def crossImage(image, args):
    args[0] = int(args[0])
    new = cropImage(image, [""])
    if args[1] == "crop":
        left = int((image.size[0] - args[0]) / 4 - (image.size[1] - args[0]) / 4)
        right = left + int((image.size[1] - args[0]) / 2)
        crop = image.crop((left, 0, right, image.size[1]))
        new.paste(crop, (0, 0))
        crop = image.crop((image.size[0] - right, 0, image.size[0] - left, image.size[1]))
        new.paste(crop, (int((image.size[1] + args[0]) / 2), 0))
    elif args[1] == "resize":
        width = int(args[2])
        height = int((image.size[1] - args[0]) / 2)
        offset = int((image.size[1] + args[0]) / 2)
        crop = image.crop((0, 0, width, height)).resize((height, height), Image.ANTIALIAS)
        new.paste(crop, (0, 0))
        crop = image.crop((image.size[0] - width, 0, image.size[0], height)).resize((height, height), Image.ANTIALIAS)
        new.paste(crop, (int((image.size[1] + args[0]) / 2), 0))
        crop = image.crop((0, offset, width, image.size[1])).resize((height, height), Image.ANTIALIAS)
        new.paste(crop, (0, offset))
        crop = image.crop((image.size[0] - width, offset, image.size[0], image.size[1])).resize((height, height), Image.ANTIALIAS)
        new.paste(crop, (offset, offset))
    return new

def cutImage(image, args):
    args = map(lambda x: int(x), args)
    return image.crop((args[0], args[1], image.size[0] - args[2], image.size[1] - args[3]))

def extendImage(image, args):
    new = Image.new("RGBA", (image.size[0], image.size[0]))
    top = int((image.size[0] - image.size[1]) / 2)
    new.paste(image, (0, top))
    if args[0] == "":
        cropTop = image.crop((0, 0, image.size[0], 1))
        cropBottom = image.crop((0, image.size[1] - 1, image.size[0], image.size[1]))
    else:
        if args[0] == "left":
            pixel = image.crop((1, 1, 2, 2))
        else:
            pixel = image.crop((image.size[0] - 2, 1, image.size[0] - 1, 2))
        cropTop = Image.new("RGBA", (image.size[0], 1))
        for x in range(image.size[0]):
            cropTop.paste(pixel, (x, 0))
        if args[1] == "left":
            pixel = image.crop((1, image.size[1] - 2, 2, image.size[1] - 1))
        else:
            pixel = image.crop((image.size[0] - 2, image.size[1] - 2, image.size[0] - 1, image.size[1] - 1))
        cropBottom = Image.new("RGBA", (image.size[0], 1))
        for x in range(image.size[0]):
            cropBottom.paste(pixel, (x, 0))
    for y in range(top):
        new.paste(cropTop, (0, y))
        new.paste(cropBottom, (0, top + image.size[1] + y))
    return new

def resizeImage(image, args):
    new = Image.new("RGBA", (image.size[1], image.size[1]))
    new.paste(image.resize((image.size[1], image.size[1]), Image.ANTIALIAS))
    return new

def specialImage(image, args):
    tmp = Image.new("RGBA", (270, 270))
    tmp.paste(image.crop((632, 68, 992, 428)).resize((270, 270), Image.ANTIALIAS))
    white = tmp.crop((269, 269, 270, 270))
    tmp.paste(white.resize((80, 40)), (0, 0))
    tmp.paste(white.resize((80, 40)), (0, 230))
    tmp.paste(white.resize((80, 20)), (80, 0))
    tmp.paste(white.resize((80, 20)), (80, 250))
    new = Image.new("RGBA", (496, 496))
    new.paste(image.resize((496, 496), Image.ANTIALIAS))
    tmp.paste(new.crop((226, 113, 276, 163)), (0, 0))
    tmp.paste(new.crop((276, 113, 326, 138)), (50, 0))
    tmp.paste(new.crop((226, 333, 276, 383)), (0, 220))
    tmp.paste(new.crop((276, 358, 326, 383)), (50, 245))
    new.paste(tmp, (226, 113))
    new.paste(white.resize((80, 40)), (409, 73))
    new.paste(white.resize((50, 20)), (390, 383))
    return new

def hashFile(filename):
    h = hashlib.sha1() 
    f = open(filename)
    h.update(f.read())
    f.close() 
    return h.hexdigest()

def writeFile(filename, data):
    print "writing", filename
    writePath(filename)
    f = open(filename, "w")
    f.write(data)
    f.close()

def writeImage(filename, image):
    print "writing", filename
    writePath(filename)
    image.save(filename)

def writePath(filename):
    path = os.path.split(filename)[0]
    if path and not os.path.exists(path):
        os.makedirs(path)

debug = True # if true, existing originals are not re-downloaded
no_flag = []
# flags.sort(lambda x, y: cmp(x[1], y[1]))
for flag in flags:
    if flag[2][0] == flag[2][0].upper():
        print flag[0], flag[1], "-->", flag[2]
    else:
        print flag[0], flag[1]
        if len(flag[0]) > 2 and flag[0][2] == "-":
            filename = "../png/originals/%s/%s.png" % (flag[0][:2], flag[0])
        else:
            filename = "../png/originals/%s.png" % flag[0]
        filename_ = "../png/originals/_tmp.png"
        if not debug or not os.path.exists(filename):
            url = getFlagUrl(flag[1])
            print "reading", url
            try:
                data = getUrl(url)
            except:
                data = getUrl(url.replace("_Prefecture", ""))
            writeFile(filename_, data)
            if not os.path.exists(filename) or hashFile(filename) != hashFile(filename_):
                writeFile(filename, data)
            os.remove(filename_)
        square(flag[0], flag[2])
print "no flag", no_flag