text: from typing import List
  
  import arcpy  # type: ignore
  import pandas as pd  # type: ignore
  
  from models.city import City
  from services.base_service import BaseService
  from services.city_db_service import CityDbService
  from services.state_service import StateService
  from utils.constants import FEATURE_CITY, SHEET_NAME_CITY, FIELD_STATE, FIELD_CITY_ID, FIELD_CITY_ID_STATE, \
      STATE_FIELD_ID, STATE_FIELD_UF, FEATURE_CITY_POINT, FIELD_CITY_LAT, FIELD_CITY_LNG, FIELD_CITY_LNG_STR, \
      FIELD_CITY_LAT_STR, FIELD_CITY_OBJECT_ID, TYPE_TEXT, TYPE_DOUBLE, TYPE_FLOAT, FIELD_CITY_NAME, FIELD_CITY_CODE_IBGE, \
      FIELD_CITY_CAPITAL, FIELD_CITY_PHONE_NUMBER
  from utils.timer_decorator import timer_decorator
  
  
  class CityService(BaseService):
  
      def __init__(self, folder_path: str, file_name: str, state: StateService) -> None:
          super().__init__(folder_path, file_name)
          self.state: StateService = state
          self.city_db_services = CityDbService()
          self.table_city: str = ''
          self._list_values: pd.DataFrame = pd.DataFrame()
          self.table_city_geo = self.configs['workspace'] + "\\" + FEATURE_CITY_POINT
          if self.configs['execution']['clear_city'] == 1:
              self.prepare_data()
  
      @property
      def list_values(self) -> pd.DataFrame:
          return self._list_values
  
      @list_values.setter
      def list_values(self, list_values: List[dict]) -> None:
          self._list_values = list_values
  
      @timer_decorator('CityService.prepare_data')
      def prepare_data(self) -> None:
          self.__create_table()
          self.__add_fields_in_table()
          self.__save_field_state()
          self.features_service.convert_table_to_point(self.table_city, self.table_city_geo,
                                                       FIELD_CITY_LAT, FIELD_CITY_LNG)
          list_city_features = self.features_service.find_all(self.table_city_geo, [FIELD_CITY_NAME, FIELD_CITY_ID,
                                                                                    FIELD_CITY_CODE_IBGE, FIELD_CITY_LAT,
                                                                                    FIELD_CITY_LNG, FIELD_CITY_CAPITAL,
                                                                                    FIELD_STATE, FIELD_CITY_PHONE_NUMBER])
          list_cities = self.__convert_feature_to_cities(list_city_features)
          self.city_db_services.delete_all_cities()
          self.city_db_services.insert_cities(list_cities)
  
      @timer_decorator('CityService.remove_feature')
      def remove_feature(self):
          self.features_service.remove_feature(self.table_city_geo)
          self.features_service.remove_feature(self.configs['workspace'] + "//" + FEATURE_CITY)
          self.state.remove_feature()
  
      @staticmethod
      @timer_decorator('CityService.__convert_feature_to_cities')
      def __convert_feature_to_cities(list_city_features: pd.DataFrame) -> List[City]:
  
          list_cities: List[City] = []
  
          for item in list_city_features.values.tolist():
              list_cities.append(City(item[0], int(item[1]), int(item[2]), item[3], item[4], item[5], item[6], item[7]))
  
          return list_cities
  
      @timer_decorator('CityService.__save_field_state')
      def __save_field_state(self) -> None:
          cursor: arcpy.da.UpdateCursor = self.features_service.update_values(self.table_city,
                                                                              [FIELD_CITY_ID_STATE, FIELD_STATE])
          for row in cursor:
              state_row = self.state.list_values.loc[self.state.list_values[STATE_FIELD_ID] == row[0]]
              row[1] = state_row[STATE_FIELD_UF].values[0]
              cursor.updateRow(row)
          del cursor
  
      @timer_decorator('CityService.__add_fields_in_table')
      def __add_fields_in_table(self) -> None:
          self.features_service.add_field_in_table(self.table_city, FIELD_STATE, TYPE_TEXT)
          self.features_service.add_computed_field(self.table_city, FIELD_CITY_ID, f'!{FIELD_CITY_OBJECT_ID}!', TYPE_TEXT)
          self.features_service.add_computed_field(self.table_city, f'{FIELD_CITY_LAT}',
                                                   f'{TYPE_FLOAT}(!{FIELD_CITY_LNG_STR}!)', TYPE_DOUBLE)
          self.features_service.add_computed_field(self.table_city, f'{FIELD_CITY_LNG}',
                                                   f'{TYPE_FLOAT}(!{FIELD_CITY_LAT_STR}!)', TYPE_DOUBLE)
  
      @timer_decorator('CityService.__create_table')
      def __create_table(self) -> None:
          self.table_city = self.features_service.excel_to_table(
              self.configs['excel_city'],
              self.configs['workspace'],
              FEATURE_CITY,
              SHEET_NAME_CITY)
  