package top.r3944realms.lib39.example.content.data;

import net.minecraft.network.FriendlyByteBuf;
import net.minecraft.resources.ResourceLocation;
import org.jetbrains.annotations.NotNull;
import top.r3944realms.lib39.core.sync.NBTEntitySyncData;

/**
 * The type Abstracted test sync data.
 */
@SuppressWarnings("unused")
public abstract class AbstractedTestSyncData extends NBTEntitySyncData {
    /**
     * The constant DEFAULT_TEST_STRING.
     */
    public final static String DEFAULT_TEST_STRING = "default_value";
    /**
     * The constant DEFAULT_TEST_INT.
     */
    public final static int DEFAULT_TEST_INT = 42;
    /**
     * The constant DEFAULT_TEST_BOOLEAN.
     */
    public final static boolean DEFAULT_TEST_BOOLEAN = true;
    /**
     * The constant DEFAULT_TEST_DOUBLE.
     */
    public final static double DEFAULT_TEST_DOUBLE = 3.14159;
    /**
     * The constant DEFAULT_TEST_DATA.
     */
    public final static TestData DEFAULT_TEST_DATA = new TestData("default", 100, false);

    /**
     * Instantiates a new Nbt sync data.
     *
     * @param id the id
     */
    protected AbstractedTestSyncData(ResourceLocation id) {
        super(id);
    }

    /**
     * Gets test string.
     *
     * @return the test string
     */
    public abstract String getTestString();

    /**
     * Sets test string.
     *
     * @param value the value
     */
    public abstract void setTestString(String value);

    /**
     * Gets test int.
     *
     * @return the test int
     */
    public abstract int getTestInt();

    /**
     * Sets test int.
     *
     * @param value the value
     */
    public abstract void setTestInt(int value);

    /**
     * Is test boolean boolean.
     *
     * @return the boolean
     */
    public abstract boolean isTestBoolean();

    /**
     * Sets test boolean.
     *
     * @param value the value
     */
    public abstract void setTestBoolean(boolean value);

    /**
     * Gets test double.
     *
     * @return the test double
     */
    public abstract double getTestDouble();

    /**
     * Sets test double.
     *
     * @param value the value
     */
    public abstract void setTestDouble(double value);

    /**
     * Gets counter.
     *
     * @return the counter
     */
    public abstract int getCounter();

    /**
     * Increment counter.
     */
    public abstract void incrementCounter();

    /**
     * Clear counter.
     */
    public abstract void clearCounter();

    /**
     * Gets last sync time.
     *
     * @return the last sync time
     */
    public abstract long getLastSyncTime();

    /**
     * Update sync time.
     */
    public abstract void updateSyncTime();

    /**
     * Clear sync time.
     */
    public abstract void clearSyncTime();

    /**
     * Gets custom data.
     *
     * @return the custom data
     */
    public abstract TestData getCustomData();

    /**
     * Sets custom data.
     *
     * @param data the data
     */
    public abstract void setCustomData(TestData data);

    /**
     * Validate data boolean.
     *
     * @return the boolean
     */
    public abstract boolean validateData();

    /**
     * Reset to defaults.
     */
    public void resetToDefaults() {
        setTestString(DEFAULT_TEST_STRING);
        setTestInt(DEFAULT_TEST_INT);
        setTestBoolean(DEFAULT_TEST_BOOLEAN);
        setTestDouble(DEFAULT_TEST_DOUBLE);
        setCustomData(DEFAULT_TEST_DATA);
        clearCounter();
        clearSyncTime();
        markDirty();
    }

    /**
     * Generate random data.
     */
    public void generateRandomData() {
        setTestString("random_" + System.currentTimeMillis());
        setTestInt((int) (Math.random() * 1000));
        setTestBoolean(Math.random() > 0.5);
        setTestDouble(Math.random() * 100.0);
        setCustomData(new TestData(
                "custom_" + getCounter(),
                (int) (Math.random() * 500),
                Math.random() > 0.5
        ));
        updateSyncTime();
        incrementCounter();
        markDirty();
    }

    /**
     * To bytes.
     *
     * @param buf the buf
     */
    public abstract void toBytes(FriendlyByteBuf buf);

    /**
     * From bytes.
     *
     * @param buf the buf
     */
    public abstract void fromBytes(@NotNull FriendlyByteBuf buf);

    /**
     * 测试数据对象
     */
    public static class TestData {
        private String name;
        private int value;
        private boolean flag;

        /**
         * Instantiates a new Test data.
         */
        public TestData() {}

        /**
         * Instantiates a new Test data.
         *
         * @param name  the name
         * @param value the value
         * @param flag  the flag
         */
        public TestData(String name, int value, boolean flag) {
            this.name = name;
            this.value = value;
            this.flag = flag;
        }

        /**
         * Gets name.
         *
         * @return the name
         */
        public String getName() { return name; }

        /**
         * Sets name.
         *
         * @param name the name
         */
        public void setName(String name) { this.name = name; }

        /**
         * Gets value.
         *
         * @return the value
         */
        public int getValue() { return value; }

        /**
         * Sets value.
         *
         * @param value the value
         */
        public void setValue(int value) { this.value = value; }

        /**
         * Is flag boolean.
         *
         * @return the boolean
         */
        public boolean isFlag() { return flag; }

        /**
         * Sets flag.
         *
         * @param flag the flag
         */
        public void setFlag(boolean flag) { this.flag = flag; }

        @Override
        public boolean equals(Object obj) {
            if (this == obj) return true;
            if (!(obj instanceof TestData other)) return false;
            return value == other.value && flag == other.flag &&
                    java.util.Objects.equals(name, other.name);
        }

        @Override
        public int hashCode() {
            return java.util.Objects.hash(name, value, flag);
        }
        }
}
