# -*- coding: utf-8 -*-
"""
Random_art.py

@author: amonmillner, adapted from pruvolo work
"""

# you do not have to use these particular modules, but they may help
from random import randint
import Image
import math

def prod(a,b):
    return a*b

def cos_pi(a):
    return math.cos(math.pi*a)
    
def sin_pi(a):
    return math.sin(math.pi*a)
    
def tan_halfpi(a):
    return math.tan(math.pi/2*a)    
    
def x(a,b):
    return a
    
def y(a,b):
    return b
    
def sphere(a,b):
    return math.sqrt(a**2+b**2)/2
  
def generate_random_building_block():
    """ generate random building block among 5 functions
    """
    num = randint(1,5)
    
    if (num == 1):
        return "prod"
    if (num == 2):
        return "cos_pi"
    if (num == 3):
        return "sin_pi"
    if (num == 4):
        return "tan_halfpi"
    if (num == 5):
        return "sphere"

def generate_random_base():
    """ generate random base among x and y
    """
    num = randint(1,2)
    
    if (num == 1):
        return "x"
    if (num == 2):
        return "y"
    
def recursive_build(n):
    """ makes function list recursively
    """
    if(n==1):
        return [generate_random_base()]
    else:
        block = generate_random_building_block()
        
        if(block == 'prod' or block == 'sphere'):
            return [block,recursive_build(n-1),recursive_build(n-1)]
        else:
            return [block,recursive_build(n-1)]
            
def set_intensity(f, width_x, width_y):
    """ setting intensity of red,green,blue for every pixel 
    """
    temp_im = Image.new("L",(width_x, width_y))
    for px in range (width_x):
        for py in range (width_y):
            px_remapped = remap_interval(px, 0, width_x-1, -1, 1)
            py_remapped = remap_interval(py, 0, width_y-1, -1, 1)
            
            intensity = evaluate_random_function(f,px_remapped,py_remapped)
            intensity_remapped = int(remap_interval(intensity,-1,1,0,255))
            
            temp_im.putpixel((px, py), intensity_remapped)
    return temp_im

def plot_rgb(func_red,func_green,func_blue,width_x,width_y):
    """ merge 3 plots (red, green, blue) generated by set_intensity() function
    """
    plot_red = set_intensity(func_red, width_x, width_y)
    plot_green = set_intensity(func_green, width_x, width_y)
    plot_blue = set_intensity(func_blue, width_x, width_y)
    return Image.merge("RGB", (plot_red, plot_green, plot_blue))
        
def build_random_function(min_depth, max_depth):
    """ set depth between min and max, then return random function built by recursive_build()
    """
    
    depth = randint(min_depth,max_depth)
    
    return recursive_build(depth)


def evaluate_random_function(f, x, y):
    """ evaluate the function f recursively. When base comes, put x, y value.
    """
    if(f[0]=='x'):
        return x
    elif(f[0]=='y'):
        return y
    elif(f[0]=='sin_pi'):
        return sin_pi(evaluate_random_function(f[1], x, y))
    elif(f[0]=='cos_pi'):
        return cos_pi(evaluate_random_function(f[1], x, y))
    elif(f[0]=='tan_halfpi'):
        return tan_halfpi(evaluate_random_function(f[1], x, y))
    elif(f[0]=='prod'):
        return prod(evaluate_random_function(f[1], x, y),evaluate_random_function(f[2], x, y))
    elif(f[0]=='sphere'):
        return sphere(evaluate_random_function(f[1], x, y),evaluate_random_function(f[2], x, y))
    

    

def remap_interval(val, input_interval_start, input_interval_end, output_interval_start, output_interval_end):
    """ Maps the input value that is in the interval [input_interval_start, input_interval_end]
        to the output interval [output_interval_start, output_interval_end].  The mapping
        is an affine one (i.e. output = input*c + b).
    
        Return value in the output interval at the same positions regarding each intervals.
    """
    input_width = float(input_interval_end - input_interval_start)
    output_width = float(output_interval_end - output_interval_start)
    
    remapped_val = (val-input_interval_start) * output_width / input_width + output_interval_start
    return remapped_val    
    
#executions


width_x = 350
width_y = 350
how_many = 10

f = open("random functions used.txt",'w')

for i in range(how_many):
    func_red = build_random_function(10,10)
    func_green = build_random_function(1,1)
    func_blue = build_random_function(4,4)
    
    f.write(str(i+1)+".\nfunction for red plot : "+str(func_red)+"\nfunction for green plot : "+str(func_red)+"\nfunction for blue plot : "+str(func_blue)+"\n")
    
    im = plot_rgb(func_red,func_green,func_blue,width_x,width_y)
    im.save("image"+str(i+1)+".png","PNG")
        


