# カスタム例外クラスの作成
class phoneEmptyRows(Exception):
    pass

class xyEmptyRows(Exception):
    pass

# モジュールのインポート
import arcpy, csv, sys

# 環境設定
arcpy.env.workspace = r"D:\Student\PYTS\Data"
arcpy.env.overwriteOutput = True

# 入出力ファイルのパラメータを設定
pNumFile = arcpy.GetParameterAsText(0)
#r"D:\Student\PYTS\Data\CSV\PhoneReports.csv"
xyFile = arcpy.GetParameterAsText(1)
#r"D:\Student\PYTS\Data\CSV\SocialMediaReports.csv"
ptFile = arcpy.GetParameterAsText(2)
#r"D:\Student\PYTS\Data\Shapefiles\AppReports.shp"


parcelPoints = r"D:\Student\PYTS\Data\Geodatabase\CountyData.gdb\Parcelpts"
serviceAreas = r"D:\Student\PYTS\Data\Geodatabase\CountyData.gdb\ServiceAreas"
aprx = arcpy.mp.ArcGISProject(r"D:\Student\PYTS\Projects\Training\Training.aprx")
outputGDB = aprx.defaultGeodatabase

serviceAreasJoin = "in_memory\join"
outages = outputGDB +"\Outages"
outageDensity = outputGDB + "\OutageDensity"
outConvexHull = outputGDB + "\OutageArea"

# エラー処理
try:
    print ("AppReports.shp を Outageフィーチャクラスにインポート")
    arcpy.AddMessage("AppReports.shp を Outageフィーチャクラスにインポート")
    arcpy.conversion.FeatureClassToFeatureClass(ptFile, outputGDB, 'Outages')

    print("SocialMediaXY テーブルからポイントを作成")
    arcpy.AddMessage("SocialMediaXY テーブルからポイントを作成")

    # XYテーブルの行数をカウントし、エラー処理
    xyCount = arcpy.management.GetCount(xyFile)
    if int(xyCount[0]) > 0:
        xyEvent = "XY_Event_Layer"
        spatialRef = arcpy.SpatialReference(103501)
        arcpy.management.MakeXYEventLayer(xyFile,"Point_X","Point_Y",xyEvent,spatialRef)
        arcpy.management.Append(xyEvent, outages,"NO_TEST")
    else:
        #例外の発生
        raise phoneEmptyRows(xyCount)

    # Searchカーソルを使用して、PhoneReports.csv から行政界ポイント（Parcelpts)の番号を検索
    # XYジオメトリをリストに追加
    print("電話番号を検索")
    arcpy.AddMessage("電話番号を検索")
    # CSVファイルのの行数をカウントし、エラー処理
    pNumCount = arcpy.management.GetCount(pNumFile)
    arcpy.AddMessage("{} phone numbers".format(pNumCount))
    if int(pNumCount[0]) > 0:
        pList = []
        csvFile = open(pNumFile)
        csvReader = csv.reader(csvFile)
        for row in csvReader:
            with arcpy.da.SearchCursor(parcelPoints,['Phone_Number','SHAPE@XY']) as sCursor:
                for sRow in sCursor:
                    if row[0] == sRow[0]:
                        pList.append(sRow[1])
            del sCursor
    else:
        #例外の発生
        raise xyEmptyRows(pNumCount)

    # リストから XY ジオメトリを Outages フィーチャクラスに挿入
    print("Outageフィーチャクラスに電話番号ポイントを挿入")
    arcpy.AddMessage("Outageフィーチャクラスに電話番号ポイントを挿入")
    iCursor = arcpy.da.InsertCursor(outages, ['SHAPE@X', 'SHAPE@Y'])
    for pRow in pList:
        iCursor.insertRow(pRow)
    del iCursor

    # カーネル密度の作成

    print("カーネル密度の作成")
    arcpy.AddMessage("カーネル密度の作成")
    arcpy.env.extent = arcpy.Extent(2053764.41650888, 507185.366399556, 2115439.05332997, 551798.058013887)
    populationField = "NONE"
    cellSize = 100
    searchRadius = ""
    outKernelDensity = arcpy.sa.KernelDensity(outages, populationField, cellSize, searchRadius, "SQUARE_MILES")
    outKernelDensity.save(outageDensity)

    # 凸包ポリゴンの作成
    # マルチ ポイント フィーチャクラスの作成
    print("凸包ポリゴンの作成")
    arcpy.AddMessage("凸包ポリゴンの作成")
    multipoints = arcpy.management.Dissolve(in_features=outages,
                                            out_feature_class=r"in_memory\multi",
                                            dissolve_field=None,
                                            multi_part=True)
    points = [f[0].convexHull() for f in arcpy.da.SearchCursor(multipoints, "SHAPE@")]
    arcpy.management.CopyFeatures(points, outConvexHull)

    # 送信する必要があるサービスエリアを決定
    print("停電ポイントとサービスエリアの結合")
    arcpy.AddMessage("停電ポイントとサービスエリアの結合")
    arcpy.analysis.SpatialJoin(serviceAreas,outages,serviceAreasJoin, "JOIN_ONE_TO_ONE", "KEEP_ALL", "", "INTERSECT")

    print("停電の件数をソートし、集計")
    arcpy.AddMessage("停電の件数をソートし、集計")
    jCursor = sorted(arcpy.da.SearchCursor(serviceAreasJoin, ["Join_Count", "ServArNu"]) , reverse=True)
    for jRow in jCursor:
        print("Service Area {}: {} outages".format(str(jRow[1]), str(jRow[0])))
        arcpy.AddMessage("Service Area {}: {} outages".format(str(jRow[1]), str(jRow[0])))
    del jCursor
    print("実行完了")

except phoneEmptyRows:
    #CSV ファイルに行がない旨をメッセージ
    print("Error: {} ファイルに行がありません".format(xyFile))
    arcpy.AddError("Error: {} ファイルに行がありません".format(xyFile))

except xyEmptyRows:
    #CSV ファイルに行がない旨をメッセージ
    print("Error: {} ファイルに行がありません".format(pNumFile))
    arcpy.AddError("Error: {} ファイルに行がありません".format(pNumFile))

except arcpy.ExecuteError:
    arcpy.AddError(arcpy.GetMessages(2))

except Exception:
    e = sys.exc_info()[1]
    print(e.args[0])
    arcpy.AddError(e.args[0])

# 結果をマップに追加
aprx = arcpy.mp.ArcGISProject("CURRENT")
m = aprx.activeMap
m.addDataFromPath(outConvexHull)
m.addDataFromPath(outages)
densityLyr = arcpy.mp.LayerFile(r"D:\Student\PYTS\Data\Other\OutageDensity.lyrx")
m.addLayer(densityLyr)
del aprx