package ru.themixray.repeating_mod.event.events;

import net.minecraft.util.PlayerInput;
import ru.themixray.repeating_mod.Main;
import ru.themixray.repeating_mod.event.RecordEvent;

public class InputEvent extends RecordEvent {
    public Boolean forward;
    public Boolean backward;
    public Boolean left;
    public Boolean right;
    public Boolean jump;
    public Boolean sneak;
    public Boolean sprint;

    public float yaw;
    public float head_yaw;
    public float body_yaw;
    public float pitch;
    public float speed;
    public float movementForward;
    public float movementSideways;

    public static InputEvent current() {
        if (Main.client.player == null) return null;
        return new InputEvent(
            Main.client.player.input.playerInput.forward(),
            Main.client.player.input.playerInput.backward(),
            Main.client.player.input.playerInput.left(),
            Main.client.player.input.playerInput.right(),
            Main.client.player.input.playerInput.jump(),
            Main.client.player.input.playerInput.sneak(),
            Main.client.player.input.playerInput.sprint(),
            Main.client.player.getHeadYaw(),
            Main.client.player.getBodyYaw(),
            Main.client.player.getPitch(),
            Main.client.player.getYaw(),
            Main.client.player.getMovementSpeed(),
            Main.client.player.input.movementForward,
            Main.client.player.input.movementSideways
        );
    }

    public InputEvent(Boolean forward,
                      Boolean backward,
                      Boolean left,
                      Boolean right,
                      Boolean jump,
                      Boolean sneak,
                      Boolean sprint,
                      float head_yaw,
                      float body_yaw,
                      float head_pitch,
                      float yaw,
                      float speed,
                      float movementForward,
                      float movementSideways) {
        this.forward = forward;
        this.backward = backward;
        this.left = left;
        this.right = right;
        this.jump = jump;
        this.sneak = sneak;
        this.sprint = sprint;

        this.head_yaw = head_yaw;
        this.body_yaw = body_yaw;
        this.pitch = head_pitch;
        this.yaw = yaw;
        this.speed = speed;
        this.movementForward = movementForward;
        this.movementSideways = movementSideways;
    }

    /**
     * Returns differences of this InputEvent to the provided one, saving first booleans if differ and first floats always
     */
    public InputEvent differs(InputEvent event) {
        return new InputEvent(
            forward == event.forward ? null : forward,
            backward == event.backward ? null : backward,
            left == event.left ? null : left,
            right == event.right ? null : right,
            jump == event.jump ? null : jump,
            sneak == event.sneak ? null : sneak,
            sprint == event.sprint ? null : sprint,
            head_yaw,
            body_yaw,
            pitch,
            yaw,
            speed,
            movementForward,
            movementSideways
        );
    }

    public static InputEvent deserialize(String[] a) {
        return new InputEvent(
            (a[0].equals("n") ? null : a[0].equals("1")),
            (a[1].equals("n") ? null : a[1].equals("1")),
            (a[2].equals("n") ? null : a[2].equals("1")),
            (a[3].equals("n") ? null : a[3].equals("1")),
            (a[4].equals("n") ? null : a[4].equals("1")),
            (a[5].equals("n") ? null : a[5].equals("1")),
            (a[6].equals("n") ? null : a[6].equals("1")),
            Float.parseFloat(a[7]),
            Float.parseFloat(a[8]),
            Float.parseFloat(a[9]),
            Float.parseFloat(a[10]),
            Float.parseFloat(a[11]),
            Float.parseFloat(a[12]),
            Float.parseFloat(a[13])
        );
    }

    protected String[] serializeArgs() {
        return new String[] {
            ((forward == null) ? "n" : (forward ? "1" : "0")),
            ((backward == null) ? "n" : (backward ? "1" : "0")),
            ((left == null) ? "n" : (left ? "1" : "0")),
            ((right == null) ? "n" : (right ? "1" : "0")),
            ((jump == null) ? "n" : (jump ? "1" : "0")),
            ((sneak == null) ? "n" : (sneak ? "1" : "0")),
            ((sprint == null) ? "n" : (sprint ? "1" : "0")),
            String.valueOf(head_yaw),
            String.valueOf(body_yaw),
            String.valueOf(pitch),
            String.valueOf(yaw),
            String.valueOf(speed),
            String.valueOf(movementForward),
            String.valueOf(movementSideways)
        };
    }

    public boolean equals(InputEvent event) {
        return event.forward == forward &&
            event.backward == backward &&
            event.sprint == sprint &&
            event.jump == jump &&
            event.sneak == sneak &&
            event.left == left &&
            event.right == right &&
            event.speed == speed &&
            event.head_yaw == head_yaw &&
            event.body_yaw == body_yaw &&
            event.yaw == yaw &&
            event.pitch == pitch &&
            event.movementForward == movementForward &&
            event.movementSideways == movementSideways;
    }

    public void replay() {
        Main.input_replay = this;
    }

    public void inputCallback() {
        if (Main.client.player != null) {
            if (sprint != null && Main.client.player.isSprinting() != sprint)
                Main.client.player.setSprinting(sprint);
            if (Main.client.player.getYaw() != yaw)
                Main.client.player.setYaw(yaw);
            if (Main.client.player.getHeadYaw() != head_yaw)
                Main.client.player.setHeadYaw(head_yaw);
            if (Main.client.player.getBodyYaw() != body_yaw)
                Main.client.player.setBodyYaw(body_yaw);
            if (Main.client.player.getPitch() != pitch)
                Main.client.player.setPitch(pitch);
            if (Main.client.player.getMovementSpeed() != speed)
                Main.client.player.setMovementSpeed(speed);

            Main.client.player.input.movementSideways = movementSideways;
            Main.client.player.input.movementForward = movementForward;

            PlayerInput input = Main.client.player.input.playerInput;
            Main.client.player.input.playerInput = new PlayerInput(
                this.forward == null ? input.forward() : this.forward,
                this.backward == null ? input.backward() : this.backward,
                this.left == null ? input.left() : this.left,
                this.right == null ? input.right() : this.right,
                this.jump == null ? input.jump() : this.jump,
                this.sneak == null ? input.sneak() : this.sneak,
                this.sprint == null ? input.sprint() : this.sprint
            );
        }
    }
}
