import {
    AViewerPluginSync,
    type IViewerEvent,
    ThreeViewer,
    uiButton,
    uiConfig,
    uiFolderContainer,
    uiToggle,
} from 'threepipe'
import {BasicSVGRenderer} from './basic/BasicSVGRenderer'

/**
 * SVG rendering of 3d objects using SVGRenderer from three/addons
 */
@uiFolderContainer('SVG Renderer')
export class BasicSVGRendererPlugin extends AViewerPluginSync<''> {
    static readonly PluginType = 'BasicSVGRendererPlugin'

    @uiToggle()
        enabled = true

    @uiConfig()
    readonly renderer = new BasicSVGRenderer()

    /**
     * @param enabled
     * @param autoAddToContainer - automatically add the svg to the viewer container and style it same as the viewer is position is absolute
     */
    constructor(enabled = true, readonly autoAddToContainer = true) {
        super()
        this._onResize = this._onResize.bind(this)
        this.enabled = enabled
        this.renderer.domElement.style.position = 'absolute'
        this.renderer.domElement.style.display = 'none'
    }

    protected _lastStyles?: string = undefined
    onAdded(viewer: ThreeViewer) {
        super.onAdded(viewer)
        this.renderer.setSize(viewer.canvas.clientWidth, viewer.canvas.clientHeight)
        this._refreshParams()
        if (this.autoAddToContainer) {
            viewer.container.prepend(this.renderer.domElement) // behind the canvas so that we get pointer events
            const element = this.renderer.domElement
            element.style.pointerEvents = 'none'
            const canvasStyles = getComputedStyle(viewer.canvas)
            if (canvasStyles.position === 'absolute') {
                this._lastStyles = element.style.cssText
                // copy styles from canvas to svg so it looks the same.
                element.style.top = canvasStyles.top
                element.style.left = canvasStyles.left
                element.style.width = canvasStyles.width
                element.style.height = canvasStyles.height
                // element.style.zIndex = '999999' // svg should be behind the canvas
            } else {
                this._viewer?.console.warn('BasicSVGRendererPlugin: canvas position should be absolute for proper rendering')
            }
            viewer.renderManager.addEventListener('resize', this._onResize)
        }
        this.renderer.domElement.style.display = this.enabled ? '' : 'none'
    }

    onRemove(viewer: ThreeViewer) {
        super.onRemove(viewer)
        if (this.autoAddToContainer) {
            viewer.container.removeChild(this.renderer.domElement)
        }
        if (this._lastStyles !== undefined) {
            this.renderer.domElement.style.cssText = this._lastStyles
            this._lastStyles = undefined
        }
        viewer.renderManager.removeEventListener('resize', this._onResize)
        this.renderer.domElement.style.display = 'none'
    }


    @uiToggle()
        autoRender = true

    @uiButton()
    render() {
        if (!this._viewer) return
        if (this.isDisabled()) return
        this.renderer.render(this._viewer.scene, this._viewer.scene.mainCamera)
    }

    @uiButton()
    download() {
        const svg = this.renderer.domElement.outerHTML
        const blob = new Blob([svg], {type: 'image/svg+xml'})
        this._viewer?.exportBlob(blob, 'scene.svg')
    }

    protected _viewerListeners = {
        postRender: (_: IViewerEvent)=>{
            if (this.autoRender) this.render()
        },
    }

    get svgNode() {
        return this.renderer.domElement
    }

    protected _refreshParams() {
        if (this.isDisabled()) return
        this.renderer.setQuality('medium')
    }
    protected _onResize() {
        if (!this._viewer) return
        this.renderer.setSize(this._viewer.canvas.clientWidth, this._viewer.canvas.clientHeight)
    }

}
