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 elw, final ResourceManager abc, final RenderTarget dgf, final ResourceLocation uh) throws IOException, JsonSyntaxException {
        this.passes = Lists.newArrayList();
        this.customRenderTargets = Maps.newHashMap();
        this.fullSizedTargets = Lists.newArrayList();
        this.resourceManager = abc;
        this.screenTarget = dgf;
        this.time = 0.0f;
        this.lastStamp = 0.0f;
        this.screenWidth = dgf.viewWidth;
        this.screenHeight = dgf.viewHeight;
        this.name = uh.toString();
        this.updateOrthoMatrix();
        this.load(elw, uh);
    }
    
    private void load(final TextureManager elw, final ResourceLocation uh) throws IOException, JsonSyntaxException {
        Resource abb4 = null;
        try {
            abb4 = this.resourceManager.getResource(uh);
            final JsonObject jsonObject5 = GsonHelper.parse(new InputStreamReader(abb4.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 uk11 = ChainedJsonException.forException(exception10);
                        uk11.prependJsonKey("targets[" + integer7 + "]");
                        throw uk11;
                    }
                    ++integer7;
                }
            }
            if (GsonHelper.isArrayNode(jsonObject5, "passes")) {
                final JsonArray jsonArray6 = jsonObject5.getAsJsonArray("passes");
                int integer7 = 0;
                for (final JsonElement jsonElement9 : jsonArray6) {
                    try {
                        this.parsePassNode(elw, jsonElement9);
                    }
                    catch (Exception exception10) {
                        final ChainedJsonException uk11 = ChainedJsonException.forException(exception10);
                        uk11.prependJsonKey("passes[" + integer7 + "]");
                        throw uk11;
                    }
                    ++integer7;
                }
            }
        }
        catch (Exception exception11) {
            final ChainedJsonException uk12 = ChainedJsonException.forException(exception11);
            uk12.setFilenameAndFlush(uh.getPath());
            throw uk12;
        }
        finally {
            IOUtils.closeQuietly((Closeable)abb4);
        }
    }
    
    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 elw, 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 dgf8 = this.getRenderTarget(string6);
        final RenderTarget dgf9 = this.getRenderTarget(string7);
        if (dgf8 == null) {
            throw new ChainedJsonException("Input target '" + string6 + "' does not exist");
        }
        if (dgf9 == null) {
            throw new ChainedJsonException("Output target '" + string7 + "' does not exist");
        }
        final PostPass ecd10 = this.addPass(string5, dgf8, dgf9);
        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");
                    boolean boolean18;
                    String string10;
                    if (string9.endsWith(":depth")) {
                        boolean18 = true;
                        string10 = string9.substring(0, string9.lastIndexOf(58));
                    }
                    else {
                        boolean18 = false;
                        string10 = string9;
                    }
                    final RenderTarget dgf10 = this.getRenderTarget(string10);
                    if (dgf10 == null) {
                        if (boolean18) {
                            throw new ChainedJsonException("Render target '" + string10 + "' can't be used as depth buffer");
                        }
                        final ResourceLocation uh21 = new ResourceLocation("textures/effect/" + string10 + ".png");
                        Resource abb22 = null;
                        try {
                            abb22 = this.resourceManager.getResource(uh21);
                        }
                        catch (FileNotFoundException fileNotFoundException23) {
                            throw new ChainedJsonException("Render target or texture '" + string10 + "' does not exist");
                        }
                        finally {
                            IOUtils.closeQuietly((Closeable)abb22);
                        }
                        elw.bind(uh21);
                        final AbstractTexture elj23 = elw.getTexture(uh21);
                        final int integer13 = GsonHelper.getAsInt(jsonObject5, "width");
                        final int integer14 = GsonHelper.getAsInt(jsonObject5, "height");
                        final boolean boolean19 = GsonHelper.getAsBoolean(jsonObject5, "bilinear");
                        if (boolean19) {
                            RenderSystem.texParameter(3553, 10241, 9729);
                            RenderSystem.texParameter(3553, 10240, 9729);
                        }
                        else {
                            RenderSystem.texParameter(3553, 10241, 9728);
                            RenderSystem.texParameter(3553, 10240, 9728);
                        }
                        ecd10.addAuxAsset(string8, elj23.getId(), integer13, integer14);
                    }
                    else if (boolean18) {
                        ecd10.addAuxAsset(string8, dgf10.depthBufferId, dgf10.width, dgf10.height);
                    }
                    else {
                        ecd10.addAuxAsset(string8, dgf10, dgf10.width, dgf10.height);
                    }
                }
                catch (Exception exception15) {
                    final ChainedJsonException uk16 = ChainedJsonException.forException(exception15);
                    uk16.prependJsonKey("auxtargets[" + integer12 + "]");
                    throw uk16;
                }
                ++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 uk17 = ChainedJsonException.forException(exception16);
                    uk17.prependJsonKey("uniforms[" + integer15 + "]");
                    throw uk17;
                }
                ++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 dhf5 = this.passes.get(this.passes.size() - 1).getEffect().getUniform(string4);
        if (dhf5 == 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 uk12 = ChainedJsonException.forException(exception11);
                uk12.prependJsonKey("values[" + integer7 + "]");
                throw uk12;
            }
            ++integer7;
        }
        switch (integer7) {
            case 1: {
                dhf5.set(arr6[0]);
                break;
            }
            case 2: {
                dhf5.set(arr6[0], arr6[1]);
                break;
            }
            case 3: {
                dhf5.set(arr6[0], arr6[1], arr6[2]);
                break;
            }
            case 4: {
                dhf5.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 dgf5 = new RenderTarget(integer2, integer3, true, Minecraft.ON_OSX);
        dgf5.setClearColor(0.0f, 0.0f, 0.0f, 0.0f);
        this.customRenderTargets.put(string, dgf5);
        if (integer2 == this.screenWidth && integer3 == this.screenHeight) {
            this.fullSizedTargets.add(dgf5);
        }
    }
    
    @Override
    public void close() {
        for (final RenderTarget dgf3 : this.customRenderTargets.values()) {
            dgf3.destroyBuffers();
        }
        for (final PostPass ecd3 : this.passes) {
            ecd3.close();
        }
        this.passes.clear();
    }
    
    public PostPass addPass(final String string, final RenderTarget dgf2, final RenderTarget dgf3) throws IOException {
        final PostPass ecd5 = new PostPass(this.resourceManager, string, dgf2, dgf3);
        this.passes.add(this.passes.size(), ecd5);
        return ecd5;
    }
    
    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 ecd5 : this.passes) {
            ecd5.setOrthoMatrix(this.shaderOrthoMatrix);
        }
        for (final RenderTarget dgf5 : this.fullSizedTargets) {
            dgf5.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 ecd4 : this.passes) {
            ecd4.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);
    }
}
