/////////////////////////////////////
// Complementary Shaders by EminGT //
// With Euphoria Patches by SpacEagle17 and isuewo //
/////////////////////////////////////

//Common//
#include "/lib/common.glsl"

//////////Fragment Shader//////////Fragment Shader//////////Fragment Shader//////////
#ifdef FRAGMENT_SHADER

//Pipeline Constants//

//Common Variables//

//Common Functions//

//Includes//

//Program//
void main() {
    discard;
}

#endif

//////////Vertex Shader//////////Vertex Shader//////////Vertex Shader//////////
#ifdef VERTEX_SHADER

//Pipeline Constants//
#if END_CRYSTAL_VORTEX_INTERNAL > 0 || DRAGON_DEATH_EFFECT_INTERNAL > 0
    #extension GL_ARB_shader_image_load_store : enable
#endif

//Uniforms//
#if END_CRYSTAL_VORTEX_INTERNAL > 0 || DRAGON_DEATH_EFFECT_INTERNAL > 0
    layout(r32i) uniform iimage2D endcrystal_img;
#endif
//Attributes//

//Common Variables//

//Common Functions//

//Includes//

//Program//
void main() {
    #if END_CRYSTAL_VORTEX_INTERNAL > 0 || DRAGON_DEATH_EFFECT_INTERNAL > 0
        vec4 position0 = ftransform();
        if (position0.x < 0.0 && position0.y > 0.0) {
            for (int index = 0; index < 20; index++) {
                int state = imageLoad(endcrystal_img, ivec2(index, 8)).r;
                state -= max(1, int(10000 * frameTime));
                if (state < 0) {
                    for (int i = 0; i < 5; i++) {
                        imageStore(endcrystal_img, ivec2(index, i+5), ivec4(0));
                    }
                } else {
                    ivec4 writeData = ivec4(
                        imageLoad(endcrystal_img, ivec2(index, 5)).r,
                        imageLoad(endcrystal_img, ivec2(index, 6)).r,
                        imageLoad(endcrystal_img, ivec2(index, 7)).r,
                        state
                    );
                    writeData.xyz += ivec3(10000 * (previousCameraPosition - cameraPosition));
                    for (int i = 0; i < 4; i++) {
                        imageStore(endcrystal_img, ivec2(index, i+5), ivec4(writeData[i]));
                    }
                    imageStore(endcrystal_img, ivec2(index, 9), ivec4(
                        imageLoad(endcrystal_img, ivec2(index, 9)).r + int(10000 * frameTime)
                    ));
                }
            }
            // crystals
            for (int index = 0; index < 20; index++) {
                ivec4 newData = ivec4(
                    imageLoad(endcrystal_img, ivec2(index, 1)).r,
                    imageLoad(endcrystal_img, ivec2(index, 2)).r,
                    imageLoad(endcrystal_img, ivec2(index, 3)).r,
                    imageLoad(endcrystal_img, ivec2(index, 4)).r
                );
                if (newData.w > 0) {
                    vec3 pos = vec3(newData.xyz) / newData.w;
                    int temporalIndex = -1;
                    for (int k = 0; k < 20; k++) {
                        ivec4 temporalData = ivec4(
                            imageLoad(endcrystal_img, ivec2(k, 5)).r,
                            imageLoad(endcrystal_img, ivec2(k, 6)).r,
                            imageLoad(endcrystal_img, ivec2(k, 7)).r,
                            imageLoad(endcrystal_img, ivec2(k, 8)).r
                        );
                        vec3 temporalPos = 0.0001 * temporalData.xyz;
                        if (temporalData.w > 0 && length((temporalPos - pos) * vec3(1.0, 0.3, 1.0)) < 1.0) {
                            temporalIndex = k;
                            break;
                        }
                    }
                    if (temporalIndex == -1) {
                        for (int k = 0; k < 20; k++) {
                            int previousWeight = imageAtomicCompSwap(endcrystal_img, ivec2(k, 8), 0, -1);
                            if (previousWeight == 0) {
                                temporalIndex = k;
                                break;
                            }
                        }
                    }
                    if (temporalIndex >= 0) {
                        ivec4 storeData = ivec4(10000 * pos, 16000);
                        for (int i = 0; i < 4; i++) {
                            imageStore(endcrystal_img, ivec2(temporalIndex, i+5), ivec4(storeData[i]));
                        }
                    }
                }
            }
            // healing beams
            for (int index = 20; index < 35; index++) {
                ivec4 writeData = ivec4(
                    imageLoad(endcrystal_img, ivec2(index, 1)).r,
                    imageLoad(endcrystal_img, ivec2(index, 2)).r,
                    imageLoad(endcrystal_img, ivec2(index, 3)).r,
                    imageLoad(endcrystal_img, ivec2(index, 4)).r
                );
                for (int i = 0; i < 4; i++) {
                    imageStore(endcrystal_img, ivec2(index, i + 5), ivec4(writeData[i]));
                }
            }
            // dragon position
                const int index = 35;
                int isDying = imageLoad(endcrystal_img, ivec2(index, 0)).r;
                // if (isDying == 0) isDying = 10000; // Helpul for debugging
                ivec4 readData = ivec4(
                    imageLoad(endcrystal_img, ivec2(index, 1)).r,
                    imageLoad(endcrystal_img, ivec2(index, 2)).r,
                    imageLoad(endcrystal_img, ivec2(index, 3)).r,
                    imageLoad(endcrystal_img, ivec2(index, 4)).r
                );
                ivec4 temporalData = ivec4(
                    imageLoad(endcrystal_img, ivec2(index, 5)).r,
                    imageLoad(endcrystal_img, ivec2(index, 6)).r,
                    imageLoad(endcrystal_img, ivec2(index, 7)).r,
                    imageLoad(endcrystal_img, ivec2(index, 8)).r
                );
                ivec4 writeData = ivec4(
                    readData.w > 0 ? 10000.0 * readData.xyz / readData.w : temporalData.xyz + ivec3(10000 * (previousCameraPosition - cameraPosition)),
                    isDying > 0 ? temporalData.w + int(10000 * frameTime) : 0
                );
                imageStore(endcrystal_img, ivec2(index, 0), ivec4(max(0, isDying - int(1000 * frameTime))));
                for (int i = 0; i < 4; i++) {
                    imageStore(endcrystal_img, ivec2(index, i + 1), ivec4(0));
                    imageStore(endcrystal_img, ivec2(index, i + 5), ivec4(writeData[i]));
                }
            // clear temporally unstable data
            for (int index = 0; index < 35; index++) {
                for (int i = 0; i < 5; i++) {
                    imageStore(endcrystal_img, ivec2(index, i), ivec4(0));
                }
            }
        }
        gl_Position = vec4(-1);
    #endif
}

#endif
