# coding=utf-8
from django.conf import settings
from api.models import Province, City


class VertexCity(object):
    def __init__(self, id, name):
        """
        二级地域(市)
        :param id:
        :param name:
        """
        self.id = id
        self.name = name


class VertexProvince(object):
    def __init__(self, id, name):
        """
        一级地域(省，直辖市)
        :param id:
        :param name:
        """
        self.id = id
        self.name = name
        self.connectedTo = {}
        self.children = {}

    def addNeighbor(self, nbr, weight=0):
        self.connectedTo[nbr] = weight

    def addChildren(self, child):
        self.children[child.id] = child

    def getConnections(self):
        return self.connectedTo.keys()

    def getId(self):
        return self.id

    def getWeight(self, nbr):
        return self.connectedTo[nbr]

    def __str__(self):
        return str(self.id) + ' connectedTo: ' + str([x.id for x in self.connectedTo])


class Graph(object):
    def __init__(self):
        self.vertexList = {}
        self.cityProvinceMapping = {}

    def addVertex(self, v):
        self.vertexList[v.id] = v

    def getVertex(self, id):
        return self.vertexList[id]

    def addEdge(self, f, t, cost=0):
        """
        临近地域有向图
        :param f: vertex id
        :param t: vertex id
        :param cost:
        :return:
        """
        nbr = self.getVertex(t)
        self.vertexList[f].addNeighbor(nbr, cost)

    def getVertices(self):
        """
        获取所有地域的id
        :return:
        """
        return self.vertexList.keys()

    def get_nearby_city_tags(self, c):
        """

        :param c:
        :return:
        """
        v = self.cityProvinceMapping.get(c)
        provinces = self.getVertex(v).getConnections()
        province_ids = [p.id for p in provinces]
        tag_ids = City.objects.filter(province_id__in=province_ids).values_list("tag_id", flat=True)
        return list(tag_ids)

    def isNearBy(self, c1, c2):
        """
        是否是临近地域
        :param c1: city 1
        :param c2: city 2
        :return:
        """
        v1, v2 = self.cityProvinceMapping.get(c1), self.cityProvinceMapping.get(c2)
        if v1 and v2:
            return self.getVertex(v2) in self.getVertex(v1).getConnections()
        return False

    @classmethod
    def buildGraph(cls):
        """
        临近地域有向图
        :return:
        """
        g = Graph()
        for p in Province.objects.all():
            v = VertexProvince(p.id, p.name)
            g.addVertex(v)
            for c in City.objects.filter(province__id=p.id):
                g.cityProvinceMapping[c.id] = p.id

        for p1, pids in settings.NEARBY_REGION.items():
            for p2 in pids:
                g.addEdge(p1, p2)
        return g

g = Graph.buildGraph()
