import re
from django.conf import settings
from evennia.utils.ansi import strip_ansi
from evennia.utils.utils import make_iter, to_str, wrap

def capitalize(text):
    #allow ellipses to force lower case.
    if not "..." in text[0:4]:
        list_text = text
        if text.startswith("|"):
            list_text = text[2:]

        for character in list_text:
            #find the first alpha value and capitalize it, then break loop
            if character.isalpha():
                i = text.index(character)
                if i == 0:
                    text = text[i].upper() + text[i+1:]
                else:
                    text = text[0:i] + text[i].upper() + text[i+1:]
                break

    return text

def get_sw(caller):  
    try:
        session = caller.sessions.all()[0]
        sw = session.protocol_flags.get("SCREENWIDTH")[0]
    except Exception:
        sw = settings.CLIENT_DEFAULT_WIDTH

    return sw

def grammarize(text, ending='.'):
    text = text.strip()
    if not text.endswith((".", "!", "?", ".'", "!'", "?'", '."', '!"', '?"')):
        text += ending

    if text[-2] == " ":
        text = text[:-2] + text[-1]
        
    return text

def list_to_string(initer, endsep=", and", addquote=False):
    """
    This pretty-formats an iterable list as string output, adding an optional
    alternative separator to the second to last entry.  If `addquote`
    is `True`, the outgoing strings will be surrounded by quotes.

    Args:
        initer (any): Usually an iterable to print. Each element must be possible to
            present with a string. Note that if this is a generator, it will be
            consumed by this operation.
        endsep (str, optional): If set, the last item separator will
            be replaced with this value.
        addquote (bool, optional): This will surround all outgoing
            values with double quotes.

    Returns:
        liststr (str): The list represented as a string.
        
    Examples:
        ```python
         # no endsep:
            [1,2,3] -> '1, 2, 3'
         # with endsep=='and':
            [1,2,3] -> '1, 2 and 3'
         # with addquote and endsep
            [1,2,3] -> '"1", "2" and "3"'
        ```
    """
    if not endsep:
        endsep = ","

    if not initer:
        return ""
    initer = tuple(str(val) for val in make_iter(initer))
    if addquote:
        if len(initer) == 1:
            return '"%s"' % initer[0]
        return ", ".join('"%s"' % v for v in initer[:-1]) + "%s %s" % (endsep, '"%s"' % initer[-1])
    else:
        if len(initer) == 1:
            return str(initer[0])
        elif len(initer) == 2:
            return " and ".join(str(v) for v in initer)
        else:
            return ", ".join(str(v) for v in initer[:-1]) + "%s %s" % (endsep, initer[-1])


def wrap(text, text_width=None, screen_width=None, pre_text="", 
         omit_pre_text=False, indent=0, align="l"):
    
    # Format Text
    text_width = text_width if text_width else settings.CLIENT_DEFAULT_WIDTH
    screen_width = screen_width if screen_width else settings.CLIENT_DEFAULT_WIDTH

    text_width = text_width-indent
    screen_width = screen_width-indent

    if screen_width is not None:
        text_lines = re.split(r"\n|\|/", text)
        if not omit_pre_text:
            final_text = pre_text
        else:
            final_text = ""
        first_line = True
        for x in text_lines:
            word_list = re.findall(r"((?:\S+\s*)|(?:^\s+))", x)
            line_list = []
            line_len = len(x) - len(strip_ansi(x))
            line_available_char = text_width - len(strip_ansi(pre_text))# + line_len
            line = ""
            for y in word_list:
                line_available_char = line_available_char + (len(y)-len(strip_ansi(y)))
                if (len(y) <= line_available_char):
                    line += y
                    line_available_char = line_available_char - len(y)
                else:
                    if (len(y) > text_width - len(strip_ansi(pre_text))):
                        line = ""
                        line_available_char = text_width - len(strip_ansi(pre_text))
                        character_list = re.findall(r"((?:\|[bBcCgGmMrRwWxXyY])|\|\d{3}|(?:.))", y)
                        for character in character_list:
                            if (len(character) <= line_available_char):
                                line += character
                                if not character in character_list:
                                    line_available_char = line_available_char - len(character)
                                    
                            else:
                                line_list.append(line)
                                line = character
                                if character in character_list:
                                    line_available_char = text_width - len(strip_ansi(pre_text))
                                else:
                                    line_available_char = text_width - len(strip_ansi(pre_text)) - len(character)
                    else:
                        line_list.append(line)
                        line = y
                        line_available_char = text_width - len(strip_ansi(pre_text)) - len(y) + (len(y)-len(strip_ansi(y)))
            line_list.append(line)
            for y in line_list:
                if ((len(y) - len(strip_ansi(y))) > 0):
                    spaces = len(y) - len(strip_ansi(y))
                else:
                    spaces = 0
                        
                line_text = ""
        
                if first_line:
                    final_text = justify(final_text, width=screen_width+spaces, align=align, indent=indent)
                    line_text = justify(y, width=screen_width+spaces, align=align)
                else:
                    line_text = justify(y, width=screen_width+spaces, align=align, indent=len(strip_ansi(pre_text))+indent)

                final_text += line_text+"|/"
                first_line = False
    final_text = final_text[:-2]
    return final_text + "|n"

def justify(text, width=settings.CLIENT_DEFAULT_WIDTH, align="l", indent=0):
    
    if align == "l":
               #|n
        return " "*indent + text
    elif align == "c":
        return " "*int(((width/2)-(len(text)/2))) + text

    return text

import re
from django.conf import settings
from evennia.utils.ansi import strip_ansi
from evennia.utils.utils import make_iter, to_str, wrap

def capitalize(text):
    #allow ellipses to force lower case.
    if not "..." in text[0:4]:
        list_text = text
        if text.startswith("|"):
            list_text = text[2:]

        for character in list_text:
            #find the first alpha value and capitalize it, then break loop
            if character.isalpha():
                i = text.index(character)
                if i == 0:
                    text = text[i].upper() + text[i+1:]
                else:
                    text = text[0:i] + text[i].upper() + text[i+1:]
                break

    return text

def get_sw(caller):  
    try:
        session = caller.sessions.all()[0]
        sw = session.protocol_flags.get("SCREENWIDTH")[0]
    except Exception:
        sw = settings.CLIENT_DEFAULT_WIDTH

    return sw

def grammarize(text, ending='.'):
    text = text.strip()
    if not text.endswith((".", "!", "?", ".'", "!'", "?'", '."', '!"', '?"')):
        text += ending

    if text[-2] == " ":
        text = text[:-2] + text[-1]
        
    return text

def list_to_string(initer, endsep=", and", addquote=False):
    """
    This pretty-formats an iterable list as string output, adding an optional
    alternative separator to the second to last entry.  If `addquote`
    is `True`, the outgoing strings will be surrounded by quotes.

    Args:
        initer (any): Usually an iterable to print. Each element must be possible to
            present with a string. Note that if this is a generator, it will be
            consumed by this operation.
        endsep (str, optional): If set, the last item separator will
            be replaced with this value.
        addquote (bool, optional): This will surround all outgoing
            values with double quotes.

    Returns:
        liststr (str): The list represented as a string.
        
    Examples:
        ```python
         # no endsep:
            [1,2,3] -> '1, 2, 3'
         # with endsep=='and':
            [1,2,3] -> '1, 2 and 3'
         # with addquote and endsep
            [1,2,3] -> '"1", "2" and "3"'
        ```
    """
    if not endsep:
        endsep = ","

    if not initer:
        return ""
    initer = tuple(str(val) for val in make_iter(initer))
    if addquote:
        if len(initer) == 1:
            return '"%s"' % initer[0]
        return ", ".join('"%s"' % v for v in initer[:-1]) + "%s %s" % (endsep, '"%s"' % initer[-1])
    else:
        if len(initer) == 1:
            return str(initer[0])
        elif len(initer) == 2:
            return " and ".join(str(v) for v in initer)
        else:
            return ", ".join(str(v) for v in initer[:-1]) + "%s %s" % (endsep, initer[-1])


def wrap(text, text_width=None, screen_width=None, pre_text="", 
         omit_pre_text=False, indent=0, align="l"):
    
    # Format Text
    text_width = text_width if text_width else settings.CLIENT_DEFAULT_WIDTH
    screen_width = screen_width if screen_width else settings.CLIENT_DEFAULT_WIDTH

    text_width = text_width-indent
    screen_width = screen_width-indent

    if screen_width is not None:
        text_lines = re.split(r"\n|\|/", text)
        if not omit_pre_text:
            final_text = pre_text
        else:
            final_text = ""
        first_line = True
        for x in text_lines:
            word_list = re.findall(r"((?:\S+\s*)|(?:^\s+))", x)
            line_list = []
            line_len = len(x) - len(strip_ansi(x))
            line_available_char = text_width - len(strip_ansi(pre_text))# + line_len
            line = ""
            for y in word_list:
                line_available_char = line_available_char + (len(y)-len(strip_ansi(y)))
                if (len(y) <= line_available_char):
                    line += y
                    line_available_char = line_available_char - len(y)
                else:
                    if (len(y) > text_width - len(strip_ansi(pre_text))):
                        line = ""
                        line_available_char = text_width - len(strip_ansi(pre_text))
                        character_list = re.findall(r"((?:\|[bBcCgGmMrRwWxXyY])|\|\d{3}|(?:.))", y)
                        for character in character_list:
                            if (len(character) <= line_available_char):
                                line += character
                                if not character in character_list:
                                    line_available_char = line_available_char - len(character)
                                    
                            else:
                                line_list.append(line)
                                line = character
                                if character in character_list:
                                    line_available_char = text_width - len(strip_ansi(pre_text))
                                else:
                                    line_available_char = text_width - len(strip_ansi(pre_text)) - len(character)
                    else:
                        line_list.append(line)
                        line = y
                        line_available_char = text_width - len(strip_ansi(pre_text)) - len(y) + (len(y)-len(strip_ansi(y)))
            line_list.append(line)
            for y in line_list:
                if ((len(y) - len(strip_ansi(y))) > 0):
                    spaces = len(y) - len(strip_ansi(y))
                else:
                    spaces = 0
                        
                line_text = ""
        
                if first_line:
                    final_text = justify(final_text, width=screen_width+spaces, align=align, indent=indent)
                    line_text = justify(y, width=screen_width+spaces, align=align)
                else:
                    line_text = justify(y, width=screen_width+spaces, align=align, indent=len(strip_ansi(pre_text))+indent)

                final_text += line_text+"|/"
                first_line = False
    final_text = final_text[:-2]
    return final_text + "|n"

def justify(text, width=settings.CLIENT_DEFAULT_WIDTH, align="l", indent=0):
    
    if align == "l":
               #|n
        return " "*indent + text
    elif align == "c":
        return " "*int(((width/2)-(len(text)/2))) + text

    return text

#allow ellipses to force lower case. #find the first alpha value and capitalize it, then break loop This pretty-formats an iterable list as string output, adding an optional     alternative separator to the second to last entry.  If `addquote`     is `True`, the outgoing strings will be surrounded by quotes.      Args:         initer (any): Usually an iterable to print. Each element must be possible to             present with a string. Note that if this is a generator, it will be             consumed by this operation.         endsep (str, optional): If set, the last item separator will             be replaced with this value.         addquote (bool, optional): This will surround all outgoing             values with double quotes.      Returns:         liststr (str): The list represented as a string.              Examples:         ```python          # no endsep:             [1,2,3] -> '1, 2, 3'          # with endsep=='and':             [1,2,3] -> '1, 2 and 3'          # with addquote and endsep             [1,2,3] -> '"1", "2" and "3"'         ``` # Format Text # + line_len #|n