#pragma once

#include "Block.h"

class TreeSeblingBlockType;

class TreeSeblingBlock : public Block
{
private:
    float seblingTicks;
    int seblingTicksMax;
    const BlockType* wood;
    const BlockType* leaves;

public:
    TreeSeblingBlock(int typeId,
        Framework::Vec3<int> pos,
        int dimensionId,
        const BlockType* wood,
        const BlockType* leaves);
    virtual bool onTick(
        TickQueue* zQueue, int numTicks, bool& blocked) override;
    virtual void onPostTick() override;
    virtual TickSourceType isTickSource() const override;
    virtual Framework::Text getTargetUIML();

    friend TreeSeblingBlockType;
};

class TreeSeblingBlockType : public BlockType
{
private:
    Framework::Text itemTypeName;
    int itemTypeId;
    bool transparent;
    bool passable;
    float speedModifier;
    bool interactable;
    Framework::Text woodTypeName;
    Framework::Text leavesTypeName;
    int woodTypeId;
    int leavesTypeId;

public:
    TreeSeblingBlockType();

protected:
    virtual void createSuperBlock(Block* zBlock, Item* zItem) const override;
    virtual void loadSuperBlock(Block* zBlock,
        Framework::StreamReader* zReader,
        int dimensionId) const override;
    virtual void saveSuperBlock(
        Block* zBlock, Framework::StreamWriter* zWriter) const override;
    virtual Item* createItem() const override;
    virtual Block* createBlock(
        Framework::Vec3<int> position, int dimensionId) const override;

public:
    virtual bool initialize(Game* zGame) override;
    virtual ItemType* createItemType() const override;

    void setItemTypeName(Framework::Text itemTypeName);
    Framework::Text getItemTypeName() const;
    void setWoodTypeName(Framework::Text woodTypeName);
    Framework::Text getWoodTypeName() const;
    void setLeavesTypeName(Framework::Text leavesTypeName);
    Framework::Text getLeavesTypeName() const;
    void setTransparent(bool transparent);
    bool isTransparent() const;
    void setPassable(bool passable);
    bool isPassable() const;
    void setSpeedModifier(float speedModifier);
    float getSpeedModifier() const;
    void setInteractable(bool interactable);
    bool isInteractable() const;
};

class TreeSeblingBlockTypeFactory
    : public BlockTypeFactoryBase<TreeSeblingBlockType>
{
public:
    TreeSeblingBlockTypeFactory();
    TreeSeblingBlockType* createValue(
        Framework::JSON::JSONObject* zJson) const override;
    TreeSeblingBlockType* fromJson(
        Framework::JSON::JSONObject* zJson) const override;
    Framework::JSON::JSONObject* toJsonObject(
        TreeSeblingBlockType* zObject) const override;
    JSONObjectValidationBuilder* addToValidator(
        JSONObjectValidationBuilder* builder) const override;
    const char* getTypeToken() const override;
};