"""
Package containing the logic and tools used by the Oklahoma Next-Generation
9-1-1 GIS Toolkit for ArcGIS Pro.

Package initialization sets up logging and patches a few methods in the
``arcgis`` package.

A log file is written to ``../ng911ok.log``.

See :func:`__patch` for details on method patching.
"""
__version__ = "3.2.2"

import datetime
import logging
import sys
from inspect import getfullargspec
from pathlib import Path

import arcpy

# noinspection PyProtectedMember
import arcgis.features.geo._array  # Used for patching
import arcgis.geometry  # Used for patching
import pandas.core.arrays.base  # Used for patching

try:
    __logging_file_path = Path(__file__).parent.parent / "ng911ok.log"
    logging.basicConfig(filename=__logging_file_path, encoding="utf-8", level=logging.DEBUG, format="%(levelname)s: %(name)s/%(funcName)s - %(message)s")
except:
    logging.basicConfig(stream=sys.stdout, encoding="utf-8", level=logging.DEBUG, format="%(levelname)s: %(name)s/%(funcName)s - %(message)s")
install_info = arcpy.GetInstallInfo()
__logger = logging.getLogger(__name__)
__logger.info(f"==== LOADED ng911ok v{__version__} @ {datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')} ====\n     ArcPy Info: {install_info['ProductName']} {install_info['Version']} ({install_info['LicenseLevel']})")

# noinspection PyProtectedMember
def __patch() -> None:
    """
    Patches, as necessary, a few functions in this package's dependencies.

    .. list-table::
       :widths: auto

       * - ``arcgis.features.geo._array.GeoArray._from_factorized()``
         - Adds an argument (``original``) missing from the signature and
           defaults it to ``None``
       * - ``arcgis.geometry._types.Polyline.__getitem__()``
         - When key ``paths`` is requested from a ``Polyline`` that has no
           ``paths`` key, returns ``curvePaths`` instead
       * - ``arcgis.geometry._types.Polygon.__getitem__()``
         - When key ``rings`` is requested from a ``Polygon`` that has no
           ``rings`` key, returns ``curveRings`` instead
    """
    # Patch arcgis.features.geo._array.GeoArray._from_factorized (if needed)
    try:
        extensionarray_from_factorized_method_args = getfullargspec(pandas.core.arrays.base.ExtensionArray._from_factorized).args
        geoarray_from_factorized_method_args = getfullargspec(arcgis.features.geo._array.GeoArray._from_factorized).args
        if len(extensionarray_from_factorized_method_args) > len(geoarray_from_factorized_method_args):
            # Patch GeoArray._from_factorized() because, as implemented in package
            # ``arcgis`` v2.3.0, GeoArray's method does not accept the (unused)
            # argument ``original`` that pandas passes to it
            # noinspection PyUnusedLocal
            def _patched_from_factorized(cls, values, original=None):
                return cls(values)

            arcgis.features.geo._array.GeoArray._from_factorized = classmethod(_patched_from_factorized)
    except Exception as exc:
        __logger.error("Failed checking/patching arcgis.features.geo._array.GeoArray._from_factorized.", exc_info=exc)
    else:
        __logger.debug("Patched arcgis.features.geo._array.GeoArray._from_factorized.")


    # Patch arcgis.geometry.Polyline.__getitem__ to handle geometry with curves
    try:
        if getattr(arcgis.geometry.Polyline.__getitem__, "__name__", None) != "_patched_polyline_getitem__":
            original_polyline_getitem = arcgis.geometry.Polyline.__getitem__
            def _patched_polyline_getitem__(self, k):
                if k == "paths" and "paths" not in self:
                    return original_polyline_getitem(self, "curvePaths")
                else:
                    return original_polyline_getitem(self, k)
            arcgis.geometry.Polyline.__getitem__ = _patched_polyline_getitem__
    except Exception as exc:
        __logger.error("Failed checking/patching arcgis.geometry.Polyline.__getitem__.", exc_info=exc)
    else:
        __logger.debug("Patched arcgis.geometry.Polyline.__getitem__.")

    # Patch arcgis.geometry.Polygon.__getitem__ to handle geometry with curves
    try:
        if getattr(arcgis.geometry.Polygon.__getitem__, "__name__", None) != "_patched_polygon_getitem__":
            original_polygon_getitem = arcgis.geometry.Polygon.__getitem__
            def _patched_polygon_getitem__(self, k):
                if k == "rings" and "rings" not in self:
                    return original_polygon_getitem(self, "curveRings")
                else:
                    return original_polygon_getitem(self, k)
            arcgis.geometry.Polygon.__getitem__ = _patched_polygon_getitem__
    except Exception as exc:
        __logger.error("Failed checking/patching arcgis.geometry.Polygon.__getitem__.", exc_info=exc)
    else:
        __logger.debug("Patched arcgis.geometry.Polygon.__getitem__.")

__patch()
