import { getRoundedInkyPolygonPath, getRoundedPolygonPoints, VecLike } from '@tldraw/primitives'
import { TLGeoShape } from '@tldraw/tlschema'
import * as React from 'react'
import { getShapeFillSvg, getSvgWithShapeFill, ShapeFill } from '../../shared/ShapeFill'
import { TLExportColors } from '../../shared/TLExportColors'

export const DrawStylePolygon = React.memo(function DrawStylePolygon({
	id,
	outline,
	lines,
	fill,
	color,
	strokeWidth,
}: Pick<TLGeoShape['props'], 'fill' | 'color'> & {
	id: TLGeoShape['id']
	outline: VecLike[]
	strokeWidth: number
	lines?: VecLike[][]
}) {
	const polygonPoints = getRoundedPolygonPoints(id, outline, strokeWidth / 3, strokeWidth * 2, 2)
	let strokePathData = getRoundedInkyPolygonPath(polygonPoints)

	if (lines) {
		for (const [A, B] of lines) {
			strokePathData += `M${A.x},${A.y}L${B.x},${B.y}`
		}
	}

	const innerPolygonPoints = getRoundedPolygonPoints(id, outline, 0, strokeWidth * 2, 1)
	const innerPathData = getRoundedInkyPolygonPath(innerPolygonPoints)

	return (
		<>
			<ShapeFill d={innerPathData} fill={fill} color={color} />
			<path d={strokePathData} stroke="currentColor" strokeWidth={strokeWidth} fill="none" />
		</>
	)
})

export function DrawStylePolygonSvg({
	id,
	outline,
	lines,
	fill,
	color,
	colors,
	strokeWidth,
}: Pick<TLGeoShape['props'], 'fill' | 'color'> & {
	id: TLGeoShape['id']
	outline: VecLike[]
	lines?: VecLike[][]
	strokeWidth: number
	colors: TLExportColors
}) {
	const polygonPoints = getRoundedPolygonPoints(id, outline, strokeWidth / 3, strokeWidth * 2, 2)

	let strokePathData = getRoundedInkyPolygonPath(polygonPoints)

	if (lines) {
		for (const [A, B] of lines) {
			strokePathData += `M${A.x},${A.y}L${B.x},${B.y}`
		}
	}

	const innerPolygonPoints = getRoundedPolygonPoints(id, outline, 0, strokeWidth * 2, 1)
	const innerPathData = getRoundedInkyPolygonPath(innerPolygonPoints)

	const strokeElement = document.createElementNS('http://www.w3.org/2000/svg', 'path')
	strokeElement.setAttribute('d', strokePathData)
	strokeElement.setAttribute('fill', 'none')
	strokeElement.setAttribute('stroke', colors.fill[color])
	strokeElement.setAttribute('stroke-width', strokeWidth.toString())

	// Get the fill element, if any
	const fillElement = getShapeFillSvg({
		d: innerPathData,
		fill,
		color,
		colors,
	})

	return getSvgWithShapeFill(strokeElement, fillElement)
}

// function getPolygonDrawPoints(id: string, outline: VecLike[], strokeWidth: number) {
// 	const points: Vec2d[] = []

// 	const getRandom = rng(id)

// 	const start = Math.round(Math.abs(getRandom()) * outline.length)

// 	const corners = outline.map((p) =>
// 		Vec2d.AddXY(p, (getRandom() * strokeWidth) / 4, (getRandom() * strokeWidth) / 4)
// 	)

// 	const len = corners.length

// 	for (let i = 0, n = len + 1; i < n; i++) {
// 		const At = corners[(start + i) % len]
// 		const Bt = corners[(start + i + 1) % len]

// 		const dist = Math.min(Vec2d.Dist(At, Bt) / 2, strokeWidth / 2)
// 		const A = Vec2d.Nudge(At, Bt, dist)

// 		const D = Vec2d.Med(At, Bt)

// 		if (i === 0) {
// 			Bt.z = 0.7
// 			points.push(new Vec2d(D.x, D.y, 0.7), Bt)
// 		} else if (i === outline.length) {
// 			const lastSegPoints = Vec2d.PointsBetween(A, D, 4)
// 			lastSegPoints.forEach((p) => (p.z = 0.7))
// 			points.push(...lastSegPoints)
// 		} else {
// 			points.push(...Vec2d.PointsBetween(A, Bt, 6))
// 		}
// 	}

// 	return points
// }

// export function getPolygonIndicatorPath(id: string, outline: VecLike[], strokeWidth: number) {
// 	const points = getPolygonDrawPoints(id, outline, strokeWidth)
// 	const options = getPolygonStrokeOptions(strokeWidth)
// 	const strokePoints = getStrokePoints(points, options)

// 	return getSvgPathFromStrokePoints(strokePoints, true)
// }

// function getPolygonStrokeOptions(strokeWidth: number) {
// 	return {
// 		size: 1 + strokeWidth * 0.618,
// 		last: true,
// 		simulatePressure: false,
// 		streamline: 0.25,
// 		thinning: 0.9,
// 	}
// }

// function getPolygonstrokePathData(id: string, outline: VecLike[], strokeWidth: number) {
// 	// draw a line between all of the points
// 	let d = `M${outline[0].x},${outline[0].y}`
// 	d += 'Z'

// 	for (const { x, y } of outline) {
// 		d += `${x},${y}`
// 	}

// 	return d
// }

// function SimpleInkyPolygon(id: string, outline: VecLike[], offset: number) {
// 	const random = rng(id)
// 	let p = outline[0]

// 	let ox = random() * offset
// 	let oy = random() * offset

// 	let polylineA = `M${p.x - ox},${p.y - oy}L`
// 	let polylineB = `${p.x + ox},${p.y + oy} `

// 	for (let i = 1, n = outline.length; i < n; i++) {
// 		p = outline[i]
// 		ox = random() * offset
// 		oy = random() * offset

// 		polylineA += `${p.x - ox},${p.y - oy} `
// 		polylineB += `${p.x + ox},${p.y + oy} `
// 	}

// 	polylineB += 'Z'

// 	polylineA += polylineB

// 	return polylineA
// }

// function CubicInkyPolygon(id: string, outline: VecLike[], offset: number) {
// 	const random = rng(id)
// 	let p0 = outline[0]
// 	let p1 = p0

// 	let ox: number
// 	let oy: number

// 	let polylineA = `M${p0.x},${p0.y} L`
// 	let polylineB = `M${p0.x},${p0.y}`

// 	for (let i = 0, n = outline.length; i < n; i++) {
// 		p0 = outline[i]
// 		p1 = outline[(i + 1) % n]

// 		polylineA += `${p1.x},${p1.y} `

// 		ox = random() * offset
// 		oy = random() * offset
// 		const c1 = Vec2d.Lrp(p0, p1, 0.25)
// 		const c2 = Vec2d.Lrp(p0, p1, 0.75)

// 		polylineB += `C${c1.x + ox},${c1.y + oy} ${c2.x - ox},${c2.y - oy} ${p1.x},${p1.y}`
// 	}

// 	polylineB += 'Z'

// 	polylineA += polylineB

// 	return polylineA
// }

// function QuadraticInkyPolygon(id: string, outline: VecLike[], offset: number) {
// 	const random = rng(id)
// 	let p0 = outline[0]
// 	let p1 = p0

// 	let polylineA = `M${p0.x},${p0.y} Q`

// 	const len = outline.length

// 	for (let i = 0, n = len * 2; i < n; i++) {
// 		p0 = outline[i % len]
// 		p1 = outline[(i + 1) % len]
// 		const dist = Vec2d.Dist(p0, p1)

// 		const c1 = Vec2d.Lrp(p0, p1, 0.5 + random() / 2)
// 		polylineA += `${c1.x + random() * Math.min(dist / 10, offset)},${
// 			c1.y + random() * Math.min(dist / 10, offset)
// 		} ${p1.x + (random() * offset) / 2},${p1.y + (random() * offset) / 2} `
// 	}

// 	polylineA += 'Z'

// 	return polylineA
// }

// function GlobyInkyPolygon(id: string, outline: VecLike[], offset: number) {
// 	const random = rng(id)
// 	let p0 = outline[0]
// 	let p1 = p0

// 	let polylineA = `M${p0.x},${p0.y} Q`

// 	const len = outline.length

// 	for (let i = 0, n = len * 2; i < n; i++) {
// 		p0 = outline[i % len]
// 		p1 = outline[(i + 1) % len]
// 		const dist = Vec2d.Dist(p0, p1)

// 		const c1 = Vec2d.Lrp(p0, p1, 0.5 + random() / 2)
// 		polylineA += `${c1.x + random() * Math.min(dist / 10, offset)},${
// 			c1.y + random() * Math.min(dist / 10, offset)
// 		} ${p1.x + (random() * offset) / 2},${p1.y + (random() * offset) / 2} `
// 	}

// 	polylineA += 'Z'

// 	return polylineA
// }
