
from peewee import Model
from .database import mysql_db, mysql_db_suivi_prod
from .database import MYSQL_DB_CHARSET, MYSQL_DB_COLLATION
import logging

logger = logging.getLogger('median')


class SqlViewException(Exception):
    def __init__(self, message):
        self.message = message


class MedianLibException(Exception):
    def __init__(self, message):
        self.message = message


class BaseModel(Model):
    """A base model that will use our MySQL database"""

    @staticmethod
    def is_sql_view():
        return False

    class Meta:
        database = mysql_db
        table_settings = [
            'ENGINE=MyISAM',
            'DEFAULT CHARSET=%s' % MYSQL_DB_CHARSET,
            'COLLATE=%s' % MYSQL_DB_COLLATION
        ]


class InnodbModel(Model):
    """A base model that will use our MySQL database with InnoDb engine"""

    @staticmethod
    def is_sql_view():
        return False

    class Meta:
        database = mysql_db
        table_settings = [
            'ENGINE=InnoDB',
            'DEFAULT CHARSET=%s' % MYSQL_DB_CHARSET,
            'COLLATE=%s' % MYSQL_DB_COLLATION
        ]


class BaseModelSqlView(Model):
    """A base model that will use our MySQL database"""

    @staticmethod
    def is_sql_view():
        return True

    def save(self):
        """insert or update are not allowed in SQL view"""
        raise SqlViewException('Insert or update not allowed in SQL view model')

    def create_view(self):
        raise SqlViewException('Need inherit to create the view')

    def delete_view(self, cascade=False):
        mysql_db.execute_sql('DROP VIEW %s %s' % (self._meta.table_name, 'CASCADE' if cascade else ''))
        logger.info('DROP VIEW %s %s' % (self._meta.table_name, 'CASCADE' if cascade else ''))
        # raise SqlViewException('Need inherit to drop a view')

    class Meta:
        database = mysql_db
        table_settings = ['ENGINE=MyISAM', 'DEFAULT CHARSET=utf8']


class BaseModelSuiviProd(Model):
    """A base model that will use our MySQL database"""

    @staticmethod
    def is_sql_view():
        return False

    class Meta:
        database = mysql_db_suivi_prod
        table_settings = ['ENGINE=MyISAM', 'DEFAULT CHARSET=utf8']


class BaseViewException(Exception):
    def __init__(self, message):
        self.message = message


class BaseViewNotImplemented(Exception):
    def __init__(self, message):
        self.message = message


class BaseViewDuplicate(Exception):
    def __init__(self, message):
        self.message = message


class BaseView:
    """
    Business object to add standard function
    """

    id = 0

    def __init__(self):
        """Initialise BaseView class"""
        pass

    #
    # Fonction publique
    #
    def creer(self):
        raise BaseViewNotImplemented('Fonction creer() non implementée')

    def modifier(self):
        raise BaseViewNotImplemented('Fonction modifier() non implementée')

    def supprimer(self):
        raise BaseViewNotImplemented('Fonction supprimer() non implementée')

    def lire(self):
        raise BaseViewNotImplemented('Fonction lire() non implementée')

    def mandatory(self, data, message=""):
        """Return an axception if data is None"""
        if data is None:
            raise BaseViewException(message)

    def non_zero(self, data, message=""):
        if data is None or data == 0:
            raise BaseViewException(message)

    def render_query(self, query: str) -> list:
        """Execute a query and return the result a list of dict"""

        cr = mysql_db.execute_sql(query)
        column_names = [x[0] for x in cr.description]
        return [dict(zip(column_names, row)) for row in cr.fetchall()]

    #
    # Fonction privée
    #

    @staticmethod
    def _protect(data):
        """
        Protège les données avant de les envoyés en tant que requête SQL
        """
        data = data.replace("\\", "\\\\")
        data = data.replace("'", "\\'")
        data = data.replace('"', '\\"')
        return data
