import { Transform } from "konva/lib/Util";
import { Pos } from "../utils/math.ts";
import { alignPortMat } from "@/utils/align-port.ts";
import mitt from 'mitt'

export type ViewerProps = {
	size?: number[];
	bound?: number[];
	padding: number | number[];
	retain: boolean;
};

export class Viewer {
	props: ViewerProps;
	viewMat: Transform;
	partMat: Transform = new Transform();
	bus = mitt<{ transformChange: Transform }>()

	constructor(props: Partial<ViewerProps> = {}) {
		this.props = {
			padding: 0,
			retain: true,
			...props,
		}
		this.viewMat = new Transform();
	}

	get bound() {
		return this.props.bound
	}

	setBound(bound: number[], size?: number[], padding?: number | number[], retain?: boolean) {
		this.props.bound = bound
		if (padding) {
			this.props.padding = padding
		}
		if (retain) {
			this.props.retain = retain
		}
		if (size) {
			this.props.size = size
		}
		padding = this.props.padding
		retain = this.props.retain
		size = this.props.size

		if (!size) {
			throw '缺少视窗size'
		}

		this.partMat = alignPortMat(
			[
				{x: bound[0], y: bound[1]},
				{x: bound[2], y: bound[3]},
			],
			[
				{x: 0, y: 0},
				{x: size[0], y: size[1]},
			],
			retain,
			typeof padding === "number"
				? padding
				: {x: padding[0], y: padding[1]}
		);
	}

	move(position: Pos, initMat = this.viewMat) {
		this.mutMat(new Transform().translate(position.x, position.y), initMat);
	}

	movePixel(position: Pos, initMat = this.viewMat) {
		if (isNaN(position.x) || isNaN(position.y)) {
			console.error(`无效移动位置${position.x} ${position.y}`)
			return;
		}

		const mat = initMat.copy().invert()
		const p1 = mat.point({x: 0, y: 0})
		const p2 = mat.point(position)
		this.move({x: p2.x - p1.x, y: p2.y - p1.y})

		// const info = initMat.decompose()
		// const tf = new Transform()
		// tf.rotate(info.rotation)
		// tf.scale(info.scaleX, info.scaleY)
		// this.move(tf.invert().point(position), this.viewMat)
	}


	scale(center: Pos, scale: number, initMat = this.viewMat) {
		const base = initMat.decompose().scaleX
		if (base * scale < 0.001 || base * scale > 1000) {
			console.error('缩放范围0.001~1000 已超过范围无法缩放')
			return;
		}
		if (isNaN(center.x) || isNaN(center.y)) {
			console.error(`无效中心点${center.x} ${center.y}`)
			return;
		}

		this.mutMat(
			new Transform()
				.translate(center.x, center.y)
				.multiply(
					new Transform()
						.scale(scale, scale)
						.multiply(new Transform().translate(-center.x, -center.y))
				),
			initMat
		);
	}

	scalePixel(center: Pos, scale: number, initMat = this.viewMat) {
		const pos = initMat.copy().invert().point(center)
		this.scale(pos, scale, initMat)
	}

	rotate(center: Pos, angleRad: number, initMat = this.viewMat) {
		this.mutMat(
			new Transform()
				.translate(center.x, center.y)
				.multiply(
					new Transform()
						.rotate(angleRad)
						.multiply(new Transform().translate(-center.x, -center.y))
				),
			initMat
		);
	}

	rotatePixel(center: Pos, angleRad: number, initMat = this.viewMat) {
		const pos = initMat.copy().invert().point(center)
		this.rotate(pos, angleRad, initMat)
	}

	mutMat(mat: Transform, initMat = this.viewMat) {
		// this.setViewMat(mat.copy().multiply(initMat))
		this.setViewMat(initMat.copy().multiply(mat))
	}

	setViewMat(mat: number[] | Transform) {
		if (mat instanceof Transform) {
			this.viewMat = mat.copy();
		} else {
			this.viewMat = new Transform(mat)
		}
		this.bus.emit('transformChange', this.transform)
	}

	get transform() {
		return this.partMat.copy().multiply(this.viewMat);
	}
	get current() {
		return this.viewMat.decompose()
	}
}