/*
 *  Copyright 2025-2026 R3944Realms
 *
 *    Licensed under the Apache License, Version 2.0 (the "License");
 *    you may not use this file except in compliance with the License.
 *    You may obtain a copy of the License at
 *
 *        http://www.apache.org/licenses/LICENSE-2.0
 *
 *    Unless required by applicable law or agreed to in writing, software
 *    distributed under the License is distributed on an "AS IS" BASIS,
 *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *    See the License for the specific language governing permissions and
 *    limitations under the License.
 */

package top.r3944realms.eroticdungeongame.content.block.blockentity;

import net.minecraft.core.BlockPos;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.phys.AABB;
import org.jetbrains.annotations.NotNull;
import software.bernie.geckolib.animatable.GeoBlockEntity;
import software.bernie.geckolib.core.animatable.instance.AnimatableInstanceCache;
import software.bernie.geckolib.core.animation.AnimatableManager;
import software.bernie.geckolib.core.animation.AnimationController;
import software.bernie.geckolib.core.animation.RawAnimation;
import software.bernie.geckolib.util.GeckoLibUtil;
import top.r3944realms.eroticdungeongame.content.block.multiply.AbstractTwoPartSeatBlock;
import top.r3944realms.eroticdungeongame.content.block.part.SeatPart;
import top.r3944realms.eroticdungeongame.content.entity.SeatEntity;
import top.r3944realms.eroticdungeongame.core.register.EDGBlockEntities;
import top.r3944realms.eroticdungeongame.other.geckolib.AutoPlayingSoundKeyframeHandler;
import top.r3944realms.lib39.util.nbt.NBTReader;
import top.r3944realms.lib39.util.nbt.NBTWriter;

public class IronCageBlockEntity extends BaseSeatBlockEntity implements GeoBlockEntity {
    private final AnimatableInstanceCache cache = GeckoLibUtil.createInstanceCache(this);
    public static final RawAnimation UNLOCKED_ANIM = RawAnimation.begin().thenPlay("iron_cage.unlocked");
    public static final RawAnimation LOCKED_ANIM = RawAnimation.begin().thenPlay("iron_cage.locked");
    public static final RawAnimation UNLOCKING_ANIM = RawAnimation.begin().thenPlay("iron_cage.unlocking").thenPlayAndHold("iron_cage.unlocked");
    public static final RawAnimation LOCKING_ANIM = RawAnimation.begin().thenPlay("iron_cage.locking").thenPlayAndHold("iron_cage.locked");

    private volatile boolean isLocked = false;

    private volatile boolean shouldPlayUnlocking = false;
    private volatile boolean shouldPlayLocking = false;

    public IronCageBlockEntity(BlockPos blockPos, BlockState blockState) {
        super(EDGBlockEntities.IRON_CAGE_SEAT_BLOCK_ENTITY.get(), blockPos, blockState);
    }

    public static void serverTick(Level pLevel, BlockPos pPos, BlockState pState, IronCageBlockEntity pBlockEntity) {
        // 可以在这里添加服务端逻辑
    }

    public boolean isLocked() {
        return isLocked;
    }

    public synchronized void setLocked(boolean locked) {
        this.isLocked = locked;
    }

    public synchronized void unlock() {
        // 直接触发解锁动画
        shouldPlayUnlocking = true;
        shouldPlayLocking = false;
        isLocked = false; // 更新状态
    }

    public synchronized void lock() {
        // 直接触发锁定动画
        shouldPlayLocking = true;
        shouldPlayUnlocking = false;
        isLocked = true; // 更新状态
    }

    public void passengerRot(@NotNull Entity passenger, @NotNull SeatEntity seat) {
        //noop
    }

    public synchronized void toggleLock() {
        if (isLocked) {
            unlock();
        } else {
            lock();
        }
    }

    @Override
    public void registerControllers(AnimatableManager.@NotNull ControllerRegistrar controllerRegistrar) {
        controllerRegistrar
                .add(new AnimationController<>(this, "iron_seat", 0, state -> {
            // 优先播放过渡动画
            if (shouldPlayUnlocking) {
                shouldPlayUnlocking = false; // 清除标志
                return state.setAndContinue(UNLOCKING_ANIM);
            }

            if (shouldPlayLocking) {
                shouldPlayLocking = false; // 清除标志
                return state.setAndContinue(LOCKING_ANIM);
            }

            // 如果没有过渡动画要播放，根据当前动画决定
            if (state.isCurrentAnimationStage("iron_cage.unlocking")) {
                return state.setAndContinue(UNLOCKING_ANIM);
            }

            if (state.isCurrentAnimationStage("iron_cage.locking")) {
                return state.setAndContinue(LOCKING_ANIM);
            }

            // 默认根据 hasLockCode 状态播放
            return isLocked ?
                    state.setAndContinue(LOCKED_ANIM) :
                    state.setAndContinue(UNLOCKED_ANIM);
        })
                .setSoundKeyframeHandler(new AutoPlayingSoundKeyframeHandler<>()));//自动解析动画geo 声音帧
    }

    @Override
    public AnimatableInstanceCache getAnimatableInstanceCache() {
        return cache;
    }

    @Override
    public void saveAdditional(@NotNull CompoundTag compoundTag) {
        super.saveAdditional(compoundTag);
        NBTWriter.of(compoundTag)
                .booleanValue("hasLockCode", isLocked)
                .booleanValue("shouldPlayUnlocking", shouldPlayUnlocking)
                .booleanValue("shouldPlayLocking", shouldPlayLocking);
    }

    @Override
    public void load(@NotNull CompoundTag compoundTag) {
        super.load(compoundTag);
        NBTReader.of(compoundTag)
                .booleanValue("hasLockCode", this::setLocked)
                .booleanValue("shouldPlayUnlocking", this::setShouldPlayUnlocking)
                .booleanValue("shouldPlayLocking", this::setShouldPlayLocking);
    }

    @Override
    public AABB getRenderBoundingBox() {
        BlockPos pos = this.getBlockPos();
        BlockState state = this.getBlockState();

        if (state.hasProperty(AbstractTwoPartSeatBlock.PART)) {
            SeatPart part = state.getValue(AbstractTwoPartSeatBlock.PART);

            if (part == SeatPart.FOOT) {
                return new AABB(
                        pos.getX(), pos.getY(), pos.getZ(),
                        pos.getX() + 1, pos.getY() + 2, pos.getZ() + 1
                );
            } else if (part == SeatPart.HEAD) {
                return new AABB(
                        pos.getX(), pos.getY() - 1, pos.getZ(),
                        pos.getX() + 1, pos.getY() + 1, pos.getZ() + 1
                );
            }
        }

        return super.getRenderBoundingBox();
    }

    public boolean isShouldPlayUnlocking() {
        return shouldPlayUnlocking;
    }

    public void setShouldPlayUnlocking(boolean shouldPlayUnlocking) {
        this.shouldPlayUnlocking = shouldPlayUnlocking;
    }

    public boolean isShouldPlayLocking() {
        return shouldPlayLocking;
    }

    public void setShouldPlayLocking(boolean shouldPlayLocking) {
        this.shouldPlayLocking = shouldPlayLocking;
    }
}
