import math

from . import patterns


def get_geometry(params):
    deformations = []
    if params.random('should_offset') > .3:
        deformations.append(deform_noise(params))

    if params.random('have_wave') > .5:
        deformations.append(deform_wave(params))

    if params.random('have_zoom') > .5:
        deformations.append(deform_zoom(params))

    if deformations:
        combined_deformation = deformations[0]
        # for deformation in deformations[1:]:
        #     combined_deformation = lambda coord: deformation(combined_deformation(coord))

        return (([combined_deformation(coord) for coord in shape], color_index)
                for (shape, color_index)
                in patterns.get_tiles(params))

    else:
        return patterns.get_tiles(params)


def deform_noise(params):
    min_offset = .2 * abs(params.size)
    max_offset = .6 * abs(params.size)

    size = .5 * abs(params.size)

    avg_offset = (min_offset + max_offset) * (0.5 + 0.5j)
    noise_x = params.perlin("noise_x", size=size,
                            min_value=min_offset, max_value=max_offset)
    noise_y = params.perlin("noise_y", size=size,
                            min_value=min_offset, max_value=max_offset)

    return lambda coord: (coord +
                          noise_x(coord) +
                          noise_y(coord) * 1J -
                          avg_offset)


def deform_wave(params):
    amplitude = params.img_scale * params.uniform('wave_amplitude', .1, 1.0)
    wavelength = params.img_scale * params.uniform('wave_wavelength', .2, 2.0)

    angle = params.uniform('wave_rotation', 1, 2 * math.pi)
    rotation = math.cos(angle) + 1J * math.sin(angle)

    direction = amplitude / rotation * 1J

    return lambda coord: (coord +
                          direction * math.sin((coord * rotation).real / wavelength))


def deform_zoom(params):
    amount = params.uniform('zoom_amount', .5, 1.5)
    center = (params.size / 2.0)
    size = max(center.real, center.imag)

    def coord_at(coord):
        offset = coord - center
        distance = abs(offset)
        new_distance = ((distance / size) ** amount) * size
        offset /= distance
        offset *= new_distance
        return center + offset

    return coord_at


def get_centroid(shape):
    return sum(shape) / len(shape)


def get_bb(shape):
    return (min(x.real for x in shape) + min(y.imag for y in shape) * 1J,
            max(x.real for x in shape) + max(y.imag for y in shape) * 1J)

@@ -105,21 +105,20 @@
 om('
-should_offset
+have_crumple
 ') %3E
@@ -153,28 +153,30 @@
 pend(deform_
-nois
+crumpl
 e(params))%0A%0A
@@ -797,20 +797,22 @@
  deform_
-nois
+crumpl
 e(params
@@ -819,18 +819,18 @@
 ):%0A    m
-in
+ax
 _offset 
@@ -831,18 +831,19 @@
 ffset = 
-.2
+-.3
  * abs(p
@@ -858,188 +858,102 @@
 ze)%0A
+%0A
     
-max_offset = .6 * abs(params.size)%0A%0A    size = .5 * abs(params.size)%0A%0A    avg_offset = (min_offset + max_offset) * (0.5 + 0.5j)%0A    noise_x = params.perlin(%22noise_x%22, size=size
+noise_x = params.perlin(%22noise_x%22,%0A                            size=.8 * params.size.real
 ,%0A  
@@ -984,35 +984,36 @@
   min_value=
-min
+-max
 _offset,
  max_value=m
@@ -992,32 +992,60 @@
 lue=-max_offset,
+%0A                           
  max_value=max_o
@@ -1093,18 +1093,63 @@
 _y%22,
- size=size
+%0A                            size=.8 * params.size.imag
 ,%0A  
@@ -1188,19 +1188,20 @@
 lue=
-min
+-max
 _offset,
  max
@@ -1196,16 +1196,44 @@
 _offset,
+%0A                           
  max_val
@@ -1374,47 +1374,8 @@
 * 1J
- -%0A                          avg_offset
 )%0A%0A%0A

Tweak cumple filter, and actually name it crumple