# -*- coding: utf-8 -*-

from collections import namedtuple

import planta
from ppms.migration import SQLPacket, PacketCategory, MinVersionDependency, MaxVersionDependency, \
    VersionType
from ppms.server_constants import SYS_VAR_LICENSE

ColumnConfiguration = namedtuple('ColumnConfiguration', ['db_type', 'df_type', 'ppms_type'])
ColumnSetting = namedtuple('ColumnSetting', ['column_type', 'di_class', 'sql_default_value'])
configurations_to_setting = {ColumnConfiguration('X', 'AL', 'AL'): ColumnSetting('5', '0', ''),  # Alpha
                             ColumnConfiguration('X', 'ALG', 'ALG'): ColumnSetting('6', '0', ''),  # Alpha, gross
                             ColumnConfiguration('', '', '-'): ColumnSetting('320', '1', ''),  # Bars
                             ColumnConfiguration('X', 'AM', 'AM'): ColumnSetting('9', '0', ''),  # Email
                             ColumnConfiguration('X', 'AP', 'AP'): ColumnSetting('10', '0', ''),  # Telephone
                             ColumnConfiguration('N8', 'C', 'C'): ColumnSetting('14', '0', ''),  # Currency
                             ColumnConfiguration('N4', 'T', 'D'): ColumnSetting('15', '0', '01.01.70'),  # Date
                             ColumnConfiguration('X', 'AL', 'HL'): ColumnSetting('16', '16', ''),  # Hyperlink
                             ColumnConfiguration('X', 'AL', 'IT'): ColumnSetting('17', '15', ''),  # I-Text
                             ColumnConfiguration('X', 'AL', 'ITG'): ColumnSetting('18', '15', ''),  # I-Text, capital
                             ColumnConfiguration('N2', 'P', 'L'): ColumnSetting('19', '0', ''),  # Relations
                             ColumnConfiguration('N2', 'N', 'N2'): ColumnSetting('20', '0', ''),  # Number (2)
                             ColumnConfiguration('N4', 'N', 'N4'): ColumnSetting('21', '0', ''),  # Number (4)
                             ColumnConfiguration('N8', 'N', 'N8'): ColumnSetting('22', '0', ''),  # Number (8)
                             ColumnConfiguration('N4', 'U', 'I'): ColumnSetting('24', '0', ''),  # Time
                             ColumnConfiguration('N2', 'Y', 'Y'): ColumnSetting('26', '0', '0'),  # Boolean
                             ColumnConfiguration('X', 'AL', 'CLOB'): ColumnSetting('27', '19', ''),  # Clob
                             ColumnConfiguration('N2', 'O', 'O'): ColumnSetting('278', '0', ''),  # object protection
                             ColumnConfiguration('', '', ''): ColumnSetting('305', '0', ''),  # incarnation or bars
                             ColumnConfiguration('ID', 'I', 'UUID'): ColumnSetting('321', '0', '')  # uuid
                             }


class FillColumnType(SQLPacket):
    """Fills the column typ for all DIs with current license where it is empty."""
    done_after_success = True
    run_on_startup = True
    category = PacketCategory.CATEGORY_MANDATORY
    wi_number = 18872

    get_columns = """select di.DI000238, di.DI000253, di.DI000244, di.DI003141 from DT412 di
                        inner join DT415 dt on dt.DI000265 = di.DI000239
                        inner join DT420 s on s.DI000289 = dt.DI000266
                    where di.DI041246 = 0 and di.ENABLED = 1 and di.DI001869 = '{license}'
                    and dt.ENABLED = 1 and s.ENABLED = 1"""

    update_column_type = """update DT412 di set di.DI041246 = '{column_type}'{settings}
                                where di.DI000238 = '{di_number}'"""

    check_default_value = """select DI026799 from DT412 where DI000238 = '{di_number}'"""

    check_di_class = """select DI001700 from DT412 where DI000238 = '{di_number}'"""

    failed_dis = []

    def get_dependencies(self):
        return (MinVersionDependency(version='39.5.9', version_type=VersionType.CUSTOMIZING),
                MaxVersionDependency(version='39.5.9', version_type=VersionType.CUSTOMIZING))

    def get_all_dataitems_without_column_type(self, license):
        for di_number, db_type, df_type, ppms_type in planta.db_select(self.get_columns.format(license=license)):
            yield di_number, ColumnConfiguration(db_type, df_type, ppms_type)

    def di_has_default_value(self, di_number):
        return bool(planta.db_select(self.check_default_value.format(di_number=di_number))[0][0])

    def di_has_di_class(self, di_number):
        return bool(planta.db_select(self.check_di_class.format(di_number=di_number))[0][0])

    def set_column_type(self, di_number, column_setting):
        settings = ""
        if column_setting.di_class and not self.di_has_di_class(di_number):
            settings = ", DI001700 = '{di_class}'".format(di_class=column_setting.di_class)
        if column_setting.sql_default_value and not self.di_has_default_value(di_number):
            settings += ", DI026799 = '{sql_default_value}'".format(
                sql_default_value=column_setting.sql_default_value)

        self.modify_and_log(self.update_column_type.format(di_number=di_number, column_type=column_setting.column_type,
                                                           settings=settings))

    def log_column_with_unknown_type(self):
        self.log(
            'Could not find the correct column type for the following DIs. Please check whether the customizing is '
            'correct: \n{di_numbers}'.format(di_numbers=str(self.failed_dis)).replace('[', '').replace(']', ''))

    def fix(self, packet_runner):
        system_license = planta.uvar_get(SYS_VAR_LICENSE)
        self.log("Starting the update of all active DIs with license " + system_license)

        for di_number, column_configuration in self.get_all_dataitems_without_column_type(system_license):
            column_setting = configurations_to_setting.get(column_configuration, None)

            if column_setting is not None:
                self.set_column_type(di_number, column_setting)
            else:
                self.failed_dis.append(di_number)

        if self.failed_dis:
            self.log_column_with_unknown_type()
            return self.fail("Not all column types could be determined. Please check the customizing manually!")

        return self.success()
