from collections import OrderedDict

from ..en import Provider as AddressProvider


class Provider(AddressProvider):
    city_prefixes = ("North", "East", "West", "South", "New", "Lake", "Port")
    city_suffixes = (
        "town",
        "ton",
        "land",
        "ville",
        "berg",
        "burgh",
        "borough",
        "bury",
        "view",
        "port",
        "mouth",
        "stad",
        "furt",
        "chester",
        "mouth",
        "fort",
        "haven",
        "side",
        "shire",
    )
    counties = (
        "Bedfordshire",
        "Buckinghamshire",
        "Cambridgeshire",
        "Cheshire",
        "Cleveland",
        "Cornwall",
        "Cumbria",
        "Derbyshire",
        "Devon",
        "Dorset",
        "Durham",
        "East Sussex",
        "Essex",
        "Gloucestershire",
        "Greater London",
        "Greater Manchester",
        "Hampshire",
        "Hertfordshire",
        "Kent",
        "Lancashire",
        "Leicestershire",
        "Lincolnshire",
        "Merseyside",
        "Norfolk",
        "North Yorkshire",
        "Northamptonshire",
        "Northumberland",
        "Nottinghamshire",
        "Oxfordshire",
        "Shropshire",
        "Somerset",
        "South Yorkshire",
        "Staffordshire",
        "Suffolk",
        "Surrey",
        "Tyne and Wear",
        "Warwickshire",
        "West Berkshire",
        "West Midlands",
        "West Sussex",
        "West Yorkshire",
        "Wiltshire",
        "Worcestershire",
        "Flintshire",
        "Glamorgan",
        "Merionethshire",
        "Monmouthshire",
        "Montgomeryshire",
        "Pembrokeshire",
        "Radnorshire",
        "Anglesey",
        "Breconshire",
        "Caernarvonshire",
        "Cardiganshire",
        "Carmarthenshire",
        "Denbighshire",
        "Aberdeen City",
        "Aberdeenshire",
        "Angus",
        "Argyll and Bute",
        "City of Edinburgh",
        "Clackmannanshire",
        "Dumfries and Galloway",
        "Dundee City",
        "East Ayrshire",
        "East Dunbartonshire",
        "East Lothian",
        "East Renfrewshire",
        "Eilean Siar",
        "Falkirk",
        "Fife",
        "Glasgow City",
        "Highland",
        "Inverclyde",
        "Midlothian",
        "Moray",
        "North Ayrshire",
        "North Lanarkshire",
        "Orkney Islands",
        "Perth and Kinross",
        "Renfrewshire",
        "Scottish Borders",
        "Shetland Islands",
        "South Ayrshire",
        "South Lanarkshire",
        "Stirling",
        "West Dunbartonshire",
        "West Lothian",
        "Antrim",
        "Armagh",
        "Down",
        "Fermanagh",
        "Derry and Londonderry",
        "Tyrone",
    )
    building_number_formats = ("#", "##", "###")
    street_suffixes = (
        "Alley",
        "Avenue",
        "Branch",
        "Bridge",
        "Brook",
        "Brooks",
        "Burg",
        "Burgs",
        "Bypass",
        "Camp",
        "Canyon",
        "Cape",
        "Causeway",
        "Center",
        "Centers",
        "Circle",
        "Circles",
        "Cliff",
        "Cliffs",
        "Club",
        "Common",
        "Corner",
        "Corners",
        "Course",
        "Court",
        "Courts",
        "Cove",
        "Coves",
        "Creek",
        "Crescent",
        "Crest",
        "Crossing",
        "Crossroad",
        "Curve",
        "Dale",
        "Dam",
        "Divide",
        "Drive",
        "Drive",
        "Drives",
        "Estate",
        "Estates",
        "Expressway",
        "Extension",
        "Extensions",
        "Fall",
        "Falls",
        "Ferry",
        "Field",
        "Fields",
        "Flat",
        "Flats",
        "Ford",
        "Fords",
        "Forest",
        "Forge",
        "Forges",
        "Fork",
        "Forks",
        "Fort",
        "Freeway",
        "Garden",
        "Gardens",
        "Gateway",
        "Glen",
        "Glens",
        "Green",
        "Greens",
        "Grove",
        "Groves",
        "Harbor",
        "Harbors",
        "Haven",
        "Heights",
        "Highway",
        "Hill",
        "Hills",
        "Hollow",
        "Inlet",
        "Inlet",
        "Island",
        "Island",
        "Islands",
        "Islands",
        "Isle",
        "Isle",
        "Junction",
        "Junctions",
        "Key",
        "Keys",
        "Knoll",
        "Knolls",
        "Lake",
        "Lakes",
        "Land",
        "Landing",
        "Lane",
        "Light",
        "Lights",
        "Loaf",
        "Lock",
        "Locks",
        "Locks",
        "Lodge",
        "Lodge",
        "Loop",
        "Mall",
        "Manor",
        "Manors",
        "Meadow",
        "Meadows",
        "Mews",
        "Mill",
        "Mills",
        "Mission",
        "Mission",
        "Motorway",
        "Mount",
        "Mountain",
        "Mountain",
        "Mountains",
        "Mountains",
        "Neck",
        "Orchard",
        "Oval",
        "Overpass",
        "Park",
        "Parks",
        "Parkway",
        "Parkways",
        "Pass",
        "Passage",
        "Path",
        "Pike",
        "Pine",
        "Pines",
        "Place",
        "Plain",
        "Plains",
        "Plains",
        "Plaza",
        "Plaza",
        "Point",
        "Points",
        "Port",
        "Port",
        "Ports",
        "Ports",
        "Prairie",
        "Prairie",
        "Radial",
        "Ramp",
        "Ranch",
        "Rapid",
        "Rapids",
        "Rest",
        "Ridge",
        "Ridges",
        "River",
        "Road",
        "Road",
        "Roads",
        "Roads",
        "Route",
        "Row",
        "Rue",
        "Run",
        "Shoal",
        "Shoals",
        "Shore",
        "Shores",
        "Skyway",
        "Spring",
        "Springs",
        "Springs",
        "Spur",
        "Spurs",
        "Square",
        "Square",
        "Squares",
        "Squares",
        "Station",
        "Station",
        "Stravenue",
        "Stravenue",
        "Stream",
        "Stream",
        "Street",
        "Street",
        "Streets",
        "Summit",
        "Summit",
        "Terrace",
        "Throughway",
        "Trace",
        "Track",
        "Trafficway",
        "Trail",
        "Trail",
        "Tunnel",
        "Tunnel",
        "Turnpike",
        "Turnpike",
        "Underpass",
        "Union",
        "Unions",
        "Valley",
        "Valleys",
        "Via",
        "Viaduct",
        "View",
        "Views",
        "Village",
        "Village",
        "Villages",
        "Ville",
        "Vista",
        "Vista",
        "Walk",
        "Walks",
        "Wall",
        "Way",
        "Ways",
        "Well",
        "Wells",
    )

    POSTAL_ZONES = (
        "AB",
        "AL",
        "B",
        "BA",
        "BB",
        "BD",
        "BH",
        "BL",
        "BN",
        "BR",
        "BS",
        "BT",
        "CA",
        "CB",
        "CF",
        "CH",
        "CM",
        "CO",
        "CR",
        "CT",
        "CV",
        "CW",
        "DA",
        "DD",
        "DE",
        "DG",
        "DH",
        "DL",
        "DN",
        "DT",
        "DY",
        "E",
        "EC",
        "EH",
        "EN",
        "EX",
        "FK",
        "FY",
        "G",
        "GL",
        "GY",
        "GU",
        "HA",
        "HD",
        "HG",
        "HP",
        "HR",
        "HS",
        "HU",
        "HX",
        "IG",
        "IM",
        "IP",
        "IV",
        "JE",
        "KA",
        "KT",
        "KW",
        "KY",
        "L",
        "LA",
        "LD",
        "LE",
        "LL",
        "LN",
        "LS",
        "LU",
        "M",
        "ME",
        "MK",
        "ML",
        "N",
        "NE",
        "NG",
        "NN",
        "NP",
        "NR",
        "NW",
        "OL",
        "OX",
        "PA",
        "PE",
        "PH",
        "PL",
        "PO",
        "PR",
        "RG",
        "RH",
        "RM",
        "S",
        "SA",
        "SE",
        "SG",
        "SK",
        "SL",
        "SM",
        "SN",
        "SO",
        "SP",
        "SR",
        "SS",
        "ST",
        "SW",
        "SY",
        "TA",
        "TD",
        "TF",
        "TN",
        "TQ",
        "TR",
        "TS",
        "TW",
        "UB",
        "W",
        "WA",
        "WC",
        "WD",
        "WF",
        "WN",
        "WR",
        "WS",
        "WV",
        "YO",
        "ZE",
    )

    POSTAL_ZONES_ONE_CHAR = [zone for zone in POSTAL_ZONES if len(zone) == 1]
    POSTAL_ZONES_TWO_CHARS = [zone for zone in POSTAL_ZONES if len(zone) == 2]

    postcode_formats = (
        "AN NEE",
        "ANN NEE",
        "PN NEE",
        "PNN NEE",
        "ANC NEE",
        "PND NEE",
    )

    _postcode_sets = OrderedDict(
        (
            (" ", " "),
            ("N", [str(i) for i in range(0, 10)]),
            ("A", POSTAL_ZONES_ONE_CHAR),
            ("B", "ABCDEFGHKLMNOPQRSTUVWXY"),
            ("C", "ABCDEFGHJKSTUW"),
            ("D", "ABEHMNPRVWXY"),
            ("E", "ABDEFGHJLNPQRSTUWXYZ"),
            ("P", POSTAL_ZONES_TWO_CHARS),
        )
    )

    city_formats = (
        "{{city_prefix}} {{first_name}}{{city_suffix}}",
        "{{city_prefix}} {{first_name}}",
        "{{first_name}}{{city_suffix}}",
        "{{last_name}}{{city_suffix}}",
    )
    street_name_formats = (
        "{{first_name}} {{street_suffix}}",
        "{{last_name}} {{street_suffix}}",
    )
    street_address_formats = (
        "{{building_number}} {{street_name}}",
        "{{secondary_address}}\n{{street_name}}",
    )
    address_formats = ("{{street_address}}\n{{city}}\n{{postcode}}",)
    secondary_address_formats = (
        "Flat #",
        "Flat ##",
        "Flat ##?",
        "Studio #",
        "Studio ##",
        "Studio ##?",
    )

    def postcode(self) -> str:
        """
        See
        http://web.archive.org/web/20090930140939/http://www.govtalk.gov.uk/gdsc/html/noframes/PostCode-2-1-Release.htm
        """
        postcode = ""
        pattern: str = self.random_element(self.postcode_formats)
        for placeholder in pattern:
            postcode += self.random_element(self._postcode_sets[placeholder])
        return postcode

    def city_prefix(self) -> str:
        return self.random_element(self.city_prefixes)

    def secondary_address(self) -> str:
        return self.bothify(self.random_element(self.secondary_address_formats))

    def administrative_unit(self) -> str:
        return self.random_element(self.counties)

    county = administrative_unit
