'''
database_maintenance_pallet.py

A module that contains a pallet defintion for performing database maintenance on a bunch
of SDE Geodatabases.
'''

from os.path import join
from time import clock

import arcpy
from forklift.models import Pallet
from forklift.seat import format_time

ANALYZE_DATA_TYPES = [
    'CadastralFabric',
    'FeatureClass',
    'GeometricNetwork',
    'LasDataset',
    'Layer',
    'Map',
    'MosaicDataset',
    'NetworkDataset',
    'PlanarGraph',
    'RasterCatalog',
    'RasterDataset',
    'RepresentationClass',
    'Table',
    'Terrain',
    'Tin'
]


class DatabaseMaintenancePallet(Pallet):
    def ship(self):
        database_infos = [
            #: (name, sde connection, [user connections])
            #: Name corresponds with the subfolder with the garage folder where the
            #: connection files are.
            ('FiberVerification', 'DC_sde@FiberVerification@itdb104sp.sde',
                ['DC_FiberAdmin@FiberVerification@itdb104sp.sde']),

            ('FFSL', 'DNR_sde@FFSL@itdb104sp.dts.utah.gov.sde',
                ['DNR_Fire@FFSL@itdb104sp.dts.utah.gov.sde',
                 'DNR_Forestry@FFSL@itdb104sp.dts.utah.gov.sde',
                 'DNR_Lands@FFSL@itdb104sp.dts.utah.gov.sde']),

            ('PLSSFabric', 'sde.sde', ['admin.sde']),

            ('SGID', 'SGID_sde@SGID@internal.agrc.utah.gov.sde',
                ['SGID_Bioscience@SGID@internal.agrc.utah.gov.sde',
                 'SGID_Boundaries@SGID@internal.agrc.utah.gov.sde',
                 'SGID_Cadastre@SGID@internal.agrc.utah.gov.sde',
                 'SGID_Climate@SGID@internal.agrc.utah.gov.sde',
                 'SGID_Demographics@SGID@internal.agrc.utah.gov.sde',
                 'SGID_Economy@SGID@internal.agrc.utah.gov.sde',
                 'SGID_Elevation@SGID@internal.agrc.utah.gov.sde',
                 'SGID_Energy@SGID@internal.agrc.utah.gov.sde',
                 'SGID_Environment@SGID@internal.agrc.utah.gov.sde',
                 'SGID_Farming@SGID@internal.agrc.utah.gov.sde',
                 'SGID_Geoscience@SGID@internal.agrc.utah.gov.sde',
                 'SGID_Health@SGID@internal.agrc.utah.gov.sde',
                 'SGID_History@SGID@internal.agrc.utah.gov.sde',
                 'SGID_Indices@SGID@internal.agrc.utah.gov.sde',
                 'SGID_Location@SGID@internal.agrc.utah.gov.sde',
                 'SGID_Meta@SGID@internal.agrc.utah.gov.sde',
                 'SGID_Planning@SGID@internal.agrc.utah.gov.sde',
                 'SGID_Political@SGID@internal.agrc.utah.gov.sde',
                 'SGID_Recreation@SGID@internal.agrc.utah.gov.sde',
                 'SGID_Society@SGID@internal.agrc.utah.gov.sde',
                 'SGID_Transportation@SGID@internal.agrc.utah.gov.sde',
                 'SGID_Utilities@SGID@internal.agrc.utah.gov.sde',
                 'SGID_Water@SGID@internal.agrc.utah.gov.sde']),

            ('UDNR', 'DNR_sde@UDNR@itdb104sp.dts.utah.gov.sde',
                ['DNR_DPR@UDNR@itdb104sp.dts.utah.gov.sde',
                 'DNR_DWR@UDNR@itdb104sp.dts.utah.gov.sde',
                 'DNR_FFSL@UDNR@itdb104sp.dts.utah.gov.sde',
                 'DNR_OGM@UDNR@itdb104sp.dts.utah.gov.sde',
                 'DNR_UGS@UDNR@itdb104sp.dts.utah.gov.sde',
                 'DNR_WRE@UDNR@itdb104sp.dts.utah.gov.sde',
                 'DNR_WRT@UDNR@itdb104sp.dts.utah.gov.sde']),

            ('UDPR', 'DNR_sde@UDPR@itdb104sp.dts.utah.gov.sde',
                ['DNR_OHV@UDPR@itdb104sp.dts.utah.gov.sde',
                 'DNR_susanz@UDPR@itdb104sp.dts.utah.gov.sde']),

            ('UDWR', 'DNR_sde@UDWR@udwr.agrc.utah.gov.sde', ['DNR_DWRADMIN@UDWR@itdb104sp.dts.utah.gov.sde']),

            ('UEMP', 'sde@UEMP@itdb104sp.dts.utah.gov.sde', ['uempadmin@UEMP@uemp.agrc.utah.gov.sde']),

            ('UGGP', 'sde@UGGP@uggp.agrc.utah.gov.sde', ['uggpadmin@UGGP@uggp.agrc.utah.gov.sde']),

            ('UGHP', 'sde@UGHP@itdb104sp.dts.utah.gov.sde', ['ughpadmin@UGHP@itdb104sp.dts.utah.gov.sde']),

            ('UGIO', 'DNR_sde@UGIO@ugio.agrc.utah.gov.sde', ['DNR_ugioadmin@UGIO@ugio.agrc.utah.gov.sde']),

            ('UGMP', 'DC_sde@UGMP@ugmp.agrc.utah.gov.sde', ['DNR_UGMPADMIN@UGMP@ugmp.agrc.utah.gov.sde']),

            ('UTAX', 'DC_sde@UTAX@itdb104sp.dts.utah.gov.sde', ['DC_ustccass@UTAX@utax.agrc.utah.gov.sde']),

            ('UTRANS', 'DC_sde@UTRANS@utrans.agrc.utah.gov.sde', ['DC_TRANSADMIN@UTRANS@utrans.agrc.utah.gov.sde']),
            
            ('Electrofishing', 'sde@Electrofishing@electrofishing.agrc.utah.gov.sde', ['WildAdmin@Electrofishing@electrofishing.agrc.utah.gov.sde'])
        ]

        results = list(map(self.run, [(self.garage,) + info for info in database_infos]))

        #: log times
        for result in results:
            self.log.info('Compress/Analyze time for {}: {}'.format(result.name, format_time(result.elapsed_time)))

        if False in [result.success for result in results]:
            message = '\n\n'.join([result.error_message for result in results if result.error_message is not None])
            self.log.error('Error: ' + message)
            self.success = (False, message)


    def run(self, database_info):
        try:
            db = Database(self.log, *database_info)
            return db.run()
        except Exception:
            import traceback
            message = traceback.format_exc()

            return Result(database_info[0], False, 'Error with Database {}: {}'.format(database_info[1], message))


class Database(object):
    def __init__(self, logger, garage, name, sde_connection, user_connections=[]):
        self.sde_connection = join(garage, name, sde_connection)
        self.user_connections = [join(garage, name, connection) for connection in user_connections]
        self.name = name
        self.log = logger

    def run(self):
        self.log.info('compressing and analyzing: ' + self.name)
        start_time = clock()
        result = Result(self.name)

        arcpy.management.Compress(self.sde_connection)
        arcpy.management.AnalyzeDatasets(self.sde_connection, 'SYSTEM')

        for connection in self.user_connections:
            user_name = arcpy.Describe(connection).connectionProperties.user
            self.log.info('user: ' + user_name)
            tables = []
            for dirpath, dirnames, walked_tables in arcpy.da.Walk(connection, datatype=ANALYZE_DATA_TYPES):
                #: filter for tables owned by the user
                tables += [table for table in walked_tables if table.split('.')[1].upper() == user_name.upper()]

            if len(tables) > 0:
                temp_start = clock()
                arcpy.management.AnalyzeDatasets(connection, 'NO_SYSTEM', tables)
                self.log.info(format_time(clock() - temp_start))
            else:
                message = 'no tables found for user connection: ' + connection
                result.success = False
                result.error_message = '{}: {}'.format(self.name, message)

        result.elapsed_time = clock() - start_time

        return result


class Result(object):
    def __init__(self, name, success=True, error_message=None, elapsed_time=0):
        self.name = name
        self.success = success
        self.error_message = error_message
        self.elapsed_time = elapsed_time


if __name__ == '__main__':
    pallet = DatabaseMaintenancePallet()
    pallet.configure_standalone_logging()
    pallet.ship()
