package net.vulkanmod.vulkan.util;

import java.nio.ByteBuffer;
import java.nio.FloatBuffer;

public class ColorUtil {
   private static final float COLOR_INV = 0.003921569F;
   static ColorConsumer colorConsumer = new DefaultColorConsumer();

   public static void useGammaCorrection(boolean b) {
      colorConsumer = (ColorConsumer)(b ? new GammaColorConsumer() : new DefaultColorConsumer());
   }

   public static int floatToInt(float f) {
      return (int)(f * 255.0F) & 255;
   }

   public static float unpackColor(int c, int s) {
      return (float)(c >> s & 255) * 0.003921569F;
   }

   public static int BGRAtoRGBA(int v) {
      byte r = (byte)(v >> 16);
      byte b = (byte)v;
      return r & 255 | b << 16 & 16711680 | v & -16711936;
   }

   public static float gamma(float f) {
      return (float)Math.pow((double)f, 2.2);
   }

   public static void setRGBA_Buffer(MappedBuffer buffer, float r, float g, float b, float a) {
      colorConsumer.setRGBA_Buffer(buffer, r, g, b, a);
   }

   public static void setRGBA_Buffer(FloatBuffer buffer, float r, float g, float b, float a) {
      colorConsumer.setRGBA_Buffer(buffer, r, g, b, a);
   }

   public static class ARGB {
      public static int pack(float r, float g, float b, float a) {
         int color = ColorUtil.floatToInt(a) << 24 | ColorUtil.floatToInt(r) << 16 | ColorUtil.floatToInt(g) << 8 | ColorUtil.floatToInt(b);
         return color;
      }

      public static float unpackR(int color) {
         return ColorUtil.unpackColor(color, 16);
      }

      public static float unpackG(int color) {
         return ColorUtil.unpackColor(color, 8);
      }

      public static float unpackB(int color) {
         return ColorUtil.unpackColor(color, 0);
      }

      public static float unpackA(int color) {
         return ColorUtil.unpackColor(color, 24);
      }

      public static int multiplyAlpha(int color, float m) {
         int newA = ColorUtil.floatToInt(unpackA(color) * m);
         return color & 16777215 | newA << 24;
      }

      public static int multiplyRGB(int color, float m) {
         int alpha = color >>> 24 & 255;
         int red = (int)((float)(color >>> 16 & 255) * m);
         int green = (int)((float)(color >>> 8 & 255) * m);
         int blue = (int)((float)(color & 255) * m);
         return alpha << 24 | red << 16 | green << 8 | blue;
      }

      public static int toRGBA(int color) {
         return color & -16711936 | color >> 16 & 255 | color << 16 & 16711680;
      }
   }

   public static class RGBA {
      public static int pack(float r, float g, float b, float a) {
         int color = ColorUtil.floatToInt(a) << 24 | ColorUtil.floatToInt(b) << 16 | ColorUtil.floatToInt(g) << 8 | ColorUtil.floatToInt(r);
         return color;
      }

      public static float unpackR(int color) {
         return ColorUtil.unpackColor(color, 24);
      }

      public static float unpackG(int color) {
         return ColorUtil.unpackColor(color, 16);
      }

      public static float unpackB(int color) {
         return ColorUtil.unpackColor(color, 8);
      }

      public static int fromArgb32(int i) {
         return i & -16711936 | (i & 16711680) >> 16 | (i & 255) << 16;
      }
   }

   interface ColorConsumer {
      void setRGBA_Buffer(MappedBuffer var1, float var2, float var3, float var4, float var5);

      void setRGBA_Buffer(FloatBuffer var1, float var2, float var3, float var4, float var5);

      void setRGBA_Buffer(ByteBuffer var1, float var2, float var3, float var4, float var5);

      default void putColor(MappedBuffer buffer, float r, float g, float b, float a) {
         buffer.putFloat(0, r);
         buffer.putFloat(4, g);
         buffer.putFloat(8, b);
         buffer.putFloat(12, a);
      }

      default void putColor(FloatBuffer buffer, float r, float g, float b, float a) {
         buffer.put(0, r);
         buffer.put(1, g);
         buffer.put(2, b);
         buffer.put(3, a);
      }

      default void putColor(ByteBuffer buffer, float r, float g, float b, float a) {
         buffer.putFloat(0, r);
         buffer.putFloat(4, g);
         buffer.putFloat(8, b);
         buffer.putFloat(12, a);
      }
   }

   public static class DefaultColorConsumer implements ColorConsumer {
      public void setRGBA_Buffer(MappedBuffer buffer, float r, float g, float b, float a) {
         this.putColor(buffer, r, g, b, a);
      }

      public void setRGBA_Buffer(FloatBuffer buffer, float r, float g, float b, float a) {
         this.putColor(buffer, r, g, b, a);
      }

      public void setRGBA_Buffer(ByteBuffer buffer, float r, float g, float b, float a) {
         this.putColor(buffer, r, g, b, a);
      }
   }

   public static class GammaColorConsumer implements ColorConsumer {
      public void setRGBA_Buffer(MappedBuffer buffer, float r, float g, float b, float a) {
         r = ColorUtil.gamma(r);
         g = ColorUtil.gamma(g);
         b = ColorUtil.gamma(b);
         this.putColor(buffer, r, g, b, a);
      }

      public void setRGBA_Buffer(FloatBuffer buffer, float r, float g, float b, float a) {
         r = ColorUtil.gamma(r);
         g = ColorUtil.gamma(g);
         b = ColorUtil.gamma(b);
         this.putColor(buffer, r, g, b, a);
      }

      public void setRGBA_Buffer(ByteBuffer buffer, float r, float g, float b, float a) {
         r = ColorUtil.gamma(r);
         g = ColorUtil.gamma(g);
         b = ColorUtil.gamma(b);
         this.putColor(buffer, r, g, b, a);
      }
   }
}
