"""Various functions for prettifying text, useful when cipher routines generate
strings of letters without spaces.
"""

import string
from szyfrow.support.segment import segment
from szyfrow.support.utilities import cat, lcat, sanitise


def prettify(text, width=100):
    """Segment a text into words, then pack into lines, and combine the lines
    into a single string for printing."""
    return lcat(tpack(segment(text), width=width))


def tpack(text, width=100):
    """Pack a list of words into lines, so long as each line (including
    intervening spaces) is no longer than _width_"""
    lines = [text[0]]
    for word in text[1:]:
        if len(lines[-1]) + 1 + len(word) <= width:
            lines[-1] += (' ' + word)
        else:
            lines += [word]
    return lines


def depunctuate_character(c):
    """Record the punctuation of a character"""
    if c in string.ascii_uppercase:
        return 'UPPER'
    elif c in string.ascii_lowercase:
        return 'LOWER'
    else:
        return c


def depunctuate(text):
    """Record the punctuation of a string, so it can be applied to a converted
    version of the string.

    For example, 
    punct = depunctuate(ciphertext)
    plaintext = decipher(sanitise(ciphertext))
    readable_plaintext = repunctuate(plaintext, punct)
    """
    return [depunctuate_character(c) for c in text]


def repunctuate_character(letters, punctuation):
    """Apply the recorded punctuation to a character. The letters must be
    an iterator of base characters."""
    if punctuation == 'UPPER':
        return next(letters).upper()
    elif punctuation == 'LOWER':
        return next(letters).lower()
    else:
        return punctuation


def repunctuate(text, punctuation):
    """Apply the recored punctuation to a sanitised string.

    For example, 
    punct = depunctuate(ciphertext)
    plaintext = decipher(sanitise(ciphertext))
    readable_plaintext = repunctuate(plaintext, punct)
    """
    letters = iter(sanitise(text))
    return cat(repunctuate_character(letters, p) for p in punctuation)
