package mekanism.client.render.obj;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import javax.vecmath.Matrix4f;
import mekanism.api.MekanismConfig.client;
import mekanism.client.render.ctm.CTMModelFactory;
import mekanism.common.multipart.ColorProperty;
import mekanism.common.multipart.ConnectionProperty;
import mekanism.common.multipart.PartSidedPipe;
import mekanism.common.multipart.PartSidedPipe.ConnectionType;
import net.minecraft.block.state.IBlockState;
import net.minecraft.client.renderer.block.model.BakedQuad;
import net.minecraft.client.renderer.block.model.IBakedModel;
import net.minecraft.client.renderer.block.model.ItemCameraTransforms;
import net.minecraft.client.renderer.block.model.ItemCameraTransforms.TransformType;
import net.minecraft.client.renderer.block.model.ItemOverrideList;
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
import net.minecraft.client.renderer.texture.TextureMap;
import net.minecraft.client.renderer.vertex.VertexFormat;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.item.ItemStack;
import net.minecraft.util.BlockRenderLayer;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.EnumFacing.Axis;
import net.minecraft.util.ResourceLocation;
import net.minecraft.world.World;
import net.minecraftforge.client.MinecraftForgeClient;
import net.minecraftforge.client.model.IPerspectiveAwareModel;
import net.minecraftforge.client.model.obj.OBJModel;
import net.minecraftforge.client.model.obj.OBJModel.Face;
import net.minecraftforge.client.model.obj.OBJModel.Group;
import net.minecraftforge.client.model.obj.OBJModel.OBJProperty;
import net.minecraftforge.client.model.obj.OBJModel.OBJState;
import net.minecraftforge.common.model.IModelState;
import net.minecraftforge.common.property.IExtendedBlockState;
import org.apache.commons.lang3.tuple.Pair;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Lists;
public class TransmitterModel extends OBJBakedModelBase
{
private static Set<TransmitterModel> modelInstances = new HashSet<TransmitterModel>();
private Map<Integer, List<BakedQuad>> modelCache = new HashMap<Integer, List<BakedQuad>>();
private TransmitterModel itemCache;
private IBlockState tempState;
private ItemStack tempStack;
private static TextureAtlasSprite[] transporter_center = new TextureAtlasSprite[2];
private static TextureAtlasSprite[] transporter_center_color = new TextureAtlasSprite[2];
private static TextureAtlasSprite[] transporter_side = new TextureAtlasSprite[2];
private static TextureAtlasSprite[] transporter_side_color = new TextureAtlasSprite[2];
private TransmitterOverride override = new TransmitterOverride();
public TransmitterModel(IBakedModel base, OBJModel model, IModelState state, VertexFormat format, ImmutableMap<String, TextureAtlasSprite> textures, HashMap<TransformType, Matrix4f> transform)
{
super(base, model, state, format, textures, transform);
modelInstances.add(this);
}
private class TransmitterOverride extends ItemOverrideList
{
public TransmitterOverride()
{
super(Lists.newArrayList());
}
@Override
public IBakedModel handleItemState(IBakedModel originalModel, ItemStack stack, World world, EntityLivingBase entity)
{
if(itemCache == null)
{
List<String> visible = new ArrayList<String>();
for(EnumFacing side : EnumFacing.values())
{
visible.add(side.getName() + (side.getAxis() == Axis.Y ? "NORMAL" : "NONE"));
}
itemCache = new TransmitterModel(baseModel, getModel(), new OBJState(visible, true), vertexFormat, textureMap, transformationMap);
itemCache.tempStack = stack;
}
return itemCache;
}
}
@Override
public ItemOverrideList getOverrides()
{
return override;
}
@Override
public List<BakedQuad> getQuads(IBlockState state, EnumFacing side, long rand)
{
if(side != null)
{
return ImmutableList.of();
}
if(state != null && tempState == null)
{
IExtendedBlockState extended = (IExtendedBlockState)state;
BlockRenderLayer layer = MinecraftForgeClient.getRenderLayer();
ColorProperty colorProp = extended.getValue(ColorProperty.INSTANCE);
int color = -1;
if(colorProp != null && colorProp.color != null)
{
color = extended.getValue(ColorProperty.INSTANCE).color.ordinal();
}
OBJState obj = extended.getValue(OBJProperty.INSTANCE);
if(layer != BlockRenderLayer.TRANSLUCENT)
{
color = -1;
}
int hash = Objects.hash(layer.ordinal(), color, ConnectionProperty.INSTANCE.valueToString(extended.getValue(ConnectionProperty.INSTANCE)));
if(obj.getVisibilityMap().containsKey(Group.ALL) || obj.getVisibilityMap().containsKey(Group.ALL_EXCEPT))
{
updateStateVisibilityMap(obj);
}
if(!modelCache.containsKey(hash))
{
TransmitterModel model = new TransmitterModel(baseModel, getModel(), obj, vertexFormat, textureMap, transformationMap);
model.tempState = state;
modelCache.put(hash, model.getQuads(state, side, rand));
}
return modelCache.get(hash);
}
return super.getQuads(state, side, rand);
}
@Override
public float[] getOverrideColor(Face f, String groupName)
{
if(tempState != null)
{
ColorProperty prop = ((IExtendedBlockState)tempState).getValue(ColorProperty.INSTANCE);
if(MinecraftForgeClient.getRenderLayer() == BlockRenderLayer.TRANSLUCENT && prop != null && prop.color != null)
{
return new float[] {prop.color.getColor(0), prop.color.getColor(1), prop.color.getColor(2), 1};
}
}
return null;
}
@Override
public TextureAtlasSprite getOverrideTexture(Face f, String groupName)
{
if(tempState != null)
{
EnumFacing side = EnumFacing.getFacingFromVector(f.getNormal().x, f.getNormal().y, f.getNormal().z);
ColorProperty prop = ((IExtendedBlockState)tempState).getValue(ColorProperty.INSTANCE);
ConnectionProperty connection = ((IExtendedBlockState)tempState).getValue(ConnectionProperty.INSTANCE);
boolean sideIconOverride = getIconStatus(side, connection) > 0;
if(MinecraftForgeClient.getRenderLayer() == BlockRenderLayer.TRANSLUCENT)
{
int opaqueVal = client.opaqueTransmitters ? 1 : 0;
if(prop != null && prop.color != null)
{
return (!sideIconOverride && f.getMaterialName().contains("Center")) ? transporter_center_color[opaqueVal] : transporter_side_color[opaqueVal];
}
else {
return (!sideIconOverride && f.getMaterialName().contains("Center")) ? transporter_center[opaqueVal] : transporter_side[opaqueVal];
}
}
else {
if(groupName.endsWith("NONE") && sideIconOverride)
{
for(String s : getModel().getMatLib().getMaterialNames())
{
if(s.contains("Texture.Name"))
{
continue;
}
if(!s.contains("Center") && !s.contains("Centre") && (client.opaqueTransmitters ? s.contains("Opaque") : !s.contains("Opaque")))
{
return textureMap.get(s);
}
}
}
else {
if(client.opaqueTransmitters)
{
return textureMap.get(f.getMaterialName() + "_Opaque");
}
}
}
}
return null;
}
@Override
public boolean shouldRotate(Face f, String groupName)
{
if(tempState != null)
{
EnumFacing side = EnumFacing.getFacingFromVector(f.getNormal().x, f.getNormal().y, f.getNormal().z);
ConnectionProperty connection = ((IExtendedBlockState)tempState).getValue(ConnectionProperty.INSTANCE);
if(groupName.endsWith("NONE") && getIconStatus(side, connection) == 2)
{
return true;
}
}
return false;
}
public byte getIconStatus(EnumFacing side, ConnectionProperty connection)
{
ConnectionType type = PartSidedPipe.getConnectionType(side, connection.connectionByte, connection.transmitterConnections, connection.connectionTypes);
if(type == ConnectionType.NONE)
{
if(client.oldTransmitterRender || connection.renderCenter)
{
return (byte)0;
}
else if(connection.connectionByte == 3 && side != EnumFacing.DOWN && side != EnumFacing.UP)
{
return (byte)1;
}
else if(connection.connectionByte == 12 && (side == EnumFacing.DOWN || side == EnumFacing.UP))
{
return (byte)1;
}
else if(connection.connectionByte == 12 && (side == EnumFacing.EAST || side == EnumFacing.WEST))
{
return (byte)2;
}
else if(connection.connectionByte == 48 && side != EnumFacing.EAST && side != EnumFacing.WEST)
{
return (byte)2;
}
}
return (byte)0;
}
@Override
public Pair<? extends IPerspectiveAwareModel, Matrix4f> handlePerspective(ItemCameraTransforms.TransformType cameraTransformType)
{
return Pair.of(this, CTMModelFactory.transforms.get(cameraTransformType).getMatrix());
}
public static void registerIcons(TextureMap map)
{
transporter_center[0] = map.registerSprite(new ResourceLocation("mekanism:blocks/models/multipart/LogisticalTransporterGlass"));
transporter_center_color[0] = map.registerSprite(new ResourceLocation("mekanism:blocks/models/multipart/LogisticalTransporterGlassColored"));
transporter_side[0] = map.registerSprite(new ResourceLocation("mekanism:blocks/models/multipart/LogisticalTransporterVerticalGlass"));
transporter_side_color[0] = map.registerSprite(new ResourceLocation("mekanism:blocks/models/multipart/LogisticalTransporterVerticalGlassColored"));
transporter_center[1] = map.registerSprite(new ResourceLocation("mekanism:blocks/models/multipart/opaque/LogisticalTransporterGlass"));
transporter_center_color[1] = map.registerSprite(new ResourceLocation("mekanism:blocks/models/multipart/opaque/LogisticalTransporterGlassColored"));
transporter_side[1] = map.registerSprite(new ResourceLocation("mekanism:blocks/models/multipart/opaque/LogisticalTransporterVerticalGlass"));
transporter_side_color[1] = map.registerSprite(new ResourceLocation("mekanism:blocks/models/multipart/opaque/LogisticalTransporterVerticalGlassColored"));
}
public static void clearCache()
{
for(TransmitterModel model : modelInstances)
{
model.modelCache.clear();
model.itemCache = null;
}
}
}