"""
 Tool Name:     CheckSnapping
 Description:  Performs a simple check to see if the WBD is correctly snapped to the NHD.  
 Author:    Patrick Longley (plongley@usgs.gov)
 Created:   08/19/2020
 Language: Written in python3 (arcpro). Modified to also work in arc2 (python2).
 History:
    10/06/2020 validation (not necesary)
    10/06/2020 constants
    10/06/2020 metadata
    10/13/2020 reviewed
    10/28/2020 respects user's selection
 TODO: flag  vertices in the middle of nhd area/waterbody
"""

# IMPORTS
import os
import sys
import arcpy
import wbd_f
import wbd_params

# Constants
PYTHON_VERSION = sys.version_info.major
MEMORY_FPATH = wbd_f.get_memoryfpath(PYTHON_VERSION)
# MEMORY_FPATH = r'C:\Users\plongley\Desktop\19050302_Pilot\MyProject1\MyProject1.gdb'

# Check snapping tool
class CheckSnapping(object):
    """
    Checks snapping.
    """

    def __init__(self):
        self.label = "G2 Check Snapping"
        self.description = "Checks that intersections with NHD are also vertices."
        self.callfrom_pyt = True
        self.category = "Geometry checks"

    def getParameterInfo(self):
        """
        Check updated WBD lines are correctly snappped to NHD feature classes.
        This is done by checking if NHD/WBD intersections are also WBD line vertices.

        Args:
            linefc_updated (str): String that gives filepath to updated WBD liuine featureclass.
            nhd_fc (list of strings):  List of nhd featureclasses.

        Outputs:
            returns: None
            output parameter: nhdsnapping_issues, output point featureclass.
        """
        nhd_line = wbd_params.nhdline_fc
        nhd_line.parameterType = "Optional"
        nhd_waterbody = wbd_params.nhdwaterbody_fc
        nhd_waterbody.parameterType = "Optional"
        nhd_area = wbd_params.nhdarea_fc
        nhd_area.parameterType = "Optional"
        params = [
            wbd_params.linefc_updated,
            nhd_line,
            nhd_waterbody,
            nhd_area,
            wbd_params.nhdsnapping_issues,
        ]
        return params

    def merge_polygons(self, polygon_fcs):
        polygons_list = [p for p in polygon_fcs if p]
        if len(polygons_list) == 0:
            return None, False
        elif len(polygons_list) == 1:
            return polygons_list[0], False
        else:
            return arcpy.Merge_management(polygons_list, os.path.join(arcpy.env.workspace, "polygons")), True

    def execute(self, params, messages):
        """
        Execute above functions to check snapping.
        """
        # parameters
        if self.callfrom_pyt:
            wbdline_fc = params[0].valueAsText
            nhdline_fc = params[1].valueAsText
            nhdwaterbody_fc = params[2].valueAsText
            nhdarea_fc = params[3].valueAsText
            out_fpath = params[4].valueAsText
        else:
            wbdline_fc = params[0]
            nhdline_fc = params[1]
            nhdwaterbody_fc = params[2]
            nhdarea_fc = params[3]
            out_fpath = params[4]
        nhd_fcs = (nhdline_fc, nhdwaterbody_fc, nhdarea_fc)
        if not any(nhd_fcs):
            raise arcpy.ExecuteError("No NHD feature classes entered.")
        with arcpy.EnvManager(overwriteOutput=True):
            # create empty output feature classe
            snapping_issues = arcpy.CreateFeatureclass_management(
                os.path.dirname(out_fpath), os.path.basename(out_fpath), geometry_type="MULTIPOINT"
            )

        # find snapping issues with polygons
        nhd_polygons, merged = self.merge_polygons(nhd_fcs[1:])
        if nhd_polygons:
            wbd_vertices = arcpy.FeatureVerticesToPoints_management(
                wbdline_fc, os.path.join(arcpy.env.workspace, "wbd_vertices")
            )
            polygons_tolines = arcpy.PolygonToLine_management(
                nhd_polygons, os.path.join(arcpy.env.workspace, "polygons_tolines")
            )
            intersect_points = arcpy.Intersect_analysis(
                [polygons_tolines, wbdline_fc],
                os.path.join(arcpy.env.workspace, "intersect_withpolygons"),
                join_attributes="ONLY_FID",
                output_type="point",
            )
            erase = arcpy.Erase_analysis(intersect_points, wbd_vertices, "erase")
            arcpy.Append_management(erase, snapping_issues, schema_type="NO_TEST")
            arcpy.Delete_management(wbd_vertices)
            arcpy.Delete_management(intersect_points)
            arcpy.Delete_management(erase)

        # check intersections with nhd flowlines
        if nhdline_fc:
            nhd_endpoints = arcpy.FeatureVerticesToPoints_management(
                nhdline_fc, os.path.join(arcpy.env.workspace, "nhd_endpoints"), point_location="END"
            )
            if nhd_polygons:
                nhdline_erase = arcpy.Erase_analysis(
                    nhdline_fc, nhd_polygons, os.path.join(arcpy.env.workspace, "flowlines_erase")
                )
                intersect_points = arcpy.Intersect_analysis(
                    [nhdline_erase, wbdline_fc],
                    os.path.join(arcpy.env.workspace, "intersect_points"),
                    join_attributes="ONLY_FID",
                    output_type="point",
                )
                arcpy.Delete_management(nhdline_erase)
            else:
                intersect_points = arcpy.Intersect_analysis(
                    [nhdline_fc, wbdline_fc],
                    os.path.join(arcpy.env.workspace, "intersect_points"),
                    join_attributes="ONLY_FID",
                    output_type="point",
                )
            erase = arcpy.Erase_analysis(intersect_points, nhd_endpoints, "erase")
            arcpy.Append_management(erase, snapping_issues, schema_type="NO_TEST")
            arcpy.Delete_management(nhd_endpoints)
            arcpy.Delete_management(intersect_points)
            arcpy.Delete_management(erase)
            if merged:
                arcpy.Delete_management(nhd_polygons)


if __name__ == "__main__":
    """
    Execute as standalone script.
    """
    check_snapping = CheckSnapping()
    check_snapping.callfrom_pyt = False
    arcpy.env.workspace = r"C:\Users\plongley\Desktop\deleteme\deleteme.gdb"
    newlines = r"C:\Users\plongley\Desktop\deleteme\19010204_project.gdb\Layers\Newlines"
    nhd = [r"C:\GIS_Project\WBD\AK\Work\hu19010204\19010204_prep\19010204_data.gdb\initial_data\NHDFlowline_19010204"]
    params = (newlines, nhd, "deleteme")
    check_snapping.execute(params, None)

