# Wave Equation in Circuit Python, see http://rotormind.com/blog/2023/Fun_with_the_wave_equation/code.py.html SPDX-FileCopyrightText: 2018 Jonathan Foote s
#
# SPDX-License-Identifier: MIT

"""CircuitPython Discrete-time silulation of the  Wave Equation """
import time
import board
import neopixel
import math
import random

import colorsys

pixel_pin = board.IO1
num_pixels = 64

pixels = neopixel.NeoPixel(pixel_pin, num_pixels, brightness=0.3, auto_write=False,
                           pixel_order=(0, 1, 2))


def colorwheel(pos):
    # Input a value 0 to 255 to get a color value.
    # The colours are a transition r - g - b - back to r.
    if pos < 1 or pos > 255:
        return (0, 0, 0, 0)
    if pos < 85:
        return (255 - pos * 3, pos * 3, 0, 0)
    if pos < 170:
        pos -= 85
        return (0, 255 - pos * 3, pos * 3, 0)
    pos -= 170
    return (pos * 3, 0, 255 - pos * 3, 0)


damping = 0.990
Courant = 0.02

# range of colors increases with this number
hue_scale = 0.5
# changes hue center
hue_center = 50

# range of brightness increases with this number
val_scale = 10


grid = 64
grid2 = grid / 2 - 1.0
nx = 8
ny = 8
u0 = []
u1 = []
u2 = []

#maxDistance
#spacer


nx = 8
ny = 8
u0 = []
u1 = []
u2 = []


def setup():

    # initialize arrays. Pad by 1 unit in each direction
    # to use for boundary conditions
    for x in range(nx + 2):
        u0.append([])
        u1.append([])
        u2.append([])
        # initial conditions may be non-zero
        for  y in range(ny + 2):
            u0[x].append(0.)
            u1[x].append(0.)
            u2[x].append(0.)

#update wave equation
def updateWE():
  # Don't iterate over boundary edges
    for x in range(1,nx+1):
        for y in range(1,ny+1):
            uxx = 0.5 * (u1[x - 1][y] + u1[x + 1][y]) - u1[x][y]
            uyy = 0.5 * (u1[x][y - 1] + u1[x][y + 1]) - u1[x][y]
            u0[x][y] = 2.*u1[x][y] - u2[x][y] + (Courant * (uxx + uyy))

#update boundary conditions
def updateTime():
  # increment time
    for x in range(1,nx+1):
        for y in range(1,ny+1):
            u2[x][y] = u1[x][y]
            u1[x][y] = damping*u0[x][y]
            
def loop():
    updateWE()
    #print("draw")
    i = 0
    for x in range(1,nx+1):
        for y in range(1,ny+1):
            thew =  u1[x][y]
            absw = abs(thew)
            hue = 0.1*thew + 0.5
            val =  0.1*(absw)
            #if  x == 4:
            #    print(theval)
            #pixels[i] = [theval, 0, 0]
            #pixels[i] = colorwheel(theval)
            pixels[i] = colorsys.hsv_to_rgb(hue, 0.9, val)
            i += 1   
    pixels.show()
    updateTime()


def perturb():
    i = random.randint(1,8)
    j = random.randint(1,8)
    u1[i][j] = 3
    print(f"splash at {i},{j}")

hls = (0.4, 0.7, 0.5)
# rgb = colorsys.hls_to_rgb(hls[0], hls[1], hls[2])
# print("HLS {} == RGB {}".format(hls, rgb))

# hsv = (0.8, 0.5, 0.5)
# rgb = colorsys.hsv_to_rgb(hsv[0], hsv[1], hsv[2])
# print("HSV {} == RGB {}".format(hsv, rgb))

    
setup()

count = 0
perturb()
while True:
    #print(count)
    if count > 400:
        perturb()
        count = 0

    loop()
    count += 1