'''
2021-06-07

img_im_word_tile
    img - from image folder
    im - Image Magick
    word_tile - the effect

I'm not refactoring to post in Dead Code.
Worked at one point.
I may not have ImageMagick installed.

As one of my first programming projects,
    I wished to creat Matrix like strings.
    This was fairly effective.
    But there is no glory in repeated other's work.

These days,
    I would start with text
        N++ or similar
    And go from there
        Inkscape, Gimp, or Irfanview

Nor would I bother with static methods...
   
# # #
    

Created on Feb 9, 2014

@author: Brett Paufler
Copyright Brett Paufler 2-9-14

WordTile Class
    Create single letter tiles
    Combine letters into words
    TODO: Combine words into blocks

TODO:
    Pull Static out as an optional step
    turn blur into an option in letter creation

    Load text file
    assemble words (have assemble letter)
        So, create block

    text as image, should be easy, he said

    font options
    
 
name = base name of the image files
path_hame = denotes full path to image including .png extension    


'''
import os
from random import choice
from itertools import count
from string import ascii_letters, digits, punctuation


class WordTile():
    '''Uses ImageMagick to create image letter tiles effects.
         
         name: output file name
         text: text of output
         color: letter color
    '''
    
    #ImageMagick path
    im_convert = '"C:\Program Files\ImageMagick-6.8.8-Q16\convert.exe"'
    
    #Limits of implementation
    charset = ascii_letters + digits + punctuation

    def __init__(self, name='word_tile', text='', color='darkgreen'):
        self.name = name
        self.text = text
        self.color = color
        
    @staticmethod
    def name_to_path(name, ext='.png'):
        '''Converts base name to an absolute path including .png extension.'''
        return os.path.join(os.getcwd(), 'output', name + ext)

    @staticmethod
    def path_to_name(path):
        '''Returns base name given an abolute path.
        The inverse of name_to_path.'''
        return os.path.splitext(os.path.basename(path))[0]

    def test_name_path(self):
        '''Test for name_to_path and path_to_name.'''
        for name in ['hard name this', '. this. and']:
            assert name == self.path_to_name(self.name_to_path(name))

    @staticmethod
    def join_c(text_list):
        '''Converts list to a space sperated command line ready string.'''
        return ' %s ' % ' '.join(str(t) for t in text_list)
    

    def create_letter(self, char_name, char,
                    black_blur=5, black_direction=90,
                    white_blur=5, white_direction=90):
                    #TODO: Kill Blur and direction at this step
        '''Create a ascii_modified letter block .png
        
        char = ASCII character
            if int, converted to ascii_modified characters
            if '@' is input, output is random
            if char not alphanum, output is blank
            
        color = color of output, must be a valid IM color
        
        black_blur = int, lenght Blur of Black (added color portion)
        black_direction = int, direction, 90 is up and down
        
        white_blur = int, lengh of BLur color subtracted (white)
        white_direction = int, direction of white blur '''  
    
        #Preprocess, chr or int for chr(int)        
        char = char if isinstance(char, str) else chr(char)
        
        #Random and Blank assignment
        if char == '@':
            char = choice(self.charset)
        elif char not in self.charset:
            char = ''
        
        #Remove spaces from name or create default if none given 
        #name = name.replace(' ','') if name else 'letter_%s_%s' % (char, color)
        print 'create_letter(name=%s, char=%s, color=%s)' % (char_name, char, self.color)
    
        #Create sN and temporary save names, the latter are hard wired
        sN = self.name_to_path(char_name)
        temp_1 = sN[:-4] + '_temporary_1.png'
        temp_2 = sN[:-4] + '_temporary_2.png'
        temp_3 = sN[:-4] + '_temporary_3.png'
    
        #Black noise
        effect = ' -size 100x100 xc: +noise Random -threshold 30% -motion-blur 0x'
        effect += '%s+%s'% (str(black_blur), str(black_direction))
        effect += ' -threshold 50% -background transparent -transparent white '
        command = self.im_convert + effect + temp_1
        os.system(command)
    
        #White noise
        effect = '  -size 100x100 xc: +noise Random -threshold 40% '
        effect += '-motion-blur 0x%d+%d' % (white_blur, white_direction)
        effect += ' -threshold 50% -background transparent -transparent white '
        effect += '-fill white -opaque black '
        command = self.im_convert + effect + temp_2
        os.system(command)
        
        #Compose Composite folds the two images together (combines as one)
        command = self.im_convert + " %s %s -compose screen -composite %s" % (
                    temp_1, temp_2, temp_3)
        os.system(command)
        
        #Either a letter or blank tile is created (see previous char filters)
        if char == '':
            effect = ' %s -size 100x100 -threshold 20%% ' % temp_1
            effect += ' -background transparent -transparent white '
        else:
            effect = ' -size 100x100 -font Courier-New-Bold -pointsize 120 '
            effect += '-gravity center label:%s -threshold 20%%' % char
            effect += ' -background transparent -transparent white ' 
        command = self.im_convert + effect + temp_1
        #print command
        os.system(command)
        
        #Compose Composite, combines letter and static
        command = self.im_convert + " %s %s -compose screen -composite %s" % (
                    temp_1, temp_3, temp_2)
        os.system(command)
    
        #Color is added, saves to final image location
        effect = ' %s  -threshold 50%% -level-colors black,white' % temp_2
        effect += ' -threshold 50%% -fill %s -opaque black -transparent white  ' % self.color
        command = self.im_convert + effect + sN
        os.system(command)
        
        #Final clean up, remove temp files
        os.remove(temp_1)
        os.remove(temp_2)
        os.remove(temp_3)

  
    def test_create_letter(self):
        '''Test suite for creat_letter.
        Runs create_letter multiple times.
        Must visual check output.'''
        self.color='blue'
        self.create_letter(char_name='01_test_asterix', char='*')
        self.color='black'
        self.create_letter(char_name='02_test_paren', char=')')
        self.color='red'
        self.create_letter(char_name='03_test_blank_32', char=32)
        self.color='green'
        self.create_letter(char_name='04_test_brack', char='{')
        self.color='purple'
        self.create_letter(char_name='05_test_88', char=88)
        self.color='yellow'
        self.create_letter(char_name='06_test_e', char='e')
        self.color='pink'
        self.create_letter(char_name='07_test_72', char=72)
        self.color='orange'
        self.create_letter(char_name='08_test_T', char='T')
        self.color='brown'
        self.create_letter(char_name='09_test_question', char='?')
        self.color='darkgreen'
        self.create_letter(char_name='10_test_bang', char='!')
        self.color='lightgreen'
        self.create_letter(char_name='11_test_blank_space', char=' ')
        self.color='blue'
        self.create_letter(char_name='12_test_dollar', char='$')
        self.color='salmon'
        self.create_letter(char_name='13_test_random_1', char='@')
        self.color='olive'
        self.create_letter(char_name='14_test_random_2', char='@')


    def im_append(self, name, images, horizontal=True):
        '''Combines images into one using IM append command.
        
        Images are appended horizonatally right to left,
            if down==True, they are appended vertically.
            No provision for reversing direction.'''
        
        direction = " +append " if horizontal else " -append " 
        
        sN = self.name_to_path(name)
        
        command = '%s %s %s %s' % (self.im_convert, self.join_c(images), direction, sN)
        print 'im_append: ', command
        os.system(command)


    def create_word(self, name=None, horizontal=True, **kwargs): 
        '''Saves a word_tile.png to disk in ./output
    
        name: base save name, no directories or extensions
        text: letters on tile, defaults to same as sN
        horizontal: default True, yields a horizontal word_tile
            False: yields vertical
        
        create_letter is called to to create temporary letters
        as such, any create_letter argument will be accepted,
            the defaults are:
                color='darkblue',
                black_blur=5,
                black_direction=90,
                white_blur=5,
                white_direction=90
                
        Note: there is a limited character set as of this implementation
            1-21-16'''
        
        #Final word tile save name
        sN = name if name else self.name
        
        #Temporary letter save names
        N = count(1)
        cS = 'temp_file_xxz_yes'
        temp_files = [('%s_%s_%s' % (self.name, str(N.next()).zfill(10), cS), t)
                      for t in self.text]
    
        #Create temporary letter tiles
        for temp_name, char in temp_files:
            self.create_letter(char_name=temp_name, char=char, **kwargs)
    
        #Assemble word_tile
        temp_pic_paths = [self.name_to_path(temp_name) for temp_name, _ in temp_files]
        self.im_append(sN, temp_pic_paths, horizontal)
        
        #clean up (remove temporary letter tiles)
        for temp_pic in temp_pic_paths:
            os.remove(temp_pic)
            
    def test_create_word(self):
        '''Test suite, runs create word four times.'''
        self.color = 'purple'
        self.text = 'REGULAR'
        self.create_word('test_word_1_REGULAR')
        self.color = 'darkgreen'
        self.text = 'reversed'[::-1]
        self.create_word('test_word_2_desrever')
        self.color = 'red'
        self.text = '!!!STOP???'
        self.create_word('test_word_3_STOP', horizontal=False)
        self.color = 'pink'
        self.text = '!!!STOP???'[::-1]
        self.create_word('test_word_4_POTS', horizontal=False)


    def test_all(self):
        '''Runs all the test functions.'''
        self.test_name_path()
        self.test_create_letter()
        self.test_create_word()



    #TODO: From Here Down - Needs to be implemented

    #TODO - BREAK OUT
    #This is worth looking at again
    #THough, not for the intended purspose
    def matrixTextTilesOLD(self):
        '''Makes a vertical strip, run and look at
        '''
        
        aText = ' -size 50x10000 xc: +noise Random -threshold '
        bText = '% -background transparent -transparent black -fill green -opaque white  '
        
        '''makes lines of static 1px wide'''
        sN_s = self.name_to_path('static_line')
        command = self.im_convert + aText + str(80) + bText + sN_s
        print command
        os.system(command)
        
        
        
        ''' this makes the text string '''
        imgText = " -size 50x10000 -background transparent -stroke green -fill green -pointsize 76 -font Courier-New-Bold caption:@"
        textFile = ".\\input\\test.txt "
        sN_m = self.name_to_path('matrix_word')
        command = self.im_convert + imgText + textFile + sN_m
        print command
        print command
        print os.system(command)
        
        
        #Compose Composite folds the two images together (combines as one)
        sN_c = self.name_to_path('combo')
        command = self.im_convert + " %s %s -compose screen -composite %s" % (
                    sN_s, sN_m, sN_c)
        os.system(command)
    
    
        sN_f = self.name_to_path('final')
        print 'HERE'
        effect = ' -level-colors darkgreen,green  '
        command = self.im_convert + " " + sN_c + effect + sN_f
        print command
        os.system(command)
        
        
        print "FINISHED"
    #matrixTextTilesOLD()





    #TODO - Look, refactor, pull into class, maybe
    #LOOK at letter creation, see if this is the same, if so, OK to kill
    def createCompleteFont(self):
    
        count = 0
        dirFont = "output"
        #im_word_tile.makeOutputDirectory(dirFont)
        #im_word_tile.makeOutputDirectory(dirFont, dirFont)
        #print effect
        def _nextPic(outputName):
            print "_nextPic called"
            command = self.im_convert + effect + dirFont + "\\" + outputName + '.png'
            print command
            os.system(command)
            
        def removeSlack(num):
            print "removeSlack called"
            os.remove('.\\font\\blackStatic.png')
            os.remove('.\\font\\whiteStatic.png')
            os.remove('.\\font\\composite.png')
            #os.remove('.\\font\\letter.png')
            newName = '.\\font\\font\\' # * sN, killed, +           #im_word_tile.assembleLabel(num, "", 'png')
            os.rename('.\\font\\green.png', newName)
        
        ''' no like 60'''
        
        
    
        for num in range(33,256,1):
            black = '  -size 100x100 xc: +noise Random -threshold 30% -motion-blur 0x5+90 -threshold 50% -background transparent -transparent white '
            white = '  -size 100x100 xc: +noise Random -threshold 40% -motion-blur 0x5+90 -threshold 50% -background transparent -transparent white -fill white -opaque black '
            letterA = ' -size 100x100 -font Courier-New-Bold -pointsize 120 -gravity center label:'
            print "Current Num is -- " + str(num)
            letterNum = str(chr(num))
            letterB = ' -threshold 20%  -background transparent -transparent white '
            letter = letterA + letterNum + letterB
        
            effect = black
            _nextPic('blackStatic')
            
            effect = white
            _nextPic('whiteStatic')
        
            effect = letter
            _nextPic('letter')
        
            
            
            #This clearly won't work
            #composite(dirFont)
        
            green = ' .\\font\\composite.png  -threshold 50% -level-colors black,white -threshold 50% -fill darkblue -opaque black -transparent white  ' #-opaque white '
            effect = green
            _nextPic('green')
        
            removeSlack(num)
        
        print "FINISHED"





if __name__ == '__main__':
    print 'RUNNING AS __MAIN__: im_word_tile'
    w = WordTile(name='word_up', text = '???Word Tile Works!!! @@@')
    #w.create_word()
    #w.test_create_letter()
    w.test_all()
    #w.test_create_word()