package net.minecraft.client.renderer;

import net.minecraft.client.Minecraft;
import com.mojang.blaze3d.shaders.Uniform;
import net.minecraft.client.renderer.texture.AbstractTexture;
import com.mojang.blaze3d.systems.RenderSystem;
import java.io.FileNotFoundException;
import java.util.Iterator;
import com.google.gson.JsonArray;
import com.google.gson.JsonObject;
import net.minecraft.server.packs.resources.Resource;
import java.io.Closeable;
import org.apache.commons.io.IOUtils;
import net.minecraft.server.ChainedJsonException;
import com.google.gson.JsonElement;
import java.io.Reader;
import net.minecraft.util.GsonHelper;
import java.io.InputStreamReader;
import java.nio.charset.StandardCharsets;
import com.google.gson.JsonSyntaxException;
import java.io.IOException;
import com.google.common.collect.Maps;
import com.google.common.collect.Lists;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.client.renderer.texture.TextureManager;
import com.mojang.math.Matrix4f;
import java.util.Map;
import java.util.List;
import net.minecraft.server.packs.resources.ResourceManager;
import com.mojang.blaze3d.pipeline.RenderTarget;

public class PostChain implements AutoCloseable {
    private final RenderTarget screenTarget;
    private final ResourceManager resourceManager;
    private final String name;
    private final List<PostPass> passes;
    private final Map<String, RenderTarget> customRenderTargets;
    private final List<RenderTarget> fullSizedTargets;
    private Matrix4f shaderOrthoMatrix;
    private int screenWidth;
    private int screenHeight;
    private float time;
    private float lastStamp;
    
    public PostChain(final TextureManager eak, final ResourceManager zb, final RenderTarget cxe, final ResourceLocation sm) throws IOException, JsonSyntaxException {
        this.passes = Lists.newArrayList();
        this.customRenderTargets = Maps.newHashMap();
        this.fullSizedTargets = Lists.newArrayList();
        this.resourceManager = zb;
        this.screenTarget = cxe;
        this.time = 0.0f;
        this.lastStamp = 0.0f;
        this.screenWidth = cxe.viewWidth;
        this.screenHeight = cxe.viewHeight;
        this.name = sm.toString();
        this.updateOrthoMatrix();
        this.load(eak, sm);
    }
    
    private void load(final TextureManager eak, final ResourceLocation sm) throws IOException, JsonSyntaxException {
        Resource za4 = null;
        try {
            za4 = this.resourceManager.getResource(sm);
            final JsonObject jsonObject5 = GsonHelper.parse(new InputStreamReader(za4.getInputStream(), StandardCharsets.UTF_8));
            if (GsonHelper.isArrayNode(jsonObject5, "targets")) {
                final JsonArray jsonArray6 = jsonObject5.getAsJsonArray("targets");
                int integer7 = 0;
                for (final JsonElement jsonElement9 : jsonArray6) {
                    try {
                        this.parseTargetNode(jsonElement9);
                    }
                    catch (Exception exception10) {
                        final ChainedJsonException sp11 = ChainedJsonException.forException(exception10);
                        sp11.prependJsonKey("targets[" + integer7 + "]");
                        throw sp11;
                    }
                    ++integer7;
                }
            }
            if (GsonHelper.isArrayNode(jsonObject5, "passes")) {
                final JsonArray jsonArray6 = jsonObject5.getAsJsonArray("passes");
                int integer7 = 0;
                for (final JsonElement jsonElement9 : jsonArray6) {
                    try {
                        this.parsePassNode(eak, jsonElement9);
                    }
                    catch (Exception exception10) {
                        final ChainedJsonException sp11 = ChainedJsonException.forException(exception10);
                        sp11.prependJsonKey("passes[" + integer7 + "]");
                        throw sp11;
                    }
                    ++integer7;
                }
            }
        }
        catch (Exception exception11) {
            final ChainedJsonException sp12 = ChainedJsonException.forException(exception11);
            sp12.setFilenameAndFlush(sm.getPath());
            throw sp12;
        }
        finally {
            IOUtils.closeQuietly((Closeable)za4);
        }
    }
    
    private void parseTargetNode(final JsonElement jsonElement) throws ChainedJsonException {
        if (GsonHelper.isStringValue(jsonElement)) {
            this.addTempTarget(jsonElement.getAsString(), this.screenWidth, this.screenHeight);
        }
        else {
            final JsonObject jsonObject3 = GsonHelper.convertToJsonObject(jsonElement, "target");
            final String string4 = GsonHelper.getAsString(jsonObject3, "name");
            final int integer5 = GsonHelper.getAsInt(jsonObject3, "width", this.screenWidth);
            final int integer6 = GsonHelper.getAsInt(jsonObject3, "height", this.screenHeight);
            if (this.customRenderTargets.containsKey(string4)) {
                throw new ChainedJsonException(string4 + " is already defined");
            }
            this.addTempTarget(string4, integer5, integer6);
        }
    }
    
    private void parsePassNode(final TextureManager eak, final JsonElement jsonElement) throws IOException {
        final JsonObject jsonObject4 = GsonHelper.convertToJsonObject(jsonElement, "pass");
        final String string5 = GsonHelper.getAsString(jsonObject4, "name");
        final String string6 = GsonHelper.getAsString(jsonObject4, "intarget");
        final String string7 = GsonHelper.getAsString(jsonObject4, "outtarget");
        final RenderTarget cxe8 = this.getRenderTarget(string6);
        final RenderTarget cxe9 = this.getRenderTarget(string7);
        if (cxe8 == null) {
            throw new ChainedJsonException("Input target '" + string6 + "' does not exist");
        }
        if (cxe9 == null) {
            throw new ChainedJsonException("Output target '" + string7 + "' does not exist");
        }
        final PostPass dqx10 = this.addPass(string5, cxe8, cxe9);
        final JsonArray jsonArray11 = GsonHelper.getAsJsonArray(jsonObject4, "auxtargets", null);
        if (jsonArray11 != null) {
            int integer12 = 0;
            for (final JsonElement jsonElement2 : jsonArray11) {
                try {
                    final JsonObject jsonObject5 = GsonHelper.convertToJsonObject(jsonElement2, "auxtarget");
                    final String string8 = GsonHelper.getAsString(jsonObject5, "name");
                    final String string9 = GsonHelper.getAsString(jsonObject5, "id");
                    final RenderTarget cxe10 = this.getRenderTarget(string9);
                    if (cxe10 == null) {
                        final ResourceLocation sm19 = new ResourceLocation("textures/effect/" + string9 + ".png");
                        Resource za20 = null;
                        try {
                            za20 = this.resourceManager.getResource(sm19);
                        }
                        catch (FileNotFoundException fileNotFoundException21) {
                            throw new ChainedJsonException("Render target or texture '" + string9 + "' does not exist");
                        }
                        finally {
                            IOUtils.closeQuietly((Closeable)za20);
                        }
                        eak.bind(sm19);
                        final AbstractTexture dzw21 = eak.getTexture(sm19);
                        final int integer13 = GsonHelper.getAsInt(jsonObject5, "width");
                        final int integer14 = GsonHelper.getAsInt(jsonObject5, "height");
                        final boolean boolean24 = GsonHelper.getAsBoolean(jsonObject5, "bilinear");
                        if (boolean24) {
                            RenderSystem.texParameter(3553, 10241, 9729);
                            RenderSystem.texParameter(3553, 10240, 9729);
                        }
                        else {
                            RenderSystem.texParameter(3553, 10241, 9728);
                            RenderSystem.texParameter(3553, 10240, 9728);
                        }
                        dqx10.addAuxAsset(string8, dzw21.getId(), integer13, integer14);
                    }
                    else {
                        dqx10.addAuxAsset(string8, cxe10, cxe10.width, cxe10.height);
                    }
                }
                catch (Exception exception15) {
                    final ChainedJsonException sp16 = ChainedJsonException.forException(exception15);
                    sp16.prependJsonKey("auxtargets[" + integer12 + "]");
                    throw sp16;
                }
                ++integer12;
            }
        }
        final JsonArray jsonArray12 = GsonHelper.getAsJsonArray(jsonObject4, "uniforms", null);
        if (jsonArray12 != null) {
            int integer15 = 0;
            for (final JsonElement jsonElement3 : jsonArray12) {
                try {
                    this.parseUniformNode(jsonElement3);
                }
                catch (Exception exception16) {
                    final ChainedJsonException sp17 = ChainedJsonException.forException(exception16);
                    sp17.prependJsonKey("uniforms[" + integer15 + "]");
                    throw sp17;
                }
                ++integer15;
            }
        }
    }
    
    private void parseUniformNode(final JsonElement jsonElement) throws ChainedJsonException {
        final JsonObject jsonObject3 = GsonHelper.convertToJsonObject(jsonElement, "uniform");
        final String string4 = GsonHelper.getAsString(jsonObject3, "name");
        final Uniform cye5 = this.passes.get(this.passes.size() - 1).getEffect().getUniform(string4);
        if (cye5 == null) {
            throw new ChainedJsonException("Uniform '" + string4 + "' does not exist");
        }
        final float[] arr6 = new float[4];
        int integer7 = 0;
        final JsonArray jsonArray8 = GsonHelper.getAsJsonArray(jsonObject3, "values");
        for (final JsonElement jsonElement2 : jsonArray8) {
            try {
                arr6[integer7] = GsonHelper.convertToFloat(jsonElement2, "value");
            }
            catch (Exception exception11) {
                final ChainedJsonException sp12 = ChainedJsonException.forException(exception11);
                sp12.prependJsonKey("values[" + integer7 + "]");
                throw sp12;
            }
            ++integer7;
        }
        switch (integer7) {
            case 1: {
                cye5.set(arr6[0]);
                break;
            }
            case 2: {
                cye5.set(arr6[0], arr6[1]);
                break;
            }
            case 3: {
                cye5.set(arr6[0], arr6[1], arr6[2]);
                break;
            }
            case 4: {
                cye5.set(arr6[0], arr6[1], arr6[2], arr6[3]);
                break;
            }
        }
    }
    
    public RenderTarget getTempTarget(final String string) {
        return this.customRenderTargets.get(string);
    }
    
    public void addTempTarget(final String string, final int integer2, final int integer3) {
        final RenderTarget cxe5 = new RenderTarget(integer2, integer3, true, Minecraft.ON_OSX);
        cxe5.setClearColor(0.0f, 0.0f, 0.0f, 0.0f);
        this.customRenderTargets.put(string, cxe5);
        if (integer2 == this.screenWidth && integer3 == this.screenHeight) {
            this.fullSizedTargets.add(cxe5);
        }
    }
    
    @Override
    public void close() {
        for (final RenderTarget cxe3 : this.customRenderTargets.values()) {
            cxe3.destroyBuffers();
        }
        for (final PostPass dqx3 : this.passes) {
            dqx3.close();
        }
        this.passes.clear();
    }
    
    public PostPass addPass(final String string, final RenderTarget cxe2, final RenderTarget cxe3) throws IOException {
        final PostPass dqx5 = new PostPass(this.resourceManager, string, cxe2, cxe3);
        this.passes.add(this.passes.size(), dqx5);
        return dqx5;
    }
    
    private void updateOrthoMatrix() {
        this.shaderOrthoMatrix = Matrix4f.orthographic((float)this.screenTarget.width, (float)this.screenTarget.height, 0.1f, 1000.0f);
    }
    
    public void resize(final int integer1, final int integer2) {
        this.screenWidth = this.screenTarget.width;
        this.screenHeight = this.screenTarget.height;
        this.updateOrthoMatrix();
        for (final PostPass dqx5 : this.passes) {
            dqx5.setOrthoMatrix(this.shaderOrthoMatrix);
        }
        for (final RenderTarget cxe5 : this.fullSizedTargets) {
            cxe5.resize(integer1, integer2, Minecraft.ON_OSX);
        }
    }
    
    public void process(final float float1) {
        if (float1 < this.lastStamp) {
            this.time += 1.0f - this.lastStamp;
            this.time += float1;
        }
        else {
            this.time += float1 - this.lastStamp;
        }
        this.lastStamp = float1;
        while (this.time > 20.0f) {
            this.time -= 20.0f;
        }
        for (final PostPass dqx4 : this.passes) {
            dqx4.process(this.time / 20.0f);
        }
    }
    
    public final String getName() {
        return this.name;
    }
    
    private RenderTarget getRenderTarget(final String string) {
        if (string == null) {
            return null;
        }
        if (string.equals("minecraft:main")) {
            return this.screenTarget;
        }
        return this.customRenderTargets.get(string);
    }
}
