import json
import re
import string
from typing import Dict

from fns.json_encoders import NpEncoder

# Compiled regular expressions
_re_space = re.compile(r" {2,}")
_re_hashtag = re.compile(r"#")
_re_retweet = re.compile(r"^RT[\s]+")
_re_hyperlink = re.compile(r"https?:\/\/.*[\r\n]*")
_re_hyphen_word = re.compile("[a-zA-Z]+-[a-zA-Z]+")
_re_comma = re.compile(r",{2,}")


def combine_hyphenated_word(text: str) -> str:
    """
    Combine words in text that contain hyphen.

    Example: e-email to email

    Args:
        text: A sentence

    Returns:
        Processed sentence
    """
    return " ".join(
        w.replace("-", "") if _re_hyphen_word.match(w) else w for w in text.split()
    )


def remove_hashtag(t: str) -> str:
    """
    Remove hashtag from the text.

    Args:
        t: Text

    Returns:
        Text without hashtag
    """
    return _re_hashtag.sub("", t)


def remove_retweet(t: str) -> str:
    """
    Remove RT from the text.

    Args:
        t: Text

    Returns:
        Text without RT symbol.
    """
    return _re_retweet.sub("", t)


def remove_hyperlink(t: str) -> str:
    """
    Remove hyperlinks from a text.

    Args:
        t: Text

    Returns:
        Text without hyperlinks.
    """
    return _re_hyperlink.sub("", t)


def remove_multiple_space(t: str) -> str:
    """
    Remove multiple spaces from the text.

    Adapted from: https://github.com/fastai/fastai/blob/master/fastai/text/core.py

    Args:
        t: Text

    Returns:
        Text without multiple space.
    """
    return _re_space.sub(" ", t)


def remove_multiple_commas(t: str) -> str:
    """
    Substitute multiple consecutive commas with a single comma.

    Usage:
    ```python
    >>> remove_multiple_commas('a,,b,c')
    'a,b,c'
    ```

    Args:
        t: Text

    Returns:
        Text without multiple commas.
    """
    return _re_comma.sub(",", t)


def remove_new_lines(text: str) -> str:
    """
    Strip away new lines at end.

    Args:
        t: Text

    Returns:
        Text without newline at end.
    """
    if isinstance(text, str):
        return text.replace("\\n", "").strip()
    return text


def remove_separator(text: str) -> str:
    """
    Keep only alphabet, number and space.

    Args:
        text:

    Returns:

    """
    no_separator_regex = re.compile(r"[^a-zA-Z0-9\s]")
    return no_separator_regex.sub("", text)


def remove_punctuation(text: str) -> str:
    """
    Remove all punctuations from a text.

    Args:
        text: Sentence

    """
    return "".join(t for t in text if t not in string.punctuation)


def normalize_json(json_data: Dict) -> Dict:
    """
    Convert any non-standard types in dictionary to basic types.

    The normalization prevent errors during serialization.

    Usage:
    ```python
    >>> normalize_json({'nums': np.array([1, 2, 3]})
    {'nums': [1, 2, 3]}
    ```

    Args:
        json_data: Dictionary

    Returns:
        Normalized dictionary
    """
    return json.loads(json.dumps(json_data, cls=NpEncoder))
