import { SceneSystem, Transform, Camera, PixiView, } from 'dacha';
import { Graphics, Filter, GlProgram, defaultFilterVert, Color } from 'pixi.js';
import { Settings } from '../../components';
import { getGridFragmentShader } from './utils';
export class GridSystem extends SceneSystem {
    constructor(options) {
        super();
        this.handleWindowResize = () => {
            const { windowSizeX, windowSizeY, zoom } = this.mainActor.getComponent(Camera);
            if (!this.gridView) {
                return;
            }
            const uniforms = this.gridView.filters[0].resources.myUniforms.uniforms;
            uniforms.u_graphic_resolution = [windowSizeX, windowSizeY];
            this.gridView.setSize(windowSizeX / zoom, windowSizeY / zoom);
        };
        const { world } = options;
        this.mainActor = world.data.mainActor;
        this.gridActor = this.mainActor.findChildById('grid');
        this.gridActor.setComponent(new PixiView({
            createView: () => {
                const gridView = new Graphics();
                gridView.rect(-1, -1, 2, 2).fill({ color: 'transparent' });
                gridView.filters = [
                    new Filter({
                        glProgram: new GlProgram({
                            fragment: getGridFragmentShader(),
                            vertex: defaultFilterVert,
                        }),
                        resources: {
                            myUniforms: {
                                u_graphic_resolution: {
                                    type: 'vec2<f32>',
                                    value: [0, 0],
                                },
                                u_spacing: {
                                    type: 'f32',
                                    value: 0,
                                },
                                u_camera_zoom: {
                                    type: 'f32',
                                    value: 1,
                                },
                                u_offset: {
                                    type: 'vec2<f32>',
                                    value: [0, 0],
                                },
                                u_line_color: {
                                    type: 'vec4<f32>',
                                    value: [1, 1, 1, 1],
                                },
                            },
                        },
                    }),
                ];
                this.gridView = gridView;
                this.handleWindowResize();
                return gridView;
            },
            sortingLayer: 'editor-layer-1',
            sortOffsetX: 0,
            sortOffsetY: 0,
        }));
        this.prevState = {};
        window.addEventListener('resize', this.handleWindowResize);
    }
    onWorldDestroy() {
        window.removeEventListener('resize', this.handleWindowResize);
    }
    isGridChanged() {
        const settings = this.mainActor.getComponent(Settings);
        const gridStep = settings.data.gridStep;
        const gridColor = settings.data.gridColor;
        const { zoom } = this.mainActor.getComponent(Camera);
        let isChanged = false;
        if (zoom !== this.prevState.zoom ||
            gridStep !== this.prevState.gridStep ||
            gridColor !== this.prevState.gridColor) {
            isChanged = true;
            this.prevState.zoom = zoom;
            this.prevState.gridStep = gridStep;
            this.prevState.gridColor = gridColor;
        }
        return isChanged;
    }
    updateGridSettings() {
        if (!this.gridView) {
            return;
        }
        const settings = this.mainActor.getComponent(Settings);
        const gridStep = settings.data.gridStep;
        const gridColor = settings.data.gridColor;
        const { zoom } = this.mainActor.getComponent(Camera);
        const uniforms = this.gridView.filters[0].resources.myUniforms.uniforms;
        uniforms.u_camera_zoom = zoom * devicePixelRatio;
        uniforms.u_spacing = gridStep;
        uniforms.u_line_color = new Color(gridColor).toArray();
    }
    update() {
        if (!this.gridView) {
            return;
        }
        const settings = this.mainActor.getComponent(Settings);
        const showGrid = settings.data.showGrid;
        this.gridView.renderable = showGrid;
        if (!showGrid) {
            return;
        }
        const { zoom, windowSizeX, windowSizeY } = this.mainActor.getComponent(Camera);
        const { world: { position }, } = this.gridActor.getComponent(Transform);
        const uniforms = this.gridView.filters[0].resources.myUniforms.uniforms;
        uniforms.u_offset = [position.x, position.y];
        const shouldUpdateGrid = this.isGridChanged();
        if (shouldUpdateGrid) {
            this.gridView.setSize(windowSizeX / zoom, windowSizeY / zoom);
            this.updateGridSettings();
        }
    }
}
GridSystem.systemName = 'GridSystem';
