import logging
import sys
import os
import csv
import logging.handlers

from argparse import ArgumentParser
from datetime import datetime as dt

# import validate_load
import field_parsing
import create_templates


class ArcPyLogHandler(logging.StreamHandler):
    """
    Custom logging class that bounces messages to the arcpy tool window as well
    as reflecting back to the file.
    """

    def emit(self, record):
        """
        Write the log message
        """
        try:
            msg = record.msg.format(record.args)
        except Exception as e:
            msg = record.msg

        if record.levelno == logging.ERROR:
            arcpy.AddError(msg)
        elif record.levelno == logging.WARNING:
            arcpy.AddWarning(msg)
        elif record.levelno == logging.INFO:
            arcpy.AddMessage(msg)
        else:
            arcpy.AddMessage(msg)

        super(ArcPyLogHandler, self).emit(record)


###############################################################################
# helper (manipulates handlers for the logic of the application)

def run_app():
    """Run the logic of application"""
    gdb, fc, codes, tbl, fc_fld, tbl_fld, logger = get_input_parameter()

    load_data(gdb, fc, codes, tbl, fc_fld, tbl_fld, logger)

    # validate_load.validate_load(gdb, logger)


###############################################################################
# handler (defines core functions of the application)

def get_input_parameter():
    """
    Parse arguments and set up logger

    :return: directory where "Data Loading Directory" will be created, version of TEIS data load process
    :rtype: str, str
    """
    try:
        parser = ArgumentParser(
            description='Run this script to load data existing TEIS data into the Stage1.gdb within the '
                        'contractor package.  If the imported feature class does not contain the attributes '
                        'required as part of the TEIS environment, then the option exists to input a standalone '
                        'table in the CSV, DBF or FGDB Table formats.')
        parser.add_argument('gdb', help='Path to the Stage_1 geodatabase within the contractor package.')
        parser.add_argument('fc', help='Feature class containing the TEIS data to import.')
        parser.add_argument('codes', nargs='?', help='[OPTIONAL] Table containing new Ecosystem Codes.')
        parser.add_argument('tbl', nargs='?', help='[OPTIONAL] attribute table to join on the feature class if the '
                                                   'feature class does not contain attributes.  This table can be '
                                                   'a CSV, DBF, or FGDB Table.')
        parser.add_argument('fc_fld', nargs='?', help='[OPTIONAL] Field name in the input feature class used '
                                                      'for the attribute table join.')
        parser.add_argument('tbl_fld', nargs='?', help='[OPTIONAL] Field name in the attribute table used to '
                                                       'join to the feature class.')
        parser.add_argument('--log_level', default='INFO', choices=['DEBUG', 'INFO', 'WARNING', 'ERROR'],
                            help='Log level')
        parser.add_argument('--log_dir', help='Path to log Directory')
        args = parser.parse_args()

        log_name = 'main_logger'
        logger = logging.getLogger(log_name)
        logger.handlers = []

        log_fmt = logging.Formatter('%(asctime)s - %(levelname)s - %(message)s')
        log_file_base_name = os.path.basename(sys.argv[0])
        log_file_extension = 'log'
        timestamp = dt.now().strftime('%Y-%m-%d_%H-%M-%S')
        log_file = "{}_{}.{}".format(timestamp, log_file_base_name, log_file_extension)

        logger.setLevel(args.log_level)

        sh = logging.StreamHandler()
        sh.setLevel(args.log_level)
        sh.setFormatter(log_fmt)
        logger.addHandler(sh)

        args.log_dir = os.path.join(os.path.dirname(sys.argv[0]), 'log')
        if args.log_dir:
            try:
                os.makedirs(args.log_dir)
            except OSError:
                pass

            fh = logging.FileHandler(os.path.join(args.log_dir, log_file))
            fh.setLevel(args.log_level)
            fh.setFormatter(log_fmt)
            logger.addHandler(fh)

            if args.gdb:
                loading_log_file = os.path.join(os.path.dirname(args.gdb), 'Loading_Log.log')
                if os.path.exists(loading_log_file):
                    os.remove(loading_log_file)
                fh2 = logging.FileHandler(loading_log_file)
                fh2.setLevel(args.log_level)
                fh2.setFormatter(log_fmt)
                logger.addHandler(fh2)

        if os.path.basename(sys.executable).lower() == 'python.exe':
            arc_env = False
        else:
            arc_env = True

        if arc_env:
            arc_handler = ArcPyLogHandler()
            arc_handler.setLevel(args.log_level)
            arc_handler.setFormatter(log_fmt)
            logger.addHandler(arc_handler)

        if args.tbl and (not args.fc_fld or not args.tbl_fld):
            logger.error('The optional attribute table requires the join field parameters '
                         'for the input feature class and attribute table. Program terminating')
            sys.exit(1)

        # Start the script
        return args.gdb, args.fc, args.codes, args.tbl, args.fc_fld, args.tbl_fld, logger

    except Exception as e:
        logging.exception('Unexpected exception. Program terminating.')
        exit(1)


def load_data(gdb, fc, codes, tbl, fc_fld, tbl_fld, logger):
    logger.info('####Initializing load_data script')
    arcpy.env.overwriteOutput = True
    logger.info('Checking input parameters\n')
    if codes == '#':
        codes = None
    if tbl == '#':
        tbl = None
    if fc_fld == '#':
        fc_fld = None
    if tbl_fld == '#':
        tbl_fld = None

    # Check if the Stage 1 geodatabase exists
    if not os.path.exists(gdb):
        logger.error('The geodatabase {} specified does not exist.  Program terminating.'.format(gdb))
        sys.exit(1)
    logger.info('****START OF USER INPUT PARAMETERS****')
    logger.info('Stage_1 geodatabase: {}'.format(gdb))

    # Check if the input feature class exists
    if not arcpy.Exists(fc):
        logger.error('The input feature class {} specified does not exist. Program terminating.'.format(fc))
        sys.exit(1)
    logger.info('Feature class to load in: {}'.format(fc))

    # Check if the eco codes table exists
    if codes:
        if not arcpy.Exists(codes):
            logger.error('The input table {} specified does not exist. Program terminating.'.format(codes))
            sys.exit(1)
        logger.info('Ecosystem Codes table to validate on: {}'.format(fc))

    bl_tbl_csv = False
    # Check if the attribute table exists
    if tbl:
        tbl_exists = True
        if os.path.splitext(tbl)[1] == '.csv':
            bl_tbl_csv = True
            if not os.path.exists(tbl):
                tbl_exists = False
        else:
            if not arcpy.Exists(tbl):
                tbl_exists = False

        if not tbl_exists:
            logger.error('The input attribute table {} specified does not exist. Program terminating.'.format(tbl))
            sys.exit(1)
        logger.info('Attribute table to join: {}'.format(tbl))

    if fc_fld:
        if fc_fld not in [f.name for f in arcpy.ListFields(fc)]:
            logger.error(' The feature class {} does not contain the join field specified {}.'
                         ' Program terminating'.format(os.path.basename(fc), fc_fld))
            sys.exit(1)
        logger.info('Feature class join field to use: {}'.format(fc_fld))

    if tbl_fld:
        if bl_tbl_csv:
            with open(tbl, 'r') as c:
                csv_reader = csv.DictReader(c)
                csv_fields = csv_reader.fieldnames
            if tbl_fld not in csv_fields:
                logger.error(' The attribute table {} does not contain the join field specified {}.'
                             ' Program terminating'.format(os.path.basename(tbl), tbl_fld))
                sys.exit(1)
        else:
            if tbl_fld not in [f.name for f in arcpy.ListFields(tbl)]:
                logger.error(' The attribute table {} does not contain the join field specified {}.'
                             ' Program terminating'.format(os.path.basename(tbl), tbl_fld))
                sys.exit(1)

        logger.info('Attribute table join field to use: {}'.format(tbl_fld))
    logger.info('****END OF USER INPUT PARAMETERS****\n')

    # Check if the Tools and Templates geodatabase exists
    tat_database = os.path.join(os.path.dirname(gdb), 'Tools_and_Templates.gdb')
    if not os.path.exists(tat_database):
        logger.error('The Tools and Templates geodatabase does not exist, please ensure the contractor'
                     ' package was extracted correctly.  Program terminating.')
        sys.exit(1)
    logger.info('****START OF DERIVED PARAMETERS****')
    logger.info('Tools and Templates geodatabase: {}'.format(tat_database))

    tbl_metadata_items = os.path.join(os.path.dirname(gdb), 'Tools_and_Templates.gdb', 'TEIS_Metadata_Items')

    if not arcpy.Exists(tbl_metadata_items):
        logger.error('Ensure the TEIS_Metadata_Items table exists in the Tools_and_Templates '
                     'geodatabase. Program Terminating.')
        sys.exit(1)
    logger.info('TEIS_Metadata_Items table: {}'.format(tbl_metadata_items))

    tbl_long_table = os.path.join(gdb, 'TEI_Long_Tbl')
    logger.info('TEI_Long_Tbl table: {}'.format(tbl_long_table))

    logger.info('****END OF DERIVED PARAMETERS****\n')

    arcpy.env.overwriteOutput = True
    feature_count = int(arcpy.GetCount_management(fc).getOutput(0))
    logger.info('{} records found within the input feature class {}'.format(feature_count, os.path.basename(fc)))
    if feature_count == 0:
        logger.warning('No records to load in the input feature class. Program Terminating')
        sys.exit(1)

    temp_fc = os.path.join(gdb, '{}_load'.format(os.path.basename(fc)))
    desc_in_file = arcpy.Describe(fc)
    spatial_ref = desc_in_file.spatialReference
    if spatial_ref.name != 'NAD_1983_BC_Environment_Albers':
        logger.info('The input feature class\'s projection is in {}, projecting to '
                    'NAD 1983 BC Environment Albers and copying into the Stage_1 geodatabase.'.format(spatial_ref.name))
        arcpy.Project_management(fc, temp_fc, arcpy.SpatialReference('NAD 1983 BC Environment Albers'))
    else:
        logger.info('The input feature class\'s projection is in NAD 1983 BC Environment Albers, '
                    'copying the input feature class to the Stage_1 geodatabase.')
        arcpy.CopyFeatures_management(fc, temp_fc)

    if tbl:
        try:
            int_fld_count = len(arcpy.ListFields(tbl))
            logger.info('Joining {} fields from {} to {}'.format(int_fld_count, os.path.basename(tbl),
                                                                 os.path.basename(temp_fc)))
            arcpy.JoinField_management(temp_fc, fc_fld, tbl, tbl_fld)
            int_new_count = len(arcpy.ListFields(temp_fc))
            logger.info('Successfully joined {} fields. Total number of fields '
                        'now in {} is {}'.format(int_fld_count, os.path.basename(temp_fc), int_new_count))
        except Exception as e:
            logger.error('There was an error while trying to join the tables. Program terminating')
            sys.exit(1)

    long_tbl_fields = create_templates.get_field_list(tat_database, 'TEI_Long_Tbl')
    lst_required_fields = []

    str_where = 'TEI_Long_Tbl IS NOT NULL And (Item_Mandatory IS NOT NULL Or Item_Mandatory_TER IS NOT NULL ' \
                'Or Item_Mandatory_TEM IS NOT NULL Or Item_Mandatory_SEI IS NOT NULL)'
    with arcpy.da.SearchCursor(tbl_metadata_items, ['FGDB_Name'], str_where) as s_cursor:
        for row in s_cursor:
            lst_required_fields.append(row[0])

    logger.info('The following fields are considered mandatory: {}'.format(lst_required_fields))
    logger.info('Comparing fields in the feature class to the required fields')
    lst_missing_fields = []
    lst_fc_fields = [f.name for f in arcpy.ListFields(temp_fc)]
    for field in lst_required_fields:
        if field not in lst_fc_fields:
            if field not in ['PROJPOLYID']:
                lst_missing_fields.append(field)

    if lst_missing_fields:
        logger.warning('The input dataset is missing the following required fields '
                       'and will be modified to include them: {}'.format(lst_missing_fields))
        for field in lst_missing_fields:
            create_templates.add_specified_field(tat_database, temp_fc, field, logger)
    logger.info('All required fields exist within the input feature class')

    lst_bapids = []
    with arcpy.da.SearchCursor(temp_fc, 'BAPID') as s_cursor:
        for row in s_cursor:
            if int(row[0]) not in lst_bapids:
                lst_bapids.append(int(row[0]))

    lst_bapids.sort()
    logger.info('The following BAPIDs were detected in the input feature class: {}'.format(lst_bapids))

    if 'PROJPOLYID' not in lst_fc_fields:
        logger.info('Creating the PROJPOLYID field')
        arcpy.AddField_management(temp_fc, 'PROJPOLYID', 'TEXT', None, None, 50)

    lst_cursor_fields = ['PROJPOLYID']
    if 'ECP_TAG' in lst_fc_fields:
        lst_cursor_fields.append('ECP_TAG')
        str_fields = 'ECP_TAG'
    elif 'TER_TAG' in lst_fc_fields:
        lst_cursor_fields.append('TER_TAG')
        str_fields = 'TER_TAG'
    elif 'POLY_NBR' in lst_fc_fields:
        str_fields = 'BAPID and POLY_NBR'
        lst_cursor_fields.extend(['BAPID', 'POLY_NBR'])
    else:
        str_fields = 'BAPID and OBJECTID'
        lst_cursor_fields.extend(['BAPID', 'OBJECTID'])

    logger.info('Populating the PROJPOLYID field with {}'.format(str_fields))
    with arcpy.da.UpdateCursor(temp_fc, lst_cursor_fields) as u_cursor:
        for row in u_cursor:
            if len(lst_cursor_fields) == 2:
                row[0] = str(row[1])
            else:
                row[0] = '{}_{}'.format(str(row[1]), str(row[2]))
            u_cursor.updateRow(row)

    logger.info('Ensuring field types match the TEI_Long_Tbl template')
    for f in arcpy.ListFields(temp_fc):
        if f.name in long_tbl_fields.keys():
            if f.type != long_tbl_fields[f.name][1]:
                logger.info('{} doesn\'t match the template, recreating and repopulating the field'.format(f.name))
                dict_values = build_value_dictionary(temp_fc, 'PROJPOLYID', f.name)
                update_values(temp_fc, dict_values, 'PROJPOLYID', f.name, long_tbl_fields[f.name])

    logger.info('Checking for user defined fields')
    lst_fc_fields = [f.name for f in arcpy.ListFields(temp_fc)]

    lst_check_fields = list(long_tbl_fields.keys()) + ['OBJECTID', 'Shape', 'Shape_Length',
                                                       'Shape_Area', 'Shape_Length_1', 'Shape_Area_1']
    lst_extra_fields = [item for item in lst_fc_fields if item not in lst_check_fields]

    if len(lst_extra_fields) == 0:
        logger.info('No user defined fields detected')
    else:
        logger.info('The following user defined fields were detected and will be '
                    'added to the TEI_Usr_Dfn_Data table: {}'.format(lst_extra_fields))
        fld_mappings = arcpy.FieldMappings()
        lst_user_fields = ['TEIS_ID', 'PROJPOLYID', 'BAPID'] + lst_extra_fields
        for field in lst_user_fields:
            fld_map = arcpy.FieldMap()
            fld_map.addInputField(temp_fc, field)
            fld_map.outputField.name = field
            fld_mappings.addFieldMap(fld_map)

        arcpy.TableToTable_conversion(temp_fc, gdb, 'TEI_Usr_Dfn_Data', '', fld_mappings)

        logger.info('Inserting field data into the TEI_Usr_Dfn_Fields table, '
                    'user input required to complete the table records')
        lst_cursor_fields = ['BAPID', 'COLM_NAME', 'VALUE_TYP', 'LENGTH', 'DECIMAL', 'REQUIRED']
        with arcpy.da.UpdateCursor(os.path.join(gdb, 'TEI_Usr_Dfn_Fields'), lst_cursor_fields) as u_cursor:
            for row in u_cursor:
                if int(row[0]) in lst_bapids:
                    u_cursor.deleteRow()

        with arcpy.da.InsertCursor(os.path.join(gdb, 'TEI_Usr_Dfn_Fields'), lst_cursor_fields) as i_cursor:
            for f in arcpy.ListFields(temp_fc):
                if f.name in lst_extra_fields:
                    for bapid in lst_bapids:
                        if f.required == 0:
                            str_req = 'N'
                        else:
                            str_req = 'Y'
                        row = [bapid, f.name, f.type, f.length, f.precision, str_req]
                        i_cursor.insertRow(row)

    logger.info('Checking for texture and surface expression fields that need to be parsed out')
    field_parsing.field_parsing(temp_fc, tbl_metadata_items, logger)

    lst_missing_fields = []
    lst_fc_fields = [f.name for f in arcpy.ListFields(temp_fc)]

    for field in long_tbl_fields.keys():
        if field not in lst_fc_fields:
            lst_missing_fields.append(field)

    if lst_missing_fields:
        logger.info('Adding missing fields to match the TEI_Long_Tbl template')
        for fld in lst_missing_fields:
            if fld in long_tbl_fields.keys():
                field_parsing.add_field(temp_fc, fld, long_tbl_fields, [], logger)

    lst_fc_fields = [f.name for f in arcpy.ListFields(temp_fc)]

    lst_bgc_fields = [i for i in lst_fc_fields if i in ["BGC_ZONE", "BGC_SUBZON", "BGC_VRT", "BGC_PHASE"]]
    if len(lst_bgc_fields) != 0:
        logger.info('Concatenating Biogeoclimatic zone fields')
        field_parsing.concatenate_bgc(temp_fc)

    lst_distcls_fields = [i for i in lst_fc_fields if i in ["DISTCLS_1", "DISTSCLS_1", "DISSSCLS_1",
                                                            "DISTCLS_2", "DISTSCLS_2", "DISSSCLS_2",
                                                            "DISTCLS_3", "DISTSCLS_3", "DISSSCLS_3"]]
    if len(lst_distcls_fields) == 9:
        logger.info('Concatenating Site Disturbance fields')
        field_parsing.concatenate_site_dist(temp_fc)

    lst_sec_fields = [i for i in lst_fc_fields if i in ["SECL_1", "SESUBCL_1", "SECL_2", "SESUBCL_2",
                                                        "SECL_3", "SESUBCL_3"]]
    if len(lst_sec_fields) == 6:
        logger.info('Concatenating Sensitive Ecosystem fields')
        field_parsing.concatenate_sec(temp_fc)

    if len(lst_sec_fields) == 6:
        logger.info('Concatenating Geomorphological Process fields')
        field_parsing.concatenate_geop(temp_fc)

    logger.info('Standardizing the NoData values in the input feature class')
    standardize_no_data(temp_fc, logger)

    details_dict = {}
    with arcpy.da.SearchCursor(temp_fc, ['BAPID', 'FCODE', 'PROJ_TYPE', 'PROJ_SCALE']) as s_cursor:
        for row in s_cursor:
            if row[0] not in details_dict.keys():
                details_dict[row[0]] = [row[1], row[2], row[3]]

    tbl_prj_details = os.path.join(gdb, 'TEI_Project_Details')
    if not arcpy.Exists(tbl_prj_details):
        logger.info('{} doesn\'t exist, creating from the TEIS_Metadata_Items table')
        create_templates.create_templates(tat_database, gdb, ['TEI_Project_Details'], logger)

    logger.info('Removing records for BAPID(s) {} from the TEI_Project_Details if they exist'.format(lst_bapids))
    delete_count = 0
    with arcpy.da.UpdateCursor(tbl_prj_details, 'BAPID') as u_cursor:
        for row in u_cursor:
            if row[0] in lst_bapids:
                u_cursor.deleteRow()
                delete_count += 1
    logger.info('Removed {} records from the TEI_Project_Details'.format(delete_count))

    insert_count = 0
    with arcpy.da.InsertCursor(tbl_prj_details, ['BAPID', 'FCODE', 'PROJ_TYPE', 'PROJ_SCALE']) as i_cursor:
        for bapid in lst_bapids:
            lst_details = details_dict[bapid]
            i_cursor.insertRow((bapid, lst_details[0], lst_details[1], lst_details[2]))
            insert_count += 1

    logger.info('Inserted {} record(s) into the TEI_Project_Details table.'
                ' Please fill in the empty fields.'.format(insert_count))

    if not arcpy.Exists(tbl_long_table):
        logger.info('Creating the TEI Long Tbl as it doesn\'t exist')
        create_templates.create_templates(tat_database, gdb, ['TEI_Long_Tbl'], logger)
    logger.info('Removing records for BAPID(s) {} from the TEI_Long_Tbl if they exist'.format(lst_bapids))
    delete_count = 0
    with arcpy.da.UpdateCursor(tbl_long_table, 'BAPID') as u_cursor:
        for row in u_cursor:
            if row[0] in lst_bapids:
                u_cursor.deleteRow()
                delete_count += 1
    logger.info('Removed {} records from the TEI_Long_Tbl'.format(delete_count))

    logger.info('Loading input features into the TEI_Long_Tbl')
    int_lng_tbl_count = int(arcpy.GetCount_management(tbl_long_table).getOutput(0))
    int_load_count = int(arcpy.GetCount_management(temp_fc).getOutput(0))
    logger.info('Load Feature Class Count: {}'.format(int_load_count))
    logger.info('Current Long Table Count: {}'.format(int_lng_tbl_count))
    logger.info('Appending input feature class')
    arcpy.Append_management(temp_fc, tbl_long_table, 'NO_TEST')

    post_lng_tbl_count = int(arcpy.GetCount_management(tbl_long_table).getOutput(0))
    loaded_count = post_lng_tbl_count - int_lng_tbl_count

    logger.info('Loaded {} out of {} into the TEI_Long_Tbl'.format(loaded_count, int_load_count))
    if loaded_count == int_load_count:
        logger.info('Successfully loaded all features'.format(int_load_count))
    else:
        logger.warning('Not all features were loaded')

    logger.info('New Long Table Count: {}'.format(post_lng_tbl_count))

    logger.info('Deleting temporary load feature class')
    arcpy.Delete_management(temp_fc)

    if codes:
        logger.info('Appending Ecosystem Code rows into the TEI_Ecosystem_Code_Submission')
        tbl_eco_codes = os.path.join(gdb, 'TEI_Ecosystem_Code_Submission')

        if tbl_eco_codes == codes:
            logger.warning('{} already within Stage1.gdb, nothing to load'.format(codes))
            logger.warning('Skipping...')
        else:
            arcpy.Append_management(codes, tbl_eco_codes, 'NO_TEST')

    logger.info('####Completed load_data script\n')


def build_value_dictionary(fc, key_fld, val_fld):

    dict_values = {}

    with arcpy.da.SearchCursor(fc, [key_fld, val_fld]) as s_cursor:
        for row in s_cursor:
            dict_values[row[0]] = row[1]

    return dict_values


def update_values(fc, dict_values, key_fld, del_fld, new_fld):
    arcpy.DeleteField_management(fc, del_fld)
    arcpy.AddField_management(fc, del_fld, new_fld[1], new_fld[3], new_fld[4], new_fld[2], new_fld[0])
    with arcpy.da.UpdateCursor(fc, [key_fld, del_fld]) as u_cursor:
        for row in u_cursor:
            row[1] = dict_values[row[0]]
            u_cursor.updateRow(row)


def standardize_no_data(input_location, logger):
    logger.info('        - Fixing null values in numeric and string fields')

    curr_fields = arcpy.ListFields(input_location)
    curr_field_names = []
    for CurrentField in curr_fields:
        if CurrentField.type not in ['Blob', 'Geometry', 'Guid', 'OID', 'Raster', 'Date']:
            curr_field_names.append(str(CurrentField.name))

    field_name_dict = {}
    x = 0
    for curr_field_name in curr_field_names:
        field_name_dict[curr_field_name] = x
        x += 1

    nullify_mean_asp_dict = {}
    logger.info('        - Processing input table for all fields except MEAN_ASP')

    with arcpy.da.UpdateCursor(input_location, curr_field_names) as cursor:
        for row in cursor:
            update_flag = False

            # handle the slope fields separately from the rest of the fields:
            # if one of a slope field pair is zero and the other is greater than zero, keep the zero;
            # otherwise nullify the zero(es)
            slope_field_pairs = [['SLPLL_1', 'SLPUL_1'], ['SLPLL_2', 'SLPUL_2'], ['SLPLL_1A', 'SLPUL_1A'],
                                 ['SLPLL_1B', 'SLPUL_1B'], ['SLPLL_2A', 'SLPUL_2A'], ['SLPLL_2B', 'SLPUL_2B'],
                                 ['SLPLL_3A', 'SLPUL_3A'], ['SLPLL_3B', 'SLPUL_3B']]
            for slope_field_pair in slope_field_pairs:
                if slope_field_pair[0] in curr_field_names and slope_field_pair[0] in curr_field_names:
                    lower_slope = str(row[field_name_dict[slope_field_pair[0]]])
                    upper_slope = str(row[field_name_dict[slope_field_pair[1]]])
                    if lower_slope == '0' and upper_slope == '0':
                        row[field_name_dict[slope_field_pair[0]]] = None
                        row[field_name_dict[slope_field_pair[1]]] = None
                        update_flag = True
                    elif lower_slope == 'None' and upper_slope == '0':
                        row[field_name_dict[slope_field_pair[1]]] = None
                        update_flag = True
                    elif lower_slope == '0' and upper_slope == 'None':
                        row[field_name_dict[slope_field_pair[0]]] = None
                        update_flag = True

            for fix_item in curr_fields:
                if fix_item.name in ['TEIS_ID', 'SLPLL_1', 'SLPUL_1', 'SLPLL_2', 'SLPUL_2', 'SLPLL_1A', 'SLPUL_1A',
                                     'SLPLL_1B', 'SLPUL_1B', 'SLPLL_2A', 'SLPUL_2A', 'SLPLL_2B', 'SLPUL_2B', 'SLPLL_3A',
                                     'SLPUL_3A', 'SLPLL_3B', 'SLPUL_3B']:
                    pass  # don't (further) modify these fields

                if fix_item.name == 'MEAN_ASP':
                    # in this cursor loop, build a dictionary of unique MEAN_ASP values for each BAPID;
                    # in the next cursor loop (below), for each BAPID, if all MEAN_ASP's are zero or
                    # null, we will nullify them, but if some are zeros and others are actual values,
                    # we will not modify any of them for that BAPID
                    bapid = row[field_name_dict['BAPID']]
                    if bapid not in nullify_mean_asp_dict:
                        nullify_mean_asp_dict[bapid] = True
                    mean_asp = str(row[field_name_dict['MEAN_ASP']])
                    if mean_asp not in ['0', 'None']:
                        nullify_mean_asp_dict[bapid] = False

                # fix SDEC-based numeric fields 'TREE_C1', 'TREE_C2', 'TREE_C3', 'SHRUB_C1', 'SHRUB_C2', 'SHRUB_C3'
                # (set to null only if SDEC_x is also zero or null)
                elif fix_item.name in ['TREE_C1', 'SHRUB_C1', 'TREE_C2', 'SHRUB_C2', 'TREE_C3', 'SHRUB_C3']:
                    fix_item_value = row[field_name_dict[str(fix_item.name)]]
                    if fix_item_value == 0:
                        sdec_field_name = 'SDEC_' + fix_item.name[-1:]
                        sdec = str(row[field_name_dict[sdec_field_name]])
                        if sdec not in ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10']:
                            row[field_name_dict[str(fix_item.name)]] = None
                            update_flag = True

                elif fix_item.type in ['Integer', 'SmallInteger']:
                    fix_item_value = str(row[field_name_dict[str(fix_item.name)]])
                    if fix_item_value == '0':
                        row[field_name_dict[str(fix_item.name)]] = None
                        update_flag = True

                elif fix_item.type not in ['SmallInteger', 'Integer', 'Single', 'Double', 'OID', 'Geometry', 'Date']:
                    # normally we would "str()" this value,
                    # but POLY_COM sometimes contains unicode characters which causes error
                    if row[field_name_dict[str(fix_item.name)]] in [' ', None]:
                        row[field_name_dict[str(fix_item.name)]] = ''
                        update_flag = True

            if update_flag:
                cursor.updateRow(row)

    if 'MEAN_ASP' in curr_field_names:
        logger.info('        - Processing input table for MEAN_ASP field')
        with arcpy.da.UpdateCursor(input_location, curr_field_names) as cursor:
            for row in cursor:
                bapid = row[field_name_dict['BAPID']]
                # check the dictionary we built in the previous cursor loop
                # for whether MEAN_ASP should be nullified for this BAPID
                if nullify_mean_asp_dict[bapid]:
                    row[field_name_dict['MEAN_ASP']] = None
                    cursor.updateRow(row)

#
# class FieldParsing:
#
#     def __init__(self):
#         pass
#
#     @staticmethod
#     def field_parsing(long_tbl, template, logger):
#
#         # Fields to add
#         textural_field_base_names = ['TTEX_', 'SURF_E', 'STTEX_', 'SSURF_E', 'TTTEX_', 'TSURF_E']
#         geo_letter_field = 'GEOP_SCM'
#         geo_prime_field = 'GEOP_INZ'
#
#         lst_fgdb_names = []
#         template_field_dict = {}
#
#         for field in arcpy.ListFields(template):
#             fld_name = str(field.name)
#             if fld_name.startswith('FGDB_'):
#                 lst_fgdb_names.append(fld_name)
#
#         long_tbl_name = os.path.basename(long_tbl)
#         if not long_tbl_name.endswith('Tbl'):
#             long_tbl_name = long_tbl_name.split('Tbl')[0] + 'Tbl'
#         where_clause = long_tbl_name + ' IS NOT NULL'
#         sql_clause = 'ORDER BY ' + long_tbl_name
#         with arcpy.da.SearchCursor(template, lst_fgdb_names + [long_tbl_name], where_clause=where_clause,
#                                    sql_clause=(None, sql_clause)) as s_cursor:
#             for row in s_cursor:
#                 fld_name = str(row[0])
#                 fld_alias = str(row[1])
#                 fld_type = str(row[2])
#                 fld_width = row[3]
#                 fld_precision = row[4]
#                 fld_scale = row[5]
#
#                 template_field_dict[fld_name] = [fld_alias, fld_type, fld_width, fld_precision, fld_scale]
#
#         # List of existing fields
#         existing_field_names = [f.name for f in arcpy.ListFields(long_tbl)]
#
#         # Fields to add
#         fields_to_add = []
#
#         # We only want to add and parse fields where the base field actually exists
#         for number in range(1, 4):
#             for field in textural_field_base_names:
#                 if field + str(number) in existing_field_names:
#                     fields_to_add.append(field + str(number))
#
#             if geo_letter_field + str(number) in existing_field_names:
#                 fields_to_add.append(geo_letter_field + str(number))
#                 fields_to_add.append(geo_prime_field + str(number))
#
#         if len(fields_to_add) == 0:
#             logger.info("There are no fields to add - This script only needs to be run on BAPIDS containing fields:")
#             logger.info(", ".join(textural_field_base_names + [geo_letter_field, geo_prime_field]))
#             return
#
#         # Add all fields, if they do not already exist
#         fields_to_update = []
#         errors = 0
#         logger.info("Adding new fields to " + os.path.basename(long_tbl))
#         for number in range(1, 4):
#
#             # Add fields with numbers appended to the end
#             field_name = geo_prime_field + str(number)
#             if field_name in fields_to_add:
#                 fields_to_update.append(field_name)
#                 errors += FieldParsing.add_field(long_tbl, field_name, template_field_dict,
#                                                  existing_field_names, logger)
#
#             # Add fields with numbers and letters appended to the end
#             for field_base in [geo_letter_field, geo_prime_field] + textural_field_base_names:
#                 field_name = field_base + str(number)
#                 if field_name in fields_to_add:
#                     fields_to_update.append(field_name)
#                     for letter in ['A', 'B', 'C']:
#                         fields_to_update.append(field_name + letter)
#                         errors += FieldParsing.add_field(long_tbl, field_name + letter,
#                                                          template_field_dict, existing_field_names, logger)
#
#         # We assume all fields were added successfully when updating fields.
#         # If there were errors at this point we must exit
#
#         if errors > 0:
#             logger.error(str(errors) + " fields could not be added, no fields have been updated. "
#                                        "Fix the issues preventing field creation and run the script again")
#
#             sys.exit(0)
#
#         # Create lookup to access fields by name in constant time
#         long_tbl_i = dict(zip(fields_to_update, range(len(fields_to_update))))
#         updates = 0
#
#         logger.info("Updating new fields in " + os.path.basename(long_tbl))
#
#         with arcpy.da.UpdateCursor(long_tbl, fields_to_update) as cursor:
#             for row in cursor:
#                 updates += 1
#                 if updates % 1000 == 0:
#                     logger.debug("   Updating row " + str(updates))
#
#                 for number in range(1, 4):
#
#                     # ------------------------
#                     # Populate textural fields
#                     for field_name in textural_field_base_names:
#
#                         # If the field doesn't exist, do not try to process it
#                         if field_name + str(number) not in fields_to_update:
#                             continue
#
#                         base_col = long_tbl_i[field_name + str(number)]
#                         base_val = row[base_col] if row[base_col] is not None else ''
#
#                         # TEX fields are populated backwards
#                         if 'TEX' in field_name:
#                             row[long_tbl_i[field_name + str(number) + 'A']] = base_val[-1:]
#                             row[long_tbl_i[field_name + str(number) + 'B']] = base_val[-2:-1]
#                             row[long_tbl_i[field_name + str(number) + 'C']] = base_val[-3:-2]
#                         else:
#                             row[long_tbl_i[field_name + str(number) + 'A']] = base_val[0:1]
#                             row[long_tbl_i[field_name + str(number) + 'B']] = base_val[1:2]
#                             row[long_tbl_i[field_name + str(number) + 'C']] = base_val[2:3]
#
#                     # -------------------
#                     # Populate Geo fields
#
#                     # If the field doesn't exist, do not try to process it
#                     if geo_letter_field + str(number) not in fields_to_update:
#                         continue
#
#                     base_col = long_tbl_i[geo_letter_field + str(number)]
#                     base_val = row[base_col] if row[base_col] is not None else ''
#
#                     prime_val = '"' if base_val.startswith('"') else ''
#                     base_val = base_val if prime_val == "" else base_val[1:]
#
#                     row[long_tbl_i[geo_prime_field + str(number)]] = prime_val
#                     row[long_tbl_i[geo_letter_field + str(number) + 'A']] = base_val[0:1]
#                     row[long_tbl_i[geo_letter_field + str(number) + 'B']] = base_val[1:2]
#                     row[long_tbl_i[geo_letter_field + str(number) + 'C']] = base_val[2:3]
#                 cursor.updateRow(row)
#         logger.info("Updated " + str(updates) + " rows")
#
#     @staticmethod
#     def concatenate_bgc(long_tbl):
#         lst_fields = ['BGC_VLD', 'BGC_ZONE', 'BGC_SUBZON', 'BGC_VRT', 'BGC_PHASE']
#
#         with arcpy.da.UpdateCursor(long_tbl, lst_fields) as u_cursor:
#             for row in u_cursor:
#                 str_bec = ''
#                 if row[1]:
#                     str_bec = str(row[1])
#                 if row[2]:
#                     str_bec += str(row[2])
#                 if row[3]:
#                     str_bec += str(row[3])
#                 if row[4]:
#                     str_bec += str(row[4])
#                 row[0] = str_bec
#                 u_cursor.updateRow(row)
#
#     @staticmethod
#     def concatenate_site_dist(long_tbl):
#         for i in range(1, 3):
#             lst_fields = ['DISTCLS_VLD{}'.format(i), 'DISTCLS_{}'.format(i),
#                           'DISTSCLS_{}'.format(i), 'DISSSCLS_{}'.format(i)]
#
#             with arcpy.da.UpdateCursor(long_tbl, lst_fields) as u_cursor:
#                 for row in u_cursor:
#                     str_dist = ''
#                     if row[1]:
#                         str_dist = str(row[1])
#                     if row[2]:
#                         str_dist += " " + str(row[2])
#                     if row[3]:
#                         str_dist += " " + str(row[3])
#                     row[0] = str_dist
#                     u_cursor.updateRow(row)
#
#     @staticmethod
#     def concatenate_sec(long_tbl):
#         for i in range(1, 3):
#             lst_fields = ['SECL_VLD{}'.format(i), 'SECL_{}'.format(i), 'SESUBCL_{}'.format(i)]
#
#             with arcpy.da.UpdateCursor(long_tbl, lst_fields) as u_cursor:
#                 for row in u_cursor:
#                     str_sec = ''
#                     if row[1]:
#                         str_sec = str(row[1])
#                     if row[2]:
#                         str_sec += " " + str(row[2])
#                     row[0] = str_sec
#                     u_cursor.updateRow(row)
#
#     @staticmethod
#     def concatenate_geop(long_tbl):
#         for i in range(1, 3):
#             lst_fields = ['GEOP_VLD{}A'.format(i), 'GEOP_VLD{}B'.format(i), 'GEOP_VLD{}C'.format(i),
#                           'GEOP_{}'.format(i), 'GEOP_SCM{}A'.format(i), 'GEOP_SCM{}B'.format(i),
#                           'GEOP_SCM{}C'.format(i)]
#
#             with arcpy.da.UpdateCursor(long_tbl, lst_fields) as u_cursor:
#                 for row in u_cursor:
#                     str_geop = ''
#                     if row[3]:
#                         str_geop = str(row[3])
#                     if row[4]:
#                         row[0] = str_geop + " " + str(row[4])
#                     if row[5]:
#                         row[1] = str_geop + " " + str(row[5])
#                     if row[6]:
#                         row[2] = str_geop + " " + str(row[6])
#
#                     u_cursor.updateRow(row)
#
#     @staticmethod
#     def parse_modifiers(long_tbl, tat_database, logger):
#
#         lst_fields = ['BGC_VLD', 'BGC_ZONE', 'BGC_SUBZON', 'BGC_VRT', 'BGC_PHASE']
#         lst_fc_fields = [f.name for f in arcpy.ListFields(long_tbl)]
#         long_tbl_fields = FieldParsing.get_field_list(tat_database, 'TEIS_Master_Long_Tbl')
#         if lst_fields[0] in lst_fc_fields:
#             for field in lst_fields[1:]:
#                 if field not in lst_fc_fields and field in long_tbl_fields.keys():
#                     FieldParsing.add_field(long_tbl, field, long_tbl_fields, lst_fc_fields, logger)
#             with arcpy.da.UpdateCursor(long_tbl, lst_fields) as u_cursor:
#                 for row in u_cursor:
#                     if row[0]:
#                         str_bec = row[0]
#                         lst_bec = str_bec.split(' ')
#
#                         row[1] = lst_bec[0]
#                         lst_bec = lst_bec[1:]
#                         if lst_bec:
#                             row[2] = lst_bec[0]
#                             lst_bec = lst_bec[1:]
#                             if lst_bec:
#                                 if str(lst_bec[0]).isdigit():
#                                     row[3] = lst_bec[0]
#                                     lst_bec = lst_bec[1:]
#                                     if lst_bec:
#                                         row[4] = lst_bec[0]
#                                 else:
#                                     row[4] = lst_bec[0]
#                         u_cursor.updateRow(row)
#
#         for i in range(1, 3):
#             lst_fields = ['DISTCLS_VLD{}'.format(i), 'DISTCLS_{}'.format(i),
#                           'DISTSCLS_{}'.format(i), 'DISSSCLS_{}'.format(i)]
#
#             lst_fc_fields = [f.name for f in arcpy.ListFields(long_tbl)]
#             if lst_fields[0] in lst_fc_fields:
#                 for field in lst_fields[1:]:
#                     if field not in lst_fc_fields and field in long_tbl_fields.keys():
#                         FieldParsing.add_field(long_tbl, field, long_tbl_fields, lst_fc_fields, logger)
#
#                 with arcpy.da.UpdateCursor(long_tbl, lst_fields) as u_cursor:
#                     for row in u_cursor:
#                         if row[0]:
#                             str_dist = row[0]
#                             lst_dist = str_dist.split(' ')
#
#                             row[1] = lst_dist[0]
#                             lst_dist = lst_dist[1:]
#                             if lst_dist:
#                                 row[2] = lst_dist[0]
#                                 lst_dist = lst_dist[1:]
#                                 if lst_dist:
#                                     row[3] = lst_dist[0]
#
#                             u_cursor.updateRow(row)
#
#         for i in range(1, 3):
#             lst_fields = ['SECL_VLD{}'.format(i), 'SECL_{}'.format(i), 'SESUBCL_{}'.format(i)]
#             lst_fc_fields = [f.name for f in arcpy.ListFields(long_tbl)]
#             if lst_fields[0] in lst_fc_fields:
#                 for field in lst_fields[1:]:
#                     if field not in lst_fc_fields and field in long_tbl_fields.keys():
#                         FieldParsing.add_field(long_tbl, field, long_tbl_fields, lst_fc_fields, logger)
#
#                 with arcpy.da.UpdateCursor(long_tbl, lst_fields) as u_cursor:
#                     for row in u_cursor:
#                         if row[0]:
#                             str_sec = row[0]
#                             lst_sec = str_sec.split(' ')
#
#                             row[1] = lst_sec[0]
#                             lst_sec = lst_sec[1:]
#                             if lst_sec:
#                                 row[2] = lst_sec[0]
#
#                             u_cursor.updateRow(row)
#
#         for i in range(1, 3):
#             lst_fields = ['GEOP_VLD{}A'.format(i), 'GEOP_VLD{}B'.format(i), 'GEOP_VLD{}C'.format(i),
#                           'GEOP_SCM{}A'.format(i), 'GEOP_SCM{}B'.format(i), 'GEOP_SCM{}C'.format(i)]
#
#             lst_fc_fields = [f.name for f in arcpy.ListFields(long_tbl)]
#             if lst_fields[0] in lst_fc_fields and lst_fields[1] in lst_fc_fields and lst_fields[2] in lst_fc_fields:
#                 for field in lst_fields[3:]:
#                     if field not in lst_fc_fields and field in long_tbl_fields.keys():
#                         FieldParsing.add_field(long_tbl, field, long_tbl_fields, lst_fc_fields, logger)
#
#                 with arcpy.da.UpdateCursor(long_tbl, lst_fields) as u_cursor:
#                     for row in u_cursor:
#                         if row[0]:
#                             row[3] = str(row[0]).split(' ')[1]
#                         if row[1]:
#                             row[4] = str(row[1]).split(' ')[1]
#                         if row[2]:
#                             row[5] = str(row[2]).split(' ')[1]
#
#                         u_cursor.updateRow(row)
#
#     @staticmethod
#     def get_field_list(tat_database, fc_name):
#         tbl_metadata_items = os.path.join(tat_database, 'TEIS_Metadata_Items')
#
#         lst_fgdb_names = []
#         dict_fields = {}
#
#         for field in arcpy.ListFields(tbl_metadata_items):
#             fld_name = str(field.name)
#             if fld_name.startswith('FGDB_'):
#                 lst_fgdb_names.append(fld_name)
#
#         where_clause = fc_name + ' IS NOT NULL'
#         sql_clause = 'ORDER BY ' + fc_name
#         with arcpy.da.SearchCursor(tbl_metadata_items, lst_fgdb_names + [fc_name], where_clause=where_clause,
#                                    sql_clause=(None, sql_clause)) as s_cursor:
#             for row in s_cursor:
#                 fld_name = str(row[0])
#                 fld_alias = str(row[1])
#                 fld_type = str(row[2])
#                 fld_width = row[3]
#                 fld_precision = row[4]
#                 fld_scale = row[5]
#
#                 dict_fields[fld_name] = [fld_alias, fld_type, fld_width, fld_precision, fld_scale]
#
#         return dict_fields
#
#     @staticmethod
#     # Add field to table if it does not yet exist in the table and exists in the template
#     def add_field(table, field_name, template_fields, existing_field_names, logger):
#         if field_name in existing_field_names:
#             logger.info("    SKIPPING - field [" + field_name + "] already exists")
#             return 0
#
#         if field_name in template_fields:
#             try:
#
#                 fld_alias = template_fields[field_name][0]
#                 fld_type = template_fields[field_name][1]
#                 fld_width = template_fields[field_name][2]
#                 fld_precision = template_fields[field_name][3]
#                 fld_scale = template_fields[field_name][4]
#                 arcpy.AddField_management(table,
#                                           field_name=field_name,
#                                           field_alias=fld_alias,
#                                           field_type=fld_type,
#                                           field_length=fld_width,
#                                           field_precision=fld_precision,
#                                           field_scale=fld_scale)
#                 logger.info("    Added field [" + field_name + "]")
#                 return 0
#
#             except Exception as e:
#
#                 logger.warning("    Could not add field [" + field_name + "]")
#                 logger.warning(str(e))
#                 return 1
#         else:
#             logger.warning("    Field [" + field_name + "] does not exist in template")
#             return 1
#
#
# class CreateTemplates:
#
#     def __init__(self):
#         pass
#
#     @staticmethod
#     def create_templates(tat_database, output_path, templates, logger):
#
#         if not arcpy.Exists(tat_database):
#             logger.error('The specified Tools and Templates database does not exist. Program Terminating.')
#             sys.exit(1)
#
#         tbl_metadata_items = tat_database + "/TEIS_Metadata_Items"
#         tbl_metadata_tables = tat_database + "/TEIS_Metadata_Tables"
#
#         if not arcpy.Exists(tbl_metadata_items):
#             logger.error('The Tools and Templates database does not contain the '
#                          'TEIS_Metadata_Items table. Program Terminating.')
#             sys.exit(1)
#
#         if not arcpy.Exists(tbl_metadata_tables):
#             logger.error('The Tools and Templates database does not contain the '
#                          'TEIS_Metadata_Tables table. Program Terminating.')
#             sys.exit(1)
#
#         if not arcpy.Exists(output_path):
#             logger.error('The output geodatabase specified does not exist. Program Terminating.')
#             sys.exit(1)
#
#         lst_template_names = []
#         lst_fgdb_names = []
#         lst_sde_names = []
#         lst_fc_fields = ['Feature_Class', 'Feature_Type', 'Spatial_Reference']
#
#         for field in arcpy.ListFields(tbl_metadata_items):
#             fld_name = str(field.name)
#             if fld_name.startswith('STE_') or fld_name.startswith('TEI'):
#                 lst_template_names.append(fld_name)
#             elif fld_name.startswith('FGDB_'):
#                 lst_fgdb_names.append(fld_name)
#             elif fld_name.startswith('SDE_'):
#                 lst_sde_names.append(fld_name)
#
#         lst_templates_create = []
#         if templates:
#             for temp in templates:
#                 if temp in lst_template_names:
#                     lst_templates_create.append(temp)
#                 else:
#                     logger.warning('{} does not exist as a template in the TEIS Metadata Items table'.format(temp))
#
#             if len(lst_templates_create) == 0:
#                 logger.error('None of the specified templates exist in the TEIS Metadata Items Table.'
#                              ' Program Terminating.')
#                 sys.exit(1)
#             lst_template_names = lst_templates_create
#
#         with arcpy.da.SearchCursor(tbl_metadata_tables, lst_fc_fields) as s_cursor:
#             for row in s_cursor:
#                 fc_name = str(row[0])
#                 if fc_name in lst_template_names:
#                     fc_type = str(row[1]).upper()
#
#                     if str(row[2]) == 'None':
#                         sr = None
#                     else:
#                         sr = arcpy.SpatialReference(str(row[2]).replace('_', ' '))
#
#                     if 'VIEW' in fc_type:
#                         fc_type = fc_type[:-4]
#
#                     temp_name = fc_name
#
#                     logger.info('Creating {}'.format(temp_name))
#
#                     temp_path = output_path + '/' + temp_name
#
#                     if arcpy.Exists(output_path + '/' + temp_name):
#                         arcpy.Delete_management(output_path + '/' + temp_name)
#
#                     if fc_type != 'TABLE':
#                         arcpy.CreateFeatureclass_management(output_path, temp_name, fc_type, spatial_reference=sr)
#                     else:
#                         arcpy.CreateTable_management(output_path, temp_name)
#
#                     if fc_name.startswith('STE_') or fc_name.endswith('_SENSITIVE'):
#                         lst_cursor_fields = lst_sde_names
#                     else:
#                         lst_cursor_fields = lst_fgdb_names
#
#                     where_clause = fc_name + ' IS NOT NULL'
#                     sql_clause = 'ORDER BY ' + fc_name
#                     with arcpy.da.SearchCursor(tbl_metadata_items, lst_cursor_fields + [fc_name],
#                                                where_clause=where_clause,
#                                                sql_clause=(None, sql_clause)) as s_cursor_2:
#                         for itm in s_cursor_2:
#                             fld_name = str(itm[0])
#                             fld_alias = str(itm[1])
#                             fld_type = str(itm[2])
#                             fld_width = itm[3]
#                             fld_precision = itm[4]
#                             fld_scale = itm[5]
#                             arcpy.AddField_management(temp_path, field_name=fld_name, field_type=fld_type,
#                                                       field_precision=fld_precision, field_scale=fld_scale,
#                                                       field_length=fld_width, field_alias=fld_alias)
#
#     @staticmethod
#     def get_field_list(tat_database, fc_name):
#         tbl_metadata_items = os.path.join(tat_database, 'TEIS_Metadata_Items')
#
#         lst_fgdb_names = []
#         dict_fields = {}
#
#         for field in arcpy.ListFields(tbl_metadata_items):
#             fld_name = str(field.name)
#             if fld_name.startswith('FGDB_'):
#                 lst_fgdb_names.append(fld_name)
#
#         where_clause = fc_name + ' IS NOT NULL'
#         sql_clause = 'ORDER BY ' + fc_name
#         with arcpy.da.SearchCursor(tbl_metadata_items, lst_fgdb_names + [fc_name], where_clause=where_clause,
#                                    sql_clause=(None, sql_clause)) as s_cursor:
#             for row in s_cursor:
#                 fld_name = str(row[0])
#                 fld_alias = str(row[1])
#                 fld_type = str(row[2])
#                 fld_width = row[3]
#                 fld_precision = row[4]
#                 fld_scale = row[5]
#
#                 dict_fields[fld_name] = [fld_alias, fld_type, fld_width, fld_precision, fld_scale]
#
#         return dict_fields
#
#     @staticmethod
#     def add_specified_field(tat_database, fc, field_name, logger):
#
#         if field_name in [f.name for f in arcpy.ListFields(fc)]:
#             return
#
#         fc_name = os.path.basename(fc)
#         if not fc_name.endswith('Tbl'):
#             fc_name = fc_name.split('Tbl')[0] + 'Tbl'
#
#         dict_fields = CreateTemplates.get_field_list(tat_database, fc_name)
#
#         if field_name in dict_fields:
#             logger.info('Adding Field {}'.format(field_name))
#             fld_alias = dict_fields[field_name][0]
#             fld_type = dict_fields[field_name][1]
#             fld_width = dict_fields[field_name][2]
#             fld_precision = dict_fields[field_name][3]
#             fld_scale = dict_fields[field_name][4]
#             arcpy.AddField_management(fc, field_name=field_name, field_type=fld_type,
#                                       field_precision=fld_precision, field_scale=fld_scale,
#                                       field_length=fld_width, field_alias=fld_alias)


###############################################################################
# register event (runs the helper with different configurations)

if __name__ == '__main__':
    try:
        # Import arcpy
        import arcpy
    except Exception as e:
        logging.error('No ArcGIS licenses available to run this tool.  Program terminating.')
        sys.exit(1)
    run_app()
else:
    try:
        # Import arcpy
        import arcpy
    except Exception as e:
        logging.error('No ArcGIS licenses available to run this tool.  Program terminating.')
        sys.exit(1)
