# coding=utf-8

"""
@name: 导出数据（导出图层到指定数据库，支持添加溯源字段，支持多个数据图层（过滤条件）导出，支持表）
@author: 陈蔡东
@datetime: 2024.04.16
"""

import codecs
import json
import os.path
import sys
import traceback

import arcpy

# region 输入参数

# 1.输入图层[{databasePath：数据库路径，layerName：图层名称，whereClause：过滤条件},...]
inputObjects = []
# 2.导出数据库(必须存在)
exportDatabase = ""
# 3.溯源字段(为空时认为无须添加)
addTraceField = ""

# endregion

# region 常量值

# 过滤数据路径 键名
DATABASE_PATH_KEY = "databasePath"
# 过滤图层 键名
LAYER_NAME_KEY = "layerName"
# 过滤条件 键名
WHERE_CLAUSE_KEY = "whereClause"


# endregion


# 消息写出
def outputMsg(msg):
    try:
        #if not isinstance(msg, str):
        #    arcpy.AddMessage(msg)
        #    return
        msg = msg.decode('utf-8')
        msg = repr(msg)
        arcpy.AddMessage(msg)
    except Exception, e:
        temp = e
        arcpy.AddMessage(msg)


# 输出错误信息
def outputErrorMsg(msg):
    try:
        #if not isinstance(msg, str):
        #    arcpy.AddError(msg)
         #   return
        msg = msg.decode('utf-8')
        msg = repr(msg)
        arcpy.AddError(msg)
    except Exception, e:
        temp = e
        arcpy.AddError(msg)


# 图层创建
def createLayer(databasePath, layerName, whereClause, newLayerName, isTable):
    arcpy.env.workspace = databasePath
    if not arcpy.Exists(layerName):
        return ""

    if bool(whereClause.strip()):
        if not isTable:
            arcpy.MakeFeatureLayer_management(layerName, newLayerName, whereClause)
        else:
            arcpy.MakeTableView_management(layerName, newLayerName, whereClause)
    else:
        if not isTable:
            arcpy.MakeFeatureLayer_management(layerName, newLayerName)
        else:
            arcpy.MakeTableView_management(layerName, newLayerName)

    return newLayerName


# 初始化
def init():
    if len(sys.argv) < 2:
        raise Exception("未找到输入参数文件")

    argumentFile = sys.argv[1]
    if not os.path.exists(argumentFile):
        raise Exception("输入参数文件[" + argumentFile + "]不存在")

    with codecs.open(argumentFile, 'r', 'utf-8') as f:
        arguments = json.load(f)

    outputMsg(arguments)

    if len(arguments) < 1:
        raise Exception("输入参数文件[" + argumentFile + ", 内容为空")

    if len(arguments) < 3:
        raise Exception("输入参数至少应为3位")

    global inputObjects, exportDatabase, addTraceField

    inputObjects = [] if arguments[0] is None else arguments[0]
    if len(inputObjects) < 1:
        raise Exception("输入图层为空")

    exportDatabase = "" if arguments[1] is None else arguments[1]
    if not os.path.exists(exportDatabase):
        raise Exception("导出数据库[" + exportDatabase + "]不存在")

    addTraceField = "" if arguments[2] is None else arguments[2]


# 打开输入图层
def openInputLayers():
    inputLayers = []

    for layer in inputObjects:
        databasePath = layer[DATABASE_PATH_KEY]
        layerName = layer[LAYER_NAME_KEY]
        whereClause = layer[WHERE_CLAUSE_KEY]

        if not os.path.exists(databasePath):
            raise Exception("输入数据[" + databasePath + "]不存在")

        if not bool(layerName.strip()):
            continue

        layerNameNew = layerName
        i = 1
        while layerNameNew in inputLayers:
            layerNameNew = layerName + "_" + str(i)

        # 图层类型
        desc = arcpy.Describe(databasePath + "\\" + layerName)

        isTable = desc.dataType == "Table"

        createLayer(databasePath, layerName, whereClause, layerNameNew, isTable)

        if not bool(layerNameNew.strip()):
            continue

        layerInfo = [databasePath, layerName, isTable]

        inputLayers.append(layerInfo)

    return inputLayers


# 导出数据
def exportData(inputLayers):
    for layer in inputLayers:
        outputMsg(layer[1] + "开始导出...")

        # 保存原图层属性值
        fieldMaps = arcpy.FieldMappings()
        for field in arcpy.ListFields(layer[1]):
            fm = arcpy.FieldMap()
            fm.addInputField(layer[1], field.name)
            fm.mergeRule = "first"

            newField = fm.outputField
            newField.name = field.name
            newField.aliasName = field.aliasName
            newField.type = field.type

            fm.outputField = newField
            fieldMaps.addFieldMap(fm)

        # 添加溯源字段
        if bool(addTraceField.strip()):
            desc = arcpy.Describe(layer[0] + "\\" + layer[1])
            idFieldName = desc.OIDFieldName

            # 保存溯源字段
            fieldMap = arcpy.FieldMap()
            fieldMap.addInputField(layer[1], idFieldName)

            outputMappingField = fieldMap.outputField
            outputMappingField.name = addTraceField
            outputMappingField.aliasName = addTraceField

            outputMappingField.type = "long"
            fieldMap.outputField = outputMappingField

            fieldMap.mergeRule = "first"

            fieldMaps.addFieldMap(fieldMap)

        if not layer[2]:
            arcpy.FeatureClassToFeatureClass_conversion(layer[1], exportDatabase, layer[1], field_mapping=fieldMaps)
        else:
            arcpy.TableToTable_conversion(layer[1], exportDatabase, layer[1], field_mapping=fieldMaps)

    outputMsg("Data" + exportDatabase)


def main():
    try:
        # 0.系统编码设置
        reload(sys)
        sys.setdefaultencoding('utf-8')

        # 1.参数解析
        outputMsg("开始初始化参数...")
        init()

        # 2.打开输入图层
        outputMsg("开始打开数据...")
        inputLayers = openInputLayers()

        # 3.导出数据
        outputMsg("开始导出数据...")
        exportData(inputLayers)

    except Exception, e:
        outputErrorMsg("数据导出异常")
        outputMsg(sys.argv)
        outputErrorMsg(e.message)
        outputErrorMsg(traceback.format_exc())
        raise e


main()
