import warnings

from flask.ext.admin.babel import gettext
from flask.ext.admin.model import filters
from flask.ext.admin.contrib.sqla import tools


class BaseSQLAFilter(filters.BaseFilter):
    """
        Base SQLAlchemy filter.
    """
    def __init__(self, column, name, options=None, data_type=None):
        """
            Constructor.

            :param column:
                Model field
            :param name:
                Display name
            :param options:
                Fixed set of options
            :param data_type:
                Client data type
        """
        super(BaseSQLAFilter, self).__init__(name, options, data_type)

        self.column = column


# Common filters
class FilterEqual(BaseSQLAFilter):
    def apply(self, query, value):
        return query.filter(self.column == value)

    def operation(self):
        return gettext('equals')


class FilterNotEqual(BaseSQLAFilter):
    def apply(self, query, value):
        return query.filter(self.column != value)

    def operation(self):
        return gettext('not equal')


class FilterLike(BaseSQLAFilter):
    def apply(self, query, value):
        stmt = tools.parse_like_term(value)
        return query.filter(self.column.ilike(stmt))

    def operation(self):
        return gettext('contains')


class FilterNotLike(BaseSQLAFilter):
    def apply(self, query, value):
        stmt = tools.parse_like_term(value)
        return query.filter(~self.column.ilike(stmt))

    def operation(self):
        return gettext('not contains')


class FilterGreater(BaseSQLAFilter):
    def apply(self, query, value):
        return query.filter(self.column > value)

    def operation(self):
        return gettext('greater than')


class FilterSmaller(BaseSQLAFilter):
    def apply(self, query, value):
        return query.filter(self.column < value)

    def operation(self):
        return gettext('smaller than')


# Customized type filters
class BooleanEqualFilter(FilterEqual, filters.BaseBooleanFilter):
    pass


class BooleanNotEqualFilter(FilterNotEqual, filters.BaseBooleanFilter):
    pass


# Base SQLA filter field converter
class FilterConverter(filters.BaseFilterConverter):
    strings = (FilterEqual, FilterNotEqual, FilterLike, FilterNotLike)
    numeric = (FilterEqual, FilterNotEqual, FilterGreater, FilterSmaller)
    bool = (BooleanEqualFilter, BooleanNotEqualFilter)
    enum = (FilterEqual, FilterNotEqual)

    def convert(self, type_name, column, name, **kwargs):
        if type_name in self.converters:
            return self.converters[type_name](column, name, **kwargs)

        return None

    @filters.convert('String', 'Unicode', 'Text', 'UnicodeText')
    def conv_string(self, column, name, **kwargs):
        return [f(column, name, **kwargs) for f in self.strings]

    @filters.convert('Boolean')
    def conv_bool(self, column, name, **kwargs):
        return [f(column, name, **kwargs) for f in self.bool]

    @filters.convert('Integer', 'SmallInteger', 'Numeric', 'Float', 'BigInteger')
    def conv_int(self, column, name, **kwargs):
        return [f(column, name, **kwargs) for f in self.numeric]

    @filters.convert('Date')
    def conv_date(self, column, name, **kwargs):
        return [f(column, name, data_type='datepicker', **kwargs) for f in self.numeric]

    @filters.convert('DateTime')
    def conv_datetime(self, column, name, **kwargs):
        return [f(column, name, data_type='datetimepicker', **kwargs) for f in self.numeric]

    @filters.convert('Enum', 'ENUM')
    def conv_enum(self, column, name, options=None, **kwargs):
        if not options:
            options = [
                (v, v)
                for v in column.type.enums
            ]
        return [f(column, name, options, **kwargs) for f in self.enum]

@@ -2511,16 +2511,24 @@
 ype_name
+.lower()
  in self
@@ -2584,16 +2584,24 @@
 ype_name
+.lower()
 %5D(column
@@ -2662,17 +2662,17 @@
 onvert('
-S
+s
 tring', 
@@ -2668,25 +2668,25 @@
 ('string', '
-U
+u
 nicode', 'Te
@@ -2687,24 +2687,24 @@
 ', '
-T
+t
 ext', '
-U
+u
 nicode
-T
+t
 ext'
@@ -2844,17 +2844,17 @@
 onvert('
-B
+b
 oolean')
@@ -2988,17 +2988,17 @@
 onvert('
-I
+i
 nteger',
@@ -3003,14 +3003,14 @@
 ', '
-S
+s
 mall
-I
+i
 nteg
@@ -3015,17 +3015,17 @@
 eger', '
-N
+n
 umeric',
@@ -3030,17 +3030,17 @@
 ', '
-F
+f
 loat', '
 BigI
@@ -3039,12 +3039,12 @@
 ', '
-BigI
+bigi
 nteg
@@ -3184,17 +3184,17 @@
 onvert('
-D
+d
 ate')%0A  
@@ -3356,13 +3356,13 @@
 rt('
-DateT
+datet
 ime'
@@ -3536,21 +3536,13 @@
 rt('
-E
+e
 num'
-, 'ENUM'
 )%0A  

Remove case sensitivity for column types (columns can be DATE)