#!/usr/bin/env python3

import colorsys
import os
import random
import sys
import time

Nx = int(sys.argv[1])
Ny = int(sys.argv[2])

PixelsPerFrame = 20
NumLines = 7
LineGenerationRate = 0.2
try:
    time_ms = int(sys.argv[3])
except:
    time_ms = 20
buffer = bytearray(3 * Nx * Ny)


def SetPixel(x, y, r, g, b):
    idx = x + Nx * y
    buffer[3 * idx + 0] = r
    buffer[3 * idx + 1] = g
    buffer[3 * idx + 2] = b


class Line:
    def __init__(self):
        self.color = random.random() * 0.3 + 0.7
        self.dir = random.randint(0, 3)
        if self.dir == 0:
            self.posx = 0
            self.posy = random.randint(0, Ny - 1)
        if self.dir == 1:
            self.posx = Nx - 1
            self.posy = random.randint(0, Ny - 1)
        if self.dir == 2:
            self.posx = random.randint(0, Nx - 1)
            self.posy = 0
        if self.dir == 3:
            self.posx = random.randint(0, Nx - 1)
            self.posy = Ny - 1

    def step(self):
        self.color *= 0.995
        pixel = int(self.color * 255)
        SetPixel(self.posx, self.posy, pixel, pixel, pixel)
        if self.dir == 0:
            self.posx += 1
        if self.dir == 1:
            self.posx -= 1
        if self.dir == 2:
            self.posy += 1
        if self.dir == 3:
            self.posy -= 1

    def alive(self):
        return 0 <= self.posx < Nx and 0 <= self.posy < Ny


def main():
    lines = []
    while True:
        for i in range(PixelsPerFrame):
            x = random.randint(0, Nx - 1)
            y = random.randint(0, Ny - 1)
            r, g, b = colorsys.hsv_to_rgb(random.random(), 0.7, 0.5)
            r = int(r * 255)
            g = int(g * 255)
            b = int(b * 255)
            SetPixel(x, y, r, g, b)
        for line in lines:
            line.step()
            if not line.alive():
                lines.remove(line)
        if len(lines) < NumLines and random.random() < LineGenerationRate:
            lines.append(Line())
        os.write(1, buffer)
        time.sleep(time_ms * 0.001)


if __name__ == '__main__':
    main()
