import * as mc from "@minecraft/server"
import { cropBlocks, cropsFarmland } from '../crops/sgs_farm_cropconfig';
import { itemManager, randomWholeNum } from "../sgs_farm_lib";

const TRACTORS = new Map();
const TICK_INTERVAL = 5;
const SOUND_TILL_LAND = "dig.gravel";
const SOUND_PLACE_CROP = "place.azalea_leaves";
const SOUND_HARVEST_CROP = "break.azalea";
const SOUND_OPTIONS = { pitch: 1.0, volume: 5.0, };

runTractors();

function runTractors() {
    mc.system.afterEvents.scriptEventReceive.subscribe((eventData) => {
        const { id, sourceEntity, message } = eventData;
        if (sourceEntity == null) return;

        if (id == "sgs_farm:start_ride") {
            const player = sourceEntity?.getComponent("minecraft:rideable").getRiders()[0];
            TRACTORS.set(sourceEntity, new Tractor(player, sourceEntity))
        };

        if (id == "sgs_farm:stop_ride") {
            TRACTORS.delete(sourceEntity);
        };

        if (id == "sgs_farm:refresh_tool") {
            if (!sourceEntity?.hasComponent(('minecraft:inventory'))) return;    //untamed horse may not have inventory yet

            if (sourceEntity.typeId == "sgs_farm:shire_horse") {
                const inventory = sourceEntity?.getComponent('minecraft:inventory').container;
                const item = inventory.getItem(0);  //1 is the tool slot on horse

                if (item == undefined) {
                    sourceEntity.triggerEvent("evt:variant_none");
                    return;
                }
                if (item.typeId == "sgs_farm:cart_harvest") sourceEntity.triggerEvent("evt:variant_harvest");
                if (item.typeId == "sgs_farm:cart_seed") sourceEntity.triggerEvent("evt:variant_seed");
                if (item.typeId == "sgs_farm:cart_plough") sourceEntity.triggerEvent("evt:variant_plough");
                if (item.typeId == "sgs_farm:cart_cargo") sourceEntity.triggerEvent("evt:variant_cargo");
                return;
            }

            if (sourceEntity.typeId == "sgs_farm:tractor") {
                const inventory = sourceEntity?.getComponent('minecraft:inventory').container;
                const item = inventory.getItem(0);

                if (item == undefined) {
                    sourceEntity.triggerEvent("evt:variant_none");
                    return;
                }
                if (item.typeId == "sgs_farm:mach_harvest") sourceEntity.triggerEvent("evt:variant_harvest");
                if (item.typeId == "sgs_farm:mach_seed") sourceEntity.triggerEvent("evt:variant_seed");
                if (item.typeId == "sgs_farm:mach_plough") sourceEntity.triggerEvent("evt:variant_plough");
                return;
            }
        };
    })

    mc.system.runInterval(() => {
        for (let tractor of TRACTORS.values()) {
            tractor.tick();
        }
    }, TICK_INTERVAL);
}

function rotateVector2D(vec, angle) {
    angle = angle * (Math.PI / 180);
    return {
        x: vec.x * Math.cos(angle) - vec.z * Math.sin(angle),
        y: vec.y,
        z: vec.x * Math.sin(angle) + vec.z * Math.cos(angle)
    };
}

export default class Tractor {

    tractor;
    player;

    tool_width = 5;
    tool_offset = -3.5;

    constructor(player, tractor) {
        this.player = player;
        this.tractor = tractor;
    };

    cameratick() {
        this.setPlayerCamera();
    }

    tick() {
        //if(this.player.isJumping) particleGround(this.tractor, this.tool_offset);
        if (this.player.isJumping) {
            this.tractor.setProperty("sgs_farm:tool_active", true);
            if (this.tractor.getProperty("sgs_farm:harvest")) tractorHarvest(this.tractor, this.tool_offset);
            if (this.tractor.getProperty("sgs_farm:seed")) tractorSeed(this.tractor, this.tool_offset);
            if (this.tractor.getProperty("sgs_farm:plough")) tractorPlough(this.tractor, this.tool_offset);
        }
        else {
            this.tractor.setProperty("sgs_farm:tool_active", false);
        }
    };

    setPlayerCamera() {
        const playerViewDirection = this.player.getViewDirection();
        const z_direction_shift = { x: playerViewDirection.x * -10, y: playerViewDirection.y * -5, z: playerViewDirection.z * -10, };
        const camera_location = { x: this.player.location.x + z_direction_shift.x, y: this.player.location.y + 5 + z_direction_shift.y, z: this.player.location.z + z_direction_shift.z };
        this.player.camera.setCamera("minecraft:free", {
            location: camera_location, facingEntity: { facingEntity: this.tractor }, rotation: this.player.getRotation(),
            easeOptions: { easeTime: 1, easeType: 'Spring' }
        })
    }
}

function tractorSeed(entity, tool_offset) {

    entity.addEffect('slowness', 10, { amplifier: 4, showParticles: false });

    let location = entity.location;
    let vector_forward = entity.getViewDirection();
    let vector_left = rotateVector2D(vector_forward, 90);
    let dimension = entity.dimension.id;
    const origin = { x: location.x + (vector_forward.x * tool_offset), y: location.y + 0.2, z: location.z + (vector_forward.z * tool_offset) };

    const tool_locations = [
        { x: origin.x, y: origin.y, z: origin.z },
        { x: origin.x + (vector_left.x * 1), y: origin.y, z: origin.z + (vector_left.z * 1) },
        { x: origin.x + (vector_left.x * 2), y: origin.y, z: origin.z + (vector_left.z * 2) },
        { x: origin.x - (vector_left.x * 1), y: origin.y, z: origin.z - (vector_left.z * 1) },
        { x: origin.x - (vector_left.x * 2), y: origin.y, z: origin.z - (vector_left.z * 2) }
    ];
    const inventory = entity.getComponent('minecraft:inventory').container;

    tool_locations.forEach(location => {
        for (let slot = 0; slot < 16; slot++) {

            const item = inventory.getItem(slot);
            const data = cropsFarmland().find((f) => f.seedID == item?.typeId);
            if (data != undefined) {
                const block = mc.world.getDimension(dimension).getBlock(location);
                const below = block.below(1);

                if (block.isAir && below.typeId == "minecraft:farmland") {
                    block.setPermutation(mc.BlockPermutation.resolve(data.blockID));
                    mc.world.playSound(SOUND_PLACE_CROP, location, SOUND_OPTIONS);
                    mc.world.getDimension(dimension).spawnParticle("minecraft:crop_growth_emitter", location);
                    inventory.setItem(slot, itemManager.reduceAmount(item, 1));
                }

            }
        }
    });
}

function tractorHarvest(entity, tool_offset) {

    entity.addEffect('slowness', 10, { amplifier: 4, showParticles: false });

    let location = entity.location;
    let vector_forward = entity.getViewDirection();
    let vector_left = rotateVector2D(vector_forward, 90);
    let dimension = entity.dimension.id;
    const origin = { x: location.x + (vector_forward.x * tool_offset), y: location.y + 0.2, z: location.z + (vector_forward.z * tool_offset) };

    const tool_locations = [
        { x: origin.x, y: origin.y, z: origin.z },
        { x: origin.x + (vector_left.x * 1), y: origin.y, z: origin.z + (vector_left.z * 1) },
        { x: origin.x + (vector_left.x * 2), y: origin.y, z: origin.z + (vector_left.z * 2) },
        { x: origin.x - (vector_left.x * 1), y: origin.y, z: origin.z - (vector_left.z * 1) },
        { x: origin.x - (vector_left.x * 2), y: origin.y, z: origin.z - (vector_left.z * 2) }
    ];

    const inventory = entity.getComponent('minecraft:inventory').container;

    tool_locations.forEach(location => {
        const block = mc.world.getDimension(dimension).getBlock(location);

        const data = cropsFarmland().find((f) => f.blockID == block.typeId);
        if (data != undefined) {
            const stage = block.permutation.getState(data.stateID);
            
            
            if (stage >= data.maxStage) {
                try {
                    inventory.addItem(new mc.ItemStack(data.cropID, randomWholeNum(1,2)));
                    if(data.type == "vanilla") inventory.addItem(new mc.ItemStack(data.seedID, 1)); //vanilla crops harvest one additional seed item
                } catch (error) {
                    mc.world.sendMessage(error);
                }

                block.setPermutation(mc.BlockPermutation.resolve("minecraft:air"));
                mc.world.playSound(SOUND_HARVEST_CROP, location, SOUND_OPTIONS);
                mc.world.getDimension(dimension).spawnParticle("sgs_farm:harvest_crop", location);
            }
        }
    });
}

function tractorPlough(entity, tool_offset) {

    entity.addEffect('slowness', 10, { amplifier: 4, showParticles: false });

    let location = entity.location;
    let vector_forward = entity.getViewDirection();
    let vector_left = rotateVector2D(vector_forward, 90);
    let dimension = entity.dimension.id;

    const origin = { x: location.x + (vector_forward.x * tool_offset), y: location.y, z: location.z + (vector_forward.z * tool_offset) };

    const tool_locations = [
        { x: origin.x, y: origin.y, z: origin.z },
        { x: origin.x + (vector_left.x * 1), y: origin.y, z: origin.z + (vector_left.z * 1) },
        { x: origin.x + (vector_left.x * 2), y: origin.y, z: origin.z + (vector_left.z * 2) },
        { x: origin.x - (vector_left.x * 1), y: origin.y, z: origin.z - (vector_left.z * 1) },
        { x: origin.x - (vector_left.x * 2), y: origin.y, z: origin.z - (vector_left.z * 2) }
    ];

    tool_locations.forEach(location => {

        const block = mc.world.getDimension(dimension).getBlock(location);
        const below = block.below(1);

        if (below.hasTag("grass")) {
            below.setPermutation(mc.BlockPermutation.resolve("minecraft:farmland", { 'moisturized_amount': 1 }));
            mc.world.playSound(SOUND_TILL_LAND, location, SOUND_OPTIONS);
            mc.world.getDimension(dimension).spawnParticle("sgs_farm:plough_dirt", location);
        }
    });

}