
# ------------------------------ Generate Characters ----------------------------#
# Import python imaging libs
from PIL import Image
from PIL import ImageDraw
from PIL import ImageFont, ImageFilter
#from skimage.util import random_noise
#from scipy.misc import toimage
import numpy as np
# Import operating system lib
import os, errno
from ImageHelper import noisy
# Import random generator
from random import randint
import shutil
import csv
import pickle
#---------------------------------- Input and Output ---------------------------#

# Directory containing fonts
font_dir = '../resources/fonts'

# Output
out_dir = '../results/'

k = 0

# ------------------------------------ Characters -------------------------------#
# Numbers
NUMBERS = ['0', '1', '2']

# Small letters
SMALL_LETTERS = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z']
SMALL_LETTERS_SAMPLE = ['k', 'b', 'c', 'e']
CAPITAL_LETTERS = [x.capitalize() for x in SMALL_LETTERS]
CAPITAL_LETTERS_SAMPLE = [x.capitalize() for x in SMALL_LETTERS_SAMPLE]

# Capital letters
#capital_letters = ["A", 'B', 'C']

# Select characters
CHARACTERS = SMALL_LETTERS
CHARACTERS_SAMPLE = SMALL_LETTERS_SAMPLE
#------------------------------------- Colors ----------------------------------#

# Background color
COLORS_WHITE = [(255, 255, 255)]
COLORS_WHITE_SAMPLE = COLORS_WHITE
COLORS_BLACK = (0, 10, 20, 30)
COLORS_GRAY = [(135, 145, 155)]

#background_colors = white_colors
COLORS_BACKGRND_CHOSEN = COLORS_WHITE_SAMPLE

# -------------------------------------- Sizes ----------------------------------#

# Character sizes
FONTSIZE_SMALL = (10, 14, 16)
FONTSIZE_MEDIUM = (20, 24, 28)
FONTSIZE_LARGE = (30, 36, 40)
FONTSIZE_LARGE_SAMPLE = (24, 30)

FONTSIZE_CHOSEN = FONTSIZE_LARGE_SAMPLE

# Image size
IMAGE_SIZE = 32

OFFSET_X = [-0.3, -0.1, 0, 0.1, 0.3]
OFFSET_Y = [-0.3, -0.1, 0, 0.1, 0.3]
OFFSET_X_SAMPLE = [-0.1, 0, 0.1]
OFFSET_Y_SAMPLE = [-0.3, -0.1, 0, 0.1, 0.3]



# -------------------------------------- rotation and offset ----------------------------------#
ROTATION = [-0.1, -0.5, 0, 0.5, 0.1]
ROTATION_SAMPLE = [0]

# ------------------------------------ Cleanup ----------------------------------#

def cleanup():
    # Delete ds_store file
    if os.path.isfile(font_dir+ '.DS_Store'):
        os.unlink(font_dir + '.DS_Store')

    if os.path.exists(out_dir):
        shutil.rmtree(out_dir, ignore_errors=True)
    # Delete all files from output directory
    #for file in os.listdir('results'):
    #    file_path = os.path.join('results', file)
    #    if os.path.isfile(file_path):
    #        os.unlink(file_path)
    return

def generateCharacters(mode ='image', sample = True):
    if(mode == 'image'):
        myoffsetsX = OFFSET_X_SAMPLE if sample else OFFSET_X
        myoffsetsY = OFFSET_Y_SAMPLE if sample else OFFSET_Y
        mydegrees = ROTATION_SAMPLE if sample else ROTATION
        mycharacters = CHARACTERS_SAMPLE if sample else CHARACTERS
        cleanup()
        # Counter
        k = 1
        i= 0
        for dirname, dirnames, filenames in os.walk(font_dir):
            # For each font do
            for filename in filenames:
                # Get font full file path
                font_resource_file = os.path.join(dirname, filename)
                # For each character do
                for char in mycharacters:
                    # For each font size do
                    for font_size in FONTSIZE_CHOSEN:
                        if font_size > 0:
                            # For each background color do
                            for background_color in COLORS_BACKGRND_CHOSEN:
                                for offsetx in myoffsetsX:
                                    for offsety in myoffsetsY:
                                        for degree in mydegrees:
                                            print("image size: {} \t "
                                                  "character: {}\t"
                                                  "font size: {}\t"
                                                  "degree: {}\t \t"
                                                  "offsetX: {}\t"
                                                  "offsetY: {}".format(IMAGE_SIZE, char, font_size, degree, offsetx, offsety))

                                            try:
                                                dir = out_dir+char+'/'
                                                os.makedirs(dir)
                                            except OSError as e:
                                                if e.errno != errno.EEXIST:
                                                    raise
                                            createImage(dir, background_color, char, font_size, k,  font_resource_file, degree, offsetx, offsety,0)
                                            createImage(dir, background_color, char, font_size, k,  font_resource_file, degree, offsetx, offsety,1)
                                            createImage(dir, background_color, char, font_size, k,  font_resource_file, degree, offsetx, offsety,2)
                                            k = k + 1
        return
    if(mode == 'csv'):
        GenerateCSVData(sample)

def GenerateCSVData(sample = True):
    myoffsetsX = OFFSET_X_SAMPLE if sample else OFFSET_X
    myoffsetsY = OFFSET_Y_SAMPLE if sample else OFFSET_Y
    mydegrees = ROTATION_SAMPLE if sample else ROTATION
    mycharacters = CHARACTERS_SAMPLE if sample else CHARACTERS
    print("image size: {} \t "
          "characters: {}\t"
          "backgrounds: {}\t"
          "font sizes: {}\t"
          "degree: {}\t"
          "offsetX: {}\t"
          "offsetY: {}".format(IMAGE_SIZE, mycharacters, COLORS_BACKGRND_CHOSEN, FONTSIZE_CHOSEN, mydegrees, myoffsetsX, myoffsetsY))
    k = 0
    i = 0
    path, dirs, files = next(os.walk(font_dir))
    file_count = len(files)

    height = file_count * len(mycharacters) * len(FONTSIZE_CHOSEN) * len(COLORS_BACKGRND_CHOSEN) * len(myoffsetsX) * len(myoffsetsY) * len(mydegrees) * 3
    print(height)
    width = IMAGE_SIZE * IMAGE_SIZE + 1
    output = np.ones((height,width), dtype=object)
    mapDic = {}
    for dirname, dirnames, filenames in os.walk(font_dir):
        # For each font do
        for filename in filenames:
            # Get font full file path
            font_resource_file = os.path.join(dirname, filename)

            # For each character do
            for char in mycharacters:
                mapDic[char] = i
                # For each font size do
                for font_size in FONTSIZE_CHOSEN:
                    if font_size > 0:
                        # For each background color do
                        for background_color in COLORS_BACKGRND_CHOSEN:
                            for offsetx in myoffsetsX:
                                for offsety in myoffsetsY:
                                    for degree in mydegrees:
                                        #createImage((255, 255, 255), 'A', 16, 1,
                                         #                   './resources/fonts\\HelveticaNeueLight.ttf', 30)
                                        # print("image size: {} \t "
                                        #       "character: {}\t"
                                        #       "font size: {}\t"
                                        #       "degree: {}\t"
                                        #       "offsetX: {}\t"
                                        #       "offsetY: {}".format(image_size, char, font_size, degree,offsetx, offsety))

                                        resultImage1 = createImage(dir, background_color, char, font_size, k,  font_resource_file, degree, offsetx, offsety,0, False)
                                        resultImage1 = resultImage1.convert('L')
                                        width = resultImage1.size[0]
                                        height = resultImage1.size[1]
                                        imageArray = np.array(resultImage1)
                                        value = np.asarray(resultImage1, dtype=np.int)
                                        value = value.flatten()
                                        value = np.append(i, value)
                                        output[k] = value
                                        resultImage2 = createImage(dir, background_color, char, font_size, k,  font_resource_file, degree, offsetx, offsety,1, False)
                                        width = resultImage1.size[0]
                                        height = resultImage1.size[1]
                                        imageArray = np.array(resultImage1)
                                        value = np.asarray(resultImage1, dtype=np.int)
                                        value = value.flatten()
                                        value = np.append(i, value)
                                        output[k+1] = value
                                        resultImage2 = createImage(dir, background_color, char, font_size, k,
                                                                   font_resource_file, degree, offsetx, offsety, 2,
                                                                   False)
                                        width = resultImage1.size[0]
                                        height = resultImage1.size[1]
                                        imageArray = np.array(resultImage1)
                                        value = np.asarray(resultImage1, dtype=np.int)
                                        value = value.flatten()
                                        value = np.append(i, value)
                                        output[k + 2] = value
                                        #print(k)
                                        k = k + 3
                print(i)
                i = i + 1

    print("dimensions {}".format(output.shape))
    np.savetxt(out_dir+"foo.csv", output,fmt='%5s', delimiter=",")
    pickle_out = open(out_dir+"mapDic.pickle", "wb")
    pickle.dump(mapDic, pickle_out)
    pickle_out.close()
    print(output[:,0])

    #np.savetxt(out_dir+"mapDic.csv", mapDic,delimiter=",")
    return

def getMapDic():
    pickle_in = open(out_dir+"mapDic.pickle", "rb")
    return pickle.load(pickle_in)


def createImageTemplate(background_color, char, font_size, k, font_filename, degree = 0, offsetX = 0, offsetY = 0, noise = 0):
    # Create character image :
    # Grayscale, image size, background color
    char_image = Image.new('RGBA', (IMAGE_SIZE, IMAGE_SIZE), \
                           background_color)
    # Draw character image
    draw = ImageDraw.Draw(char_image)
    # Specify font : Resource file, font size
    font = \
        ImageFont.truetype(font_filename, font_size)
    # Get character width and height
    (font_width, font_height) = font.getsize(char)
    # Calculate x position
    x = (IMAGE_SIZE - font_width) / 2 + offsetX * IMAGE_SIZE
    # Calculate y position
    y = (IMAGE_SIZE - font_height) / 2 + offsetY * IMAGE_SIZE
    # Draw text : Position, String,
    # Options = Fill color, Font
    draw.text((x, y), char,(0,0,0), font=font)
    char_image = char_image.rotate(degree)
    fontname = os.path.split(font_filename)[1].split('.')[0]
    # Final file name
    file_name = "{}_f_{}_fs_{}_bc_{}_n_{}_r_{}_ox_{}_oy_{}_{}.png".\
        format(char,fontname, font_size,background_color,noise,degree,offsetX,offsetY,k)

    # Save image
    #char_image.save('results/' + file_name)
    return (char_image, file_name)


def createImage(directory, background_color, char, font_size, k, font_filename, degree = 0, offsetX = 0, offsetY = 0, noise = 0, save = True):
    blankImage, file_name = createBlankImage()
    #blankImage.save('blankImage.png')
    image2, file_name2 = createImageTemplate(background_color, char, font_size, k, font_filename, degree, offsetX, offsetY, noise)
    #image2.save('./results/'+str(k)+'.png')
    px, py = 0, 0
    sx, sy = image2.size
    blankImage.paste(image2, (px, py, px + sx, py + sy), image2)
    #resultImage = addNoise(blankImage,noise)
    resultImage = blankImage
    if resultImage.mode != 'RGB':
        resultImage = resultImage.convert('RGB')
    if(save):
        resultImage.save(directory+file_name2)
    return resultImage

def addNoise(image, noise = 0):
    pix = np.array(image)
    if noise == 2:
        #print("noise gaussian")
        pix = noisy('gauss', pix)

        #pix = random_noise(pix, mode='gaussian', clip=True)
    elif noise == 1:
        pix = noisy('s&p',pix)
        #print("noise s and p")
        #pix = random_noise(pix, mode='pepper', clip=True, amount = 0.1)
    else:
        pix = np.array(image)
    result =Image.fromarray(pix.astype('uint8'))
    #result.show()
    return result

def createBlankImage():
    # Create character image :
    # Grayscale, image size, background color
    char_image = Image.new('RGBA', (IMAGE_SIZE, IMAGE_SIZE), \
                           (255,255,255))

    # w = char_image.rotate(45.5, expand=1)
    #char_image.rotate(45).show()
    # Final file name
    file_name = 'blankoImage {}x{}.png'.format(IMAGE_SIZE, IMAGE_SIZE)
    #print(file_name)
    # Save image
    #char_image.save('results/' + file_name)
    return (char_image, file_name)





def main():
    generateCharacters('image', True)
   #printMapDic()
    #GenerateCharacters()

if __name__ == "__main__":
    main()
    #image1.save('results/blank.png')
    #createMovedImage()

