import abc
import logging
import requests

from django.contrib.gis.geos import Point
from django.core.exceptions import ObjectDoesNotExist
from django.forms import ValidationError

from localflavor.gb.forms import GBPostcodeField
from uk_geo_utils.geocoders import OnspdGeocoder


logger = logging.getLogger(__name__)


class PostcodeError(Exception):
    pass


class BasePostcodeLookup(metaclass=abc.ABCMeta):
    def __init__(self, postcode):
        self.postcode = postcode.replace(" ", "")

    @property
    @abc.abstractmethod
    def point(self):
        pass


class BaseMaPitPostcodeLookup(BasePostcodeLookup, metaclass=abc.ABCMeta):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.fetch_from_mapit()

    @property
    @abc.abstractmethod
    def mapit_base(self):
        pass

    def fetch_from_mapit(self):
        logger.warning("Querying mySociety mapit for postcode {}".format(self.postcode))
        if hasattr(self, "mapit_data"):
            return self.mapit_data

        req = requests.get("{}/postcode/{}".format(self.mapit_base, self.postcode))
        if req.status_code != 200:
            raise PostcodeError
        try:
            self.mapit_data = req.json()
        except ValueError:
            raise PostcodeError
        return self.mapit_data

    @property
    def point(self):
        if not "wgs84_lon" in self.mapit_data:
            raise PostcodeError
        return Point(self.mapit_data["wgs84_lon"], self.mapit_data["wgs84_lat"])


class mySocietyMapitPostcodeLookup(BaseMaPitPostcodeLookup):
    mapit_base = "https://mapit.mysociety.org/"


class ONSPDPostcodeLookup(BasePostcodeLookup):
    def __init__(self, postcode):
        try:
            self.geocoder = OnspdGeocoder(postcode)
        except ObjectDoesNotExist:
            raise PostcodeError("No location information")

    @property
    def point(self):
        centre = self.geocoder.centroid
        if not centre:
            raise PostcodeError("No location information")
        return centre


def get_point_from_postcode(postcode):

    validator = GBPostcodeField()
    try:
        postcode = validator.clean(postcode)
    except ValidationError:
        raise PostcodeError("Invalid Postcode")

    # methods = [ONSPDPostcodeLookup, mySocietyMapitPostcodeLookup]
    methods = [ONSPDPostcodeLookup]
    for method in methods:
        try:
            return method(postcode).point
        except PostcodeError:
            continue
    raise PostcodeError

@@ -23,66 +23,8 @@
 ing%0A
-import requests%0A%0Afrom django.contrib.gis.geos import Point
 %0Afro
@@ -510,1077 +510,8 @@
 s%0A%0A%0A
-class BaseMaPitPostcodeLookup(BasePostcodeLookup, metaclass=abc.ABCMeta):%0A    def __init__(self, *args, **kwargs):%0A        super().__init__(*args, **kwargs)%0A        self.fetch_from_mapit()%0A%0A    @property%0A    @abc.abstractmethod%0A    def mapit_base(self):%0A        pass%0A%0A    def fetch_from_mapit(self):%0A        logger.warning(%22Querying mySociety mapit for postcode %7B%7D%22.format(self.postcode))%0A        if hasattr(self, %22mapit_data%22):%0A            return self.mapit_data%0A%0A        req = requests.get(%22%7B%7D/postcode/%7B%7D%22.format(self.mapit_base, self.postcode))%0A        if req.status_code != 200:%0A            raise PostcodeError%0A        try:%0A            self.mapit_data = req.json()%0A        except ValueError:%0A            raise PostcodeError%0A        return self.mapit_data%0A%0A    @property%0A    def point(self):%0A        if not %22wgs84_lon%22 in self.mapit_data:%0A            raise PostcodeError%0A        return Point(self.mapit_data%5B%22wgs84_lon%22%5D, self.mapit_data%5B%22wgs84_lat%22%5D)%0A%0A%0Aclass mySocietyMapitPostcodeLookup(BaseMaPitPostcodeLookup):%0A    mapit_base = %22https://mapit.mysociety.org/%22%0A%0A%0A
 clas
@@ -1137,76 +1137,8 @@
 %22)%0A%0A
-    # methods = %5BONSPDPostcodeLookup, mySocietyMapitPostcodeLookup%5D%0A
     

remove mapit geocoder