import numpy as np
from raytrace_2D import Disk
import csv

class Ray:
	def __init__(self, origin, direction, intensity):
		self.origin = np.array(origin)
		self.direction = np.array(direction) / np.linalg.norm(direction)
		self.intensity = intensity

center = [0,0]
r = 1
n = 1.3
disk = Disk(center, r, n)
dx = 0.005
N = int(2*r /dx - 1)
min_intensity = 0.001
max_ray = 10000

stack = []
result = []
points = []

def init():
	for x in np.linspace(-r + dx, r-dx, N):
		stack.append(Ray([x, 2*r], [0,-1], 1))
	print(np.linspace(-r + dx, r-dx, N))

def reflection_and_refraction(ray:Ray, intersection_point, normal, n):
	print("reflection/refraction at the point:", intersection_point)
	k_n = np.dot(ray.direction, normal)
	if k_n > 0:
		n1,n2 = n,1
	else:
		n1, n2 = 1,n
	kp = ray.direction - k_n*normal
	k2p = n1*kp/n2
	if np.dot(k2p, k2p) >= 1:
		ray1 = Ray(intersection_point, ray.direction-2*k_n*normal, ray.intensity)
		return ray1,None
	else:
		k2n = np.sqrt(1 - np.dot(k2p, k2p))*np.sign(k_n)
		Rs = (n1*k_n - n2*k2n)*(n1*k_n - n2*k2n)/((n1*k_n + n2*k2n)*(n1*k_n + n2*k2n))
		Rp = (n1*k2n - n2*k_n)*(n1*k2n - n2*k_n)/((n1*k2n + n2*k_n)*(n1*k2n + n2*k_n))
		R = (Rs+Rp)/2
		ray1 = Ray(intersection_point, ray.direction-2*k_n*normal, ray.intensity*R)
		ray2 = Ray(intersection_point, k2n*normal+k2p, ray.intensity*(1-R))
		return ray1,ray2

def trace(disk:Disk, stack:list, max_ray:int):
	ray_count = 0
	while stack and ray_count < max_ray:
		ray = stack.pop()
		ray_count += 1
		if ray is None:
			continue
		if isinstance(ray, Ray):
			if ray.intensity < min_intensity:
				continue
			direction = ray.direction
			t,intersection_point = disk.find_intersection(ray)
			if intersection_point is not None:
				points.append(np.concatenate((ray.origin, intersection_point,[ray.intensity])))
				normal = disk.get_normal(intersection_point)
				stack.extend(reflection_and_refraction(ray, intersection_point, normal, disk.refractive_index))
			else:
				points.append(np.concatenate((ray.origin, ray.origin+ray.direction,[ray.intensity])))
				if direction[1] > 0:
					result.append([np.arccos(direction[1]), ray.intensity*direction[1]])

init()
# stack.append(Ray([0.8, 2*r], [0,-1], 1))
trace(disk, stack, max_ray)

with open("result.csv", 'w', newline='') as f:
    writer = csv.writer(f)
    writer.writerows(result)

with open("points.csv", 'w', newline='') as f:
    writer = csv.writer(f)
    writer.writerows(points)
