"""
Obj module parses obj files and import the geometry into the city model structure
SPDX - License - Identifier: LGPL - 3.0 - or -later
Copyright © 2022 Concordia CERC group
Project Coder Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concordia.ca
"""
import trimesh.exchange.load
from trimesh import Scene
import trimesh.geometry
from hub.city_model_structure.city import City
from hub.city_model_structure.building import Building
from hub.city_model_structure.building_demand.surface import Surface
from hub.city_model_structure.attributes.polygon import Polygon


class Obj:
  """
  Obj class
  """
  def __init__(self, path):
    self._city = None
    with open(path, 'r') as file:
      self._scene = trimesh.exchange.load.load(file, file_type='obj', force='scene')
    self._corners = self._scene.bounds_corners
    _bound_corner_min = None
    _bound_corner_max = None
    for corner in self._corners:
      if _bound_corner_min is None:
        _bound_corner_min = corner
      elif _bound_corner_max is None:
        _bound_corner_max = corner
      else:
        _bound_corner_min[0] = min(_bound_corner_min[0], corner[0])
        _bound_corner_min[1] = min(_bound_corner_min[1], corner[1])
        _bound_corner_min[2] = min(_bound_corner_min[2], corner[2])
        _bound_corner_max[0] = max(_bound_corner_max[0], corner[0])
        _bound_corner_max[1] = max(_bound_corner_max[1], corner[1])
        _bound_corner_max[2] = max(_bound_corner_max[2], corner[2])
    self._lower_corner = _bound_corner_min
    self._upper_corner = _bound_corner_max

  @property
  def scene(self) -> Scene:
    """
    Get obj scene
    """
    return self._scene

  @property
  def city(self) -> City:
    """
    Get city out of an obj file
    """
    lod = 0
    if self._city is None:
      # todo: refactor this method to clearly choose the obj type
      # todo: where do we get this information from?
      srs_name = 'EPSG:26911'

      self._city = City(self._lower_corner, self._upper_corner, srs_name)
      scene = self.scene.geometry
      keys = scene.keys()
      for key in keys:
        name = key
        # todo: where do we get this information from?
        lod = 1
        year_of_construction = 0
        function = ''

        obj = scene[key]
        surfaces = []
        for face in obj.faces:
          # todo: review for obj with windows
          points = []
          for vertex_index in face:
            points.append(obj.vertices[vertex_index])
          solid_polygon = Polygon(points)
          perimeter_polygon = solid_polygon
          surface = Surface(solid_polygon, perimeter_polygon)
          surfaces.append(surface)
        building = Building(name, surfaces, year_of_construction, function, terrains=None)
        self._city.add_city_object(building)
      self._city.level_of_detail.geometry = lod
    return self._city
