package com.cjm721.overloaded.client.render.dynamic.compressed.block;

import com.cjm721.overloaded.client.render.dynamic.ImageUtil;
import com.cjm721.overloaded.client.resource.BlockResourcePack;
import com.cjm721.overloaded.config.OverloadedConfig;
import net.minecraft.client.renderer.texture.TextureUtil;
import net.minecraft.util.ResourceLocation;
import net.minecraftforge.client.event.TextureStitchEvent;
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
import net.minecraftforge.fml.relauncher.Side;
import net.minecraftforge.fml.relauncher.SideOnly;

import javax.annotation.Nonnull;
import java.awt.image.BufferedImage;
import java.awt.image.WritableRaster;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

@SideOnly(Side.CLIENT)
public class CompressedBlockAssets {

    private static List<CompressedResourceLocation> toCreateTextures = new ArrayList<>();

    public static void addToTextureQueue(CompressedResourceLocation location) {
        toCreateTextures.add(location);

        generateTexture(location);
    }

    private static String getBlockState(@Nonnull ResourceLocation location) {
        return String.format(
            "{ " +
                "\"forge_marker\": 1, " +
                "\"defaults\": { " +
                    "\"model\": \"cube_all\", " +
                    "\"textures\": { " +
                        "\"all\": \"%1$s\" " +
                    "} " +
                "}," +
                "\"variants\": { " +
                    "\"normal\": [{ }], " +
                    "\"inventory\": [{ }] " +
                "}" +
            "}", getBlocksPath(location));
    }

    private static ResourceLocation getBlocksPath(@Nonnull ResourceLocation base) {
        return new ResourceLocation(base.getResourceDomain(), "blocks/" + base.getResourcePath());
    }

    private static ResourceLocation getTexturePath(@Nonnull ResourceLocation base) {
        return new ResourceLocation(base.getResourceDomain(), "textures/blocks/" + base.getResourcePath() + ".png");
    }

    public static ResourceLocation getJsonPath(@Nonnull ResourceLocation base) {
        return new ResourceLocation(base.getResourceDomain(), "blockstates/" + base.getResourcePath() + ".json");
    }

    @SubscribeEvent
    public void texturePre(TextureStitchEvent.Pre event) {
        for(CompressedResourceLocation locations: toCreateTextures) {
            if (!generateTexture(locations)) return;

            event.getMap().registerSprite(getBlocksPath(locations.compressed));
        }
    }

    private static boolean generateTexture(@Nonnull CompressedResourceLocation locations) {
        String state = getBlockState(locations.compressed);
        BlockResourcePack.INSTANCE.addBlockState(getJsonPath(locations.compressed), state);

        BufferedImage image;
        try {
            image = TextureUtil.readBufferedImage(ImageUtil.getTextureInputStream(CompressedBlockAssets.getTexturePath(locations.base)));
        } catch (IOException e) {
            e.printStackTrace();
            return false;
        }

        int scale = 1 + locations.compressionAmount;

        WritableRaster raster = image.getColorModel().createCompatibleWritableRaster(image.getWidth()*scale,image.getHeight()*scale);
        int[] pixels = image.getData().getPixels(0,0,image.getWidth(), image.getHeight(), (int[])null);

        for(int x = 0; x < scale; x++) {
            for(int y = 0; y < scale; y++) {
                raster.setPixels(x*image.getWidth(),y*image.getHeight(),image.getWidth(),image.getHeight(),pixels);
            }
        }
        BufferedImage compressedImage = new BufferedImage(image.getColorModel(), raster, true, null);

        if(compressedImage.getWidth() > OverloadedConfig.compressedConfig.maxTextureWidth) {
            compressedImage = ImageUtil.scaleDownToWidth(compressedImage, OverloadedConfig.compressedConfig.maxTextureWidth);
        }

        ResourceLocation rl = getTexturePath(locations.compressed);
        BlockResourcePack.INSTANCE.addImage(rl, compressedImage);

        return true;
    }

    public static class CompressedResourceLocation {
        public ResourceLocation base;
        public ResourceLocation compressed;
        public int compressionAmount;

        public CompressedResourceLocation(@Nonnull ResourceLocation base, @Nonnull ResourceLocation compressed, int compressionAmount) {
            this.base = base;
            this.compressed = compressed;
            this.compressionAmount = compressionAmount;
        }
    }

}

@@ -1197,15 +1197,27 @@
     
+    
 %22%7B %22 +%0A
+        
     
@@ -1270,16 +1270,24 @@
         
+       
+ 
 %22%5C%22defau
@@ -1291,32 +1291,36 @@
 faults%5C%22: %7B %22 +%0A
+    
                 
@@ -1349,24 +1349,28 @@
 _all%5C%22, %22 +%0A
+    
             
@@ -1465,16 +1465,20 @@
         
+    
 %22%7D %22 +%0A 
@@ -1496,15 +1496,31 @@
     
+      
+  
 %22%7D,%22 +%0A
+        
     
@@ -1572,16 +1572,20 @@
         
+    
 %22%5C%22norma
@@ -1596,24 +1596,28 @@
  %5B%7B %7D%5D, %22 +%0A
+    
             
@@ -1670,14 +1670,34 @@
     
+ 
-%22%7D%22 +%0A
+       %22%7D%22 +%0A            
     
@@ -2433,16 +2433,17 @@
      for
+ 
 (Compres
@@ -2471,16 +2471,17 @@
 ocations
+ 
 : toCrea
@@ -3221,32 +3221,105 @@
 ressionAmount;%0A%0A
+        int squareSize = Math.min(image.getWidth(), image.getHeight());%0A%0A
         Writable
@@ -3391,57 +3391,49 @@
 ter(
-image.getWidth()*scale,image.getHeight()*
+squareSize * scale, squareSize * 
 scale);%0A
     
@@ -3428,16 +3428,18 @@
 scale);%0A
+%0A%0A
         
@@ -3485,45 +3485,34 @@
 s(0,
+ 
 0,
-image.getWidth(), image.getHeight()
+ squareSize, squareSize
 , (i
@@ -3516,16 +3516,17 @@
  (int%5B%5D)
+ 
 null);%0A%0A
@@ -3532,24 +3532,25 @@
 %0A        for
+ 
 (int x = 0; 
@@ -3582,16 +3582,17 @@
      for
+ 
 (int y =
@@ -3651,81 +3651,63 @@
 ls(x
-*image.getWidth(),y*image.getHeight(),image.getWidth(),image.getHeight(),
+ * squareSize, y * squareSize, squareSize, squareSize, 
 pixe
@@ -3848,16 +3848,17 @@
       if
+ 
 (compres

Fix #27 issue was it not being square due to animations so I just use the first still now.