package classes

import gregtech.api.metatileentity.MetaTileEntity
import gregtech.common.metatileentities.MetaTileEntities
import gregtech.api.metatileentity.interfaces.IGregTechTileEntity
import gregtech.api.metatileentity.multiblock.IMultiblockPart
import gregtech.api.metatileentity.multiblock.RecipeMapMultiblockController
import gregtech.api.pattern.BlockPattern
import gregtech.api.pattern.FactoryBlockPattern
import gregtech.api.recipes.RecipeMap
import gregtech.api.recipes.RecipeMaps
import gregtech.api.recipes.builders.SimpleRecipeBuilder
import gregtech.client.renderer.ICubeRenderer

import gregtech.client.renderer.texture.Textures
import gregicality.multiblocks.api.render.GCYMTextures
import gregtech.client.utils.TooltipHelper
import gregtech.common.blocks.BlockMetalCasing
import gregtech.common.blocks.BlockFusionCasing
import gregtech.common.blocks.BlockGlassCasing
import gregtech.common.blocks.BlockCleanroomCasing
import gregtech.common.blocks.BlockMachineCasing
import gregtech.common.blocks.BlockBoilerCasing
import gregtech.common.blocks.BlockComputerCasing
import gregtech.common.blocks.BlockWireCoil
import gregtech.api.unification.material.Materials
import gregtech.common.blocks.MetaBlocks
import gregtech.api.pattern.TraceabilityPredicate
import gregtech.api.metatileentity.multiblock.MultiblockAbility
import gregicality.multiblocks.common.block.GCYMMetaBlocks
import gregicality.multiblocks.common.block.blocks.BlockLargeMultiblockCasing

import gregtech.api.recipes.recipeproperties.TemperatureProperty
import gregtech.api.capability.IHeatingCoil
import gregtech.api.capability.IMufflerHatch
import gregtech.api.metatileentity.interfaces.IGregTechTileEntity
import gregtech.api.metatileentity.multiblock.IMultiblockPart
import gregtech.api.metatileentity.multiblock.MultiblockAbility
import gregtech.api.metatileentity.multiblock.MultiblockDisplayText
import gregtech.api.metatileentity.multiblock.RecipeMapMultiblockController

import net.minecraft.init.Blocks
import net.minecraft.util.ResourceLocation

import net.minecraftforge.fml.relauncher.Side
import net.minecraftforge.fml.relauncher.SideOnly

import gregtech.api.GTValues
import gregtech.api.block.IHeatingCoilBlockStats
import gregtech.api.capability.IHeatingCoil
import gregtech.api.capability.IMufflerHatch
import gregtech.api.metatileentity.ITieredMetaTileEntity
import gregtech.api.metatileentity.MetaTileEntity
import gregtech.api.metatileentity.interfaces.IGregTechTileEntity
import gregtech.api.metatileentity.multiblock.IMultiblockPart
import gregtech.api.metatileentity.multiblock.MultiblockAbility
import gregtech.api.metatileentity.multiblock.MultiblockDisplayText
import gregtech.api.metatileentity.multiblock.RecipeMapMultiblockController
import gregtech.api.pattern.BlockPattern
import gregtech.api.pattern.FactoryBlockPattern
import gregtech.api.pattern.PatternMatchContext
import gregtech.api.pattern.TraceabilityPredicate
import gregtech.api.recipes.Recipe
import gregtech.api.recipes.RecipeMaps
import gregtech.api.recipes.recipeproperties.IRecipePropertyStorage
import gregtech.api.recipes.recipeproperties.TemperatureProperty
import gregtech.api.unification.material.Materials
import gregtech.api.util.GTUtility
import gregtech.api.util.TextComponentUtil
import gregtech.api.util.TextFormattingUtil
import gregtech.client.renderer.ICubeRenderer
import gregtech.client.renderer.texture.Textures
import gregtech.client.renderer.texture.cube.OrientedOverlayRenderer
import gregtech.common.blocks.*
import gregicality.multiblocks.api.capability.impl.GCYMMultiblockRecipeLogic
import gregicality.multiblocks.api.metatileentity.GCYMMultiblockAbility
import gregicality.multiblocks.api.metatileentity.GCYMRecipeMapMultiblockController
import gregicality.multiblocks.api.render.GCYMTextures
import gregicality.multiblocks.common.GCYMConfigHolder
import gregicality.multiblocks.common.block.GCYMMetaBlocks
import gregicality.multiblocks.common.block.blocks.BlockLargeMultiblockCasing
import gregicality.multiblocks.common.block.blocks.BlockUniqueCasing
import net.minecraft.block.state.IBlockState
import net.minecraft.client.resources.I18n
import net.minecraft.item.ItemStack
import net.minecraft.util.ResourceLocation
import net.minecraft.util.text.ITextComponent
import net.minecraft.util.text.TextComponentTranslation
import net.minecraft.util.text.TextFormatting
import net.minecraft.world.World
import org.jetbrains.annotations.NotNull
import org.jetbrains.annotations.Nullable

public class MetaTileEntityVolcanus extends GCYMRecipeMapMultiblockController implements IHeatingCoil {

    public MetaTileEntityVolcanus(ResourceLocation metaTileEntityId) {
        super(metaTileEntityId, RecipeMaps.BLAST_RECIPES)
        this.recipeMapWorkable = new MegaBlastFurnaceRecipeLogic(this)
    }

    @Override
    public MetaTileEntity createMetaTileEntity(IGregTechTileEntity tileEntity) {
        return new MetaTileEntityVolcanus(metaTileEntityId)
    }

    @Override
    protected BlockPattern createStructurePattern() {
        return FactoryBlockPattern.start()
                .aisle("CCC", "OOO", "OOO", "CCC")
                .aisle("CCC", "O#O", "O#O", "CMC")
                .aisle("CSC", "OOO", "OOO", "CCC")
                .where('S' as char, selfPredicate())
                .where('C' as char, states(MetaBlocks.COMPUTER_CASING.getState(BlockComputerCasing.CasingType.ADVANCED_COMPUTER_CASING))
                    .setMinGlobalLimited(6)
                    .or(autoAbilities()))
                .where('O' as char, heatingCoils())
                .where('M' as char, abilities(MultiblockAbility.MUFFLER_HATCH))
                .where('#' as char, air())
                .build()
    }

    @Override
    protected void addDisplayText(List<ITextComponent> textList) {
        MultiblockDisplayText.builder(textList, isStructureFormed())
                .setWorkingStatus(recipeMapWorkable.isWorkingEnabled(), recipeMapWorkable.isActive())
                .addEnergyUsageLine(getEnergyContainer())
                .addEnergyTierLine(GTUtility.getTierByVoltage(recipeMapWorkable.getMaxVoltage()))
                .addCustom(tl -> {
                    // Tiered Hatch Line
                    if (isStructureFormed()) {
                        List<ITieredMetaTileEntity> list = getAbilities(GCYMMultiblockAbility.TIERED_HATCH)
                        if (GCYMConfigHolder.globalMultiblocks.enableTieredCasings && !list.isEmpty()) {
                            long maxVoltage = Math.min(GTValues.V[list.get(0).getTier()],
                                    Math.max(energyContainer.getInputVoltage(), energyContainer.getOutputVoltage()))
                            String voltageName = GTValues.VNF[list.get(0).getTier()]
                            tl.add(new TextComponentTranslation("gcym.multiblock.tiered_hatch.tooltip", maxVoltage,
                                    voltageName))
                        }
                    }
                })
                .addCustom(tl -> {
                    // Coil heat capacity line
                    if (isStructureFormed()) {
                        ITextComponent heatString = TextComponentUtil.stringWithColor(
                                TextFormatting.RED,
                                TextFormattingUtil.formatNumbers(blastFurnaceTemperature) + "K")

                        tl.add(TextComponentUtil.translationWithColor(
                                TextFormatting.GRAY,
                                "gregtech.multiblock.blast_furnace.max_temperature",
                                heatString))
                    }
                })
                .addParallelsLine(recipeMapWorkable.getParallelLimit())
                .addWorkingStatusLine()
                .addProgressLine(recipeMapWorkable.getProgressPercent())

    protected void formStructure(PatternMatchContext context) {
        super.formStructure(context)
        Object type = context.get("CoilType")
        if (type instanceof IHeatingCoilBlockStats stats) {
            this.blastFurnaceTemperature = stats.getCoilTemperature()
        } else {
            this.blastFurnaceTemperature = BlockWireCoil.CoilType.CUPRONICKEL.getCoilTemperature()
        }

        this.blastFurnaceTemperature += 100 *
                Math.max(0, GTUtility.getTierByVoltage(getEnergyContainer().getInputVoltage()) - GTValues.MV)
    }

    @Override
    public void addInformation(ItemStack stack, @Nullable World player, List<String> tooltip, boolean advanced) {
        super.addInformation(stack, player, tooltip, advanced)
        tooltip.add(I18n.format("gregtech.machine.electric_blast_furnace.tooltip.3"))
        tooltip.add(TooltipHelper.RAINBOW_SLOW + I18n.format("gregtech.machine.perfect_oc"))
    }

    @Override
    public void invalidateStructure() {
        super.invalidateStructure()
        this.blastFurnaceTemperature = 0
    }
    
    @Override
    public boolean hasMufflerMechanics() {
        return true;
    }

    @Override
    public boolean checkRecipe(@NotNull Recipe recipe, boolean consumeIfSuccess) {
        return this.blastFurnaceTemperature >= recipe.getProperty(TemperatureProperty.getInstance(), 0)
    }

    @SuppressWarnings("InnerClassMayBeStatic")
    private class MegaBlastFurnaceRecipeLogic extends GCYMMultiblockRecipeLogic {

        public MegaBlastFurnaceRecipeLogic(RecipeMapMultiblockController metaTileEntity) {
            super(metaTileEntity)
        }

    @Override
    @SideOnly(Side.CLIENT)
    public ICubeRenderer getBaseTexture(IMultiblockPart sourcePart) {
        return Textures.ADVANCED_COMPUTER_CASING
    }

    public boolean hasMaintenanceMechanics() {
        return true;
    }
}