"""
Default feature encoding functions and pipelines
for automated feature transformation.
"""

from sklearn.pipeline import Pipeline 
from sklearn.preprocessing import OneHotEncoder
from sklearn.feature_extraction.text import CountVectorizer
from sklearn.feature_extraction import DictVectorizer
from sklearn.feature_selection import VarianceThreshold
from sklearn.preprocessing import StandardScaler
from sklearn.impute import SimpleImputer

from ..preprocessing import (
    ImputeNull, SelectField, FeatureCast, 
    LabelEncoderPipe, HashingVectorizerChunked,
    MultihotEncoder
    )

def tokenizer(x):
    """ Trivial tokenizer """
    return x

dict_encoder = lambda c: [(
                "{0}_dict_encoder".format(c),
                Pipeline(steps=[
                    ("var", SelectField(cols=[c], single_dimension=True)),
                    ("fillna", ImputeNull({})),
                    ("vec", DictVectorizer())])  
                )]

onehot_encoder = lambda c: [(
                "{0}_onehot".format(c), 
                 Pipeline(steps=[
                     ("var", SelectField(cols=[c], single_dimension=True)),
                     ("cast", FeatureCast(cast_type=str)),
                     ("fillna", ImputeNull("")),
                     ("vec", CountVectorizer(
                         tokenizer=tokenizer, 
                         binary=True,
                         decode_error="ignore"))])
                )]

multihot_encoder = lambda c: [(
                "{0}_multihot".format(c), 
                Pipeline(steps=[
                   ("var", SelectField(cols=[c], single_dimension=True)),
                   ("fillna", ImputeNull([])),
                   ("vec", MultihotEncoder())])
                )]

numeric_encoder = lambda c: [(
                "{0}_scaler".format(c),
                Pipeline(steps=[
                    ("var", SelectField(cols=[c])),
                    ("imputer", SimpleImputer(strategy="median")), 
                    ("scaler", StandardScaler(copy=False))])
                )]

_default_encoders = {
    "small": {
        "string_vectorizer": lambda c: [(
                "{0}_word_vec".format(c), 
                 Pipeline(steps=[
                     ("var", SelectField(cols=[c], single_dimension=True)),
                     ("fillna", ImputeNull(" ")), 
                     ("vec", HashingVectorizerChunked(
                         ngram_range=(1,2), 
                         analyzer="word", 
                         decode_error="ignore")),
                     ("var_thresh", VarianceThreshold())])
                )],
        "onehotencoder": onehot_encoder,
        "multihotencoder": multihot_encoder,
        "numeric": numeric_encoder,
        "dict": dict_encoder
    },
    "medium": {
        "string_vectorizer": lambda c: [(
                    "{0}_word_vec".format(c), 
                     Pipeline(steps=[
                         ("var", SelectField(cols=[c], single_dimension=True)),
                         ("fillna", ImputeNull(" ")), 
                         ("vec", HashingVectorizerChunked(
                             ngram_range=(1,3), 
                             analyzer="word", 
                             decode_error="ignore")),
                         ("var_thresh", VarianceThreshold())])
                    ),
                    (
                    "{0}_char_vec".format(c), 
                     Pipeline(steps=[
                         ("var", SelectField(cols=[c], single_dimension=True)),
                         ("fillna", ImputeNull(" ")), 
                         ("vec", HashingVectorizerChunked(
                             ngram_range=(3,4), 
                             analyzer="char_wb", 
                             decode_error="ignore")),
                         ("var_thresh", VarianceThreshold())])
                    )
                ],
        "onehotencoder": onehot_encoder,
        "multihotencoder": multihot_encoder,
        "numeric": numeric_encoder,
        "dict": dict_encoder
    },
    "large": {
        "string_vectorizer": lambda c: [(
                    "{0}_word_vec".format(c), 
                     Pipeline(steps=[
                         ("var", SelectField(cols=[c], single_dimension=True)),
                         ("fillna", ImputeNull(" ")), 
                         ("vec", HashingVectorizerChunked(
                             ngram_range=(1,3), 
                             analyzer="word", 
                             decode_error="ignore")),
                         ("var_thresh", VarianceThreshold())])
                    ),
                    (
                    "{0}_char_vec".format(c), 
                     Pipeline(steps=[
                         ("var", SelectField(cols=[c], single_dimension=True)),
                         ("fillna", ImputeNull(" ")), 
                         ("vec", HashingVectorizerChunked(
                             ngram_range=(2,5), 
                             analyzer="char_wb", 
                             decode_error="ignore")),
                         ("var_thresh", VarianceThreshold())])
                    )
                ],
        "onehotencoder": onehot_encoder,
        "multihotencoder": multihot_encoder,
        "numeric": numeric_encoder,
        "dict": dict_encoder
    }
}
