# Path: roadmaptools/utm.py
# class CoordinateConvertor:
#     projection = default_projection
# 
#     @staticmethod
#     def convert(latitude: float, longitude: float) -> Tuple[float, float]:
#         return wgs84_to_utm(latitude, longitude, CoordinateConvertor.projection)
# 
# Path: roadmaptools/printer.py
# def print_info(info, file=sys.stdout, end="\n"):
#     print("[{0}]: {1}".format(datetime.now().strftime('%H:%M:%S'), info), file=file, end=end)
# 
# Path: roadmaptools/road_structures.py
# class LinestringEdge:
# 
# 	def __init__(self, geojson_linestring: geojson.geometry.LineString,
# 				 coordinate_convertor: Callable[[float, float], Tuple[float, float]], node_from: Node, node_to: Node):
# 		self.geojson_linestring = geojson_linestring
# 		self.linestring = roadmaptools.geojson_shp.geojson_linestring_to_shp_linestring(geojson_linestring,
# 																							coordinate_convertor)
# 		self.node_from = node_from
# 		self.node_to = node_to
# 		self.id = get_edge_id(node_from.id, node_to.id)
# 
# 	def __eq__(self, o: object) -> bool:
# 		if isinstance(o, self.__class__):
# 			return self.id == o.id
# 		return False
# 
# 	def __ne__(self, o: object) -> bool:
# 		if isinstance(o, self.__class__):
# 			return self.id != o.id
# 		return False
# 
# 	def __hash__(self) -> int:
# 		return hash(self.id)
# 
# class Node:
# 	def __init__(self, x: float, y: float, id: int):
# 		self.id = id
# 		self.x = x
# 		self.y = y
# 		self._point = None
# 
# 	def get_point(self) -> Point:
# 		if not self._point:
# 			self._point = Point(self.x, self.y)
# 
# 		return self._point
# 
# 	def __eq__(self, o: object) -> bool:
# 		if isinstance(o, self.__class__):
# 			return self.id == o.id
# 		return False
# 
# 	def __ne__(self, o: object) -> bool:
# 		if isinstance(o, self.__class__):
# 			return self.id != o.id
# 		return False
# 
# 	def __hash__(self) -> int:
# 		return hash(self.id)


import networkx
import roadmaptools.inout
import roadmaptools.geometry
from typing import Dict
from geojson import FeatureCollection
from tqdm import tqdm
from networkx import DiGraph
from roadmaptools.utm import CoordinateConvertor
from roadmaptools.printer import print_info
from roadmaptools.road_structures import LinestringEdge, Node


def load_from_geojson(geojson: FeatureCollection):
	# projection determination
	first_coord = geojson['features'][0]['geometry']['coordinates']
	projection = roadmaptools.utm.TransposedUTM(first_coord[1], first_coord[0])
	print_info("Projection determined from the first coordinate: {}{}".format(
		projection.origin_zone_number, projection.origin_zone_letter))
	CoordinateConvertor.projection = projection

	print_info("Creating networkx graph from geojson")
	for item in tqdm(geojson['features'], desc="processing features"):
		if item["geometry"]["type"] == "LineString":
			coords = item['geometry']['coordinates']
			coord_from = roadmaptools.utm.wgs84_to_utm(coords[0][1], coords[0][0], projection)
			coord_to = roadmaptools.utm.wgs84_to_utm(coords[-1][1], coords[-1][0], projection)

			node_from = _get_node(coord_from[0], coord_from[1])
			node_to = _get_node(coord_to[0], coord_to[1])

			edge = LinestringEdge(item, CoordinateConvertor.convert, node_from, node_to)

			# TODO legacy, remove after moving id from properties to id attribute
			edge_id = item['properties']['id'] if "id" in item['properties'] else item['id']
			length = item['properties']['length'] if 'length' in item['properties'] \
				else roadmaptools.geometry.get_distance(coord_from, coord_to)
			graph.add_edge(node_from, node_to, id=edge_id, length=length, edge=edge)


def _get_node(x: float, y: float) -> Node:
	id = roadmaptools.utm.get_id_from_utm_coords(x, y)

# Path: roadmaptools/utm.py
# class CoordinateConvertor:
#     projection = default_projection
# 
#     @staticmethod
#     def convert(latitude: float, longitude: float) -> Tuple[float, float]:
#         return wgs84_to_utm(latitude, longitude, CoordinateConvertor.projection)
# 
# Path: roadmaptools/printer.py
# def print_info(info, file=sys.stdout, end="\n"):
#     print("[{0}]: {1}".format(datetime.now().strftime('%H:%M:%S'), info), file=file, end=end)
# 
# Path: roadmaptools/road_structures.py
# class LinestringEdge:
# 
# 	def __init__(self, geojson_linestring: geojson.geometry.LineString,
# 				 coordinate_convertor: Callable[[float, float], Tuple[float, float]], node_from: Node, node_to: Node):
# 		self.geojson_linestring = geojson_linestring
# 		self.linestring = roadmaptools.geojson_shp.geojson_linestring_to_shp_linestring(geojson_linestring,
# 																							coordinate_convertor)
# 		self.node_from = node_from
# 		self.node_to = node_to
# 		self.id = get_edge_id(node_from.id, node_to.id)
# 
# 	def __eq__(self, o: object) -> bool:
# 		if isinstance(o, self.__class__):
# 			return self.id == o.id
# 		return False
# 
# 	def __ne__(self, o: object) -> bool:
# 		if isinstance(o, self.__class__):
# 			return self.id != o.id
# 		return False
# 
# 	def __hash__(self) -> int:
# 		return hash(self.id)
# 
# class Node:
# 	def __init__(self, x: float, y: float, id: int):
# 		self.id = id
# 		self.x = x
# 		self.y = y
# 		self._point = None
# 
# 	def get_point(self) -> Point:
# 		if not self._point:
# 			self._point = Point(self.x, self.y)
# 
# 		return self._point
# 
# 	def __eq__(self, o: object) -> bool:
# 		if isinstance(o, self.__class__):
# 			return self.id == o.id
# 		return False
# 
# 	def __ne__(self, o: object) -> bool:
# 		if isinstance(o, self.__class__):
# 			return self.id != o.id
# 		return False
# 
# 	def __hash__(self) -> int:
# 		return hash(self.id)


# Path: roadmaptools/test/networkx_pickle_test.py
import networkx
import roadmaptools.inout
import roadmaptools.geometry
from typing import Dict
from geojson import FeatureCollection
from tqdm import tqdm
from networkx import DiGraph
from roadmaptools.utm import CoordinateConvertor
from roadmaptools.printer import print_info
from roadmaptools.road_structures import LinestringEdge, Node


def load_from_geojson(geojson: FeatureCollection):
	# projection determination
	first_coord = geojson['features'][0]['geometry']['coordinates']
	projection = roadmaptools.utm.TransposedUTM(first_coord[1], first_coord[0])
	print_info("Projection determined from the first coordinate: {}{}".format(
		projection.origin_zone_number, projection.origin_zone_letter))
	CoordinateConvertor.projection = projection

	print_info("Creating networkx graph from geojson")
	for item in tqdm(geojson['features'], desc="processing features"):
		if item["geometry"]["type"] == "LineString":
			coords = item['geometry']['coordinates']
			coord_from = roadmaptools.utm.wgs84_to_utm(coords[0][1], coords[0][0], projection)
			coord_to = roadmaptools.utm.wgs84_to_utm(coords[-1][1], coords[-1][0], projection)

			node_from = _get_node(coord_from[0], coord_from[1])
			node_to = _get_node(coord_to[0], coord_to[1])

			edge = LinestringEdge(item, CoordinateConvertor.convert, node_from, node_to)

			# TODO legacy, remove after moving id from properties to id attribute
			edge_id = item['properties']['id'] if "id" in item['properties'] else item['id']
			length = item['properties']['length'] if 'length' in item['properties'] \
				else roadmaptools.geometry.get_distance(coord_from, coord_to)
			graph.add_edge(node_from, node_to, id=edge_id, length=length, edge=edge)


def _get_node(x: float, y: float) -> Node:
	id = roadmaptools.utm.get_id_from_utm_coords(x, y)

	if id in node_map:
