#!/usr/bin/env python
# encoding: utf-8
import numbers
import os
import re
import sys
from itertools import chain

import numpy as np
import scipy.sparse as sp
import six
import pickle

from .model import get_convo_nn2
from .stop_words import THAI_STOP_WORDS
from .utils import CHAR_TYPES_MAP, CHARS_MAP, create_feature_array

MODULE_PATH = os.path.dirname(__file__)
WEIGHT_PATH = os.path.join(MODULE_PATH, 'weight', 'cnn_without_ne_ab.h5')

TOKENIZER = None

def tokenize(text, custom_dict=None):
    """
    Tokenize given Thai text string

    Input
    =====
    text: str, Thai text string
    custom_dict: str (or list), path to customized dictionary file
        It allows the function not to tokenize given dictionary wrongly.
        The file should contain custom words separated by line.
        Alternatively, you can provide list of custom words too.

    Output
    ======
    tokens: list, list of tokenized words

    Example
    =======
    >> deepcut.tokenize('ตัดคำได้ดีมาก')
    >> ['ตัดคำ','ได้','ดี','มาก']

    """
    global TOKENIZER
    if not TOKENIZER:
        TOKENIZER = DeepcutTokenizer()
    return TOKENIZER.tokenize(text, custom_dict=custom_dict)


def _custom_dict(word, text, word_end):
    word_length = len(word)
    initial_loc = 0

    while True:
        try:
            start_char = re.search(word, text).start()
            first_char = start_char + initial_loc
            last_char = first_char + word_length - 1

            initial_loc += start_char + word_length
            text = text[start_char + word_length:]
            word_end[first_char:last_char] = (word_length - 1) * [0]
            word_end[last_char] = 1
        except:
            break
    return word_end


def _document_frequency(X):
    """
    Count the number of non-zero values for each feature in sparse X.
    """
    if sp.isspmatrix_csr(X):
        return np.bincount(X.indices, minlength=X.shape[1])
    return np.diff(sp.csc_matrix(X, copy=False).indptr)


def _check_stop_list(stop):
    """
    Check stop words list
    ref: https://github.com/scikit-learn/scikit-learn/blob/master/sklearn/feature_extraction/text.py#L87-L95
    """
    if stop == "thai":
        return THAI_STOP_WORDS
    elif isinstance(stop, six.string_types):
        raise ValueError("not a built-in stop list: %s" % stop)
    elif stop is None:
        return None
    # assume it's a collection
    return frozenset(stop)


def load_model(file_path):
    """
    Load saved pickle file of DeepcutTokenizer

    Parameters
    ==========
    file_path: str, path to saved model from ``save_model`` method in DeepcutTokenizer 
    """
    tokenizer = pickle.load(open(file_path, 'rb'))
    tokenizer.model = get_convo_nn2()
    tokenizer.model = tokenizer.model.load_weights(WEIGHT_PATH)
    return tokenizer


class DeepcutTokenizer(object):
    """
    Class for tokenizing given Thai text documents using deepcut library

    Parameters
    ==========
    ngram_range : tuple, tuple for ngram range for vocabulary, (1, 1) for unigram
        and (1, 2) for bigram
    stop_words : list or set, list or set of stop words to be removed
        if None, max_df can be set to value [0.7, 1.0) to automatically remove
        vocabulary. If using "thai", this will use list of pre-populated stop words
    max_features : int or None, if provided, only consider number of vocabulary
        ordered by term frequencies
    max_df : float in range [0.0, 1.0] or int, default=1.0
        ignore terms that have a document frequency higher than the given threshold
    min_df : float in range [0.0, 1.0] or int, default=1
        ignore terms that have a document frequency lower than the given threshold
    dtype : type, optional


    Example
    =======
    raw_documents = ['ฉันอยากกินข้าวของฉัน',
                     'ฉันอยากกินไก่',
                     'อยากนอนอย่างสงบ']
    tokenizer = DeepcutTokenizer(ngram_range=(1, 1))
    X = tokenizer.fit_tranform(raw_documents) # document-term matrix in sparse CSR format

    >> X.todense()
    >> [[0, 0, 1, 0, 1, 0, 2, 1],
        [0, 1, 1, 0, 1, 0, 1, 0],
        [1, 0, 0, 1, 1, 1, 0, 0]]
    >> tokenizer.vocabulary_
    >> {'นอน': 0, 'ไก่': 1, 'กิน': 2, 'อย่าง': 3, 'อยาก': 4, 'สงบ': 5, 'ฉัน': 6, 'ข้าว': 7}

    """

    def __init__(self, ngram_range=(1, 1), stop_words=None,
                 max_df=1.0, min_df=1, max_features=None, dtype=
np.dtype('float64')