# -*- coding: utf-8 -*-
# author: 王树根
# email: wangshugen@ict.ac.cn
# date: 2018/11/19 09:30
from __future__ import division
from __future__ import print_function

import functools
import sys

from .stringext import as_json
from ..compat import python3


def _add_indent(lines, space_cnt):
    """
    add blank before message

    :param lines: lines to be operated
    :type lines: Iterable of str

    :param space_cnt: space number
    :type space_cnt: int

    :return: lines with each started with space_cnt blanks
    """
    s = lines.split('\n')
    # don't do anything for single-line stuff
    if len(s) == 1:
        return lines
    first = s.pop(0)
    s = [(space_cnt * ' ') + line for line in s]
    s = '\n'.join(s)
    s = first + '\n' + s
    return s


"""
Whether enable message out or not
"""
_enable = True


def it_print(message='', indent=None, device=1, newline=True, json_fmt=False):
    """
    in time print: print one line to console immediately

    :param message: the message to be printed
    :type message: object

    :param indent: number of blank to be indented, default 0
    :type indent: int

    :param device: stdout -> 1, stderr -> 2, default 1
    :type device: int

    :param newline: whether to append a new line, default True
    :type newline: bool

    :param json_fmt: whether to print as json
    :type json_fmt: bool
    """
    global _enable
    if not _enable or device is None:
        return

    if message is None:
        message = str(None)
    else:
        if not json_fmt:
            if indent is None:
                indent = 0
            message = ' ' * indent + str(message)
        else:
            message = as_json(message, indent=indent)

    if device == 2:
        device = sys.stderr
        message = '\033[0;31m%s\033[0m' % message
    elif device == 1:
        device = sys.stdout

    # a file-like object
    assert hasattr(device, 'write')

    kwargs = dict(file=device,
                  end='\n' if newline else '')
    if python3:
        kwargs['flush'] = True
    print(message, **kwargs)


def it_prints(message='', indent=None, indent_inner=2, device=1, newline=True):
    """
    in time print multiple lines: first indent with indent blanks, then every line is indented with indent_inner blanks
    """
    if message is not None:
        message = _add_indent(message, indent_inner)
    it_print(message, indent=indent, device=device, newline=newline)


def _set_enabled(enable):
    global _enable
    _enable = enable


def is_print_enable():
    """
    get the current printable status
    """
    return _enable


def set_print_enable():
    _set_enabled(True)


def set_print_disable():
    _set_enabled(False)


class disable_print(object):
    def __init__(self):
        self.prev = is_print_enable()

    def __enter__(self):
        set_print_disable()

    def __exit__(self, *args):
        _set_enabled(self.prev)
        return False

    def __call__(self, func):
        @functools.wraps(func)
        def decorate_disable_print(*args, **kwargs):
            with self:
                return func(*args, **kwargs)

        return decorate_disable_print


class enable_print(object):
    def __init__(self):
        self.prev = is_print_enable()

    def __enter__(self):
        set_print_enable()

    def __exit__(self, *args):
        _set_enabled(self.prev)
        return False

    def __call__(self, func):
        @functools.wraps(func)
        def decorate_disable_print(*args, **kwargs):
            with self:
                return func(*args, **kwargs)

        return decorate_disable_print
