import { cropsCombined } from '../crops/sgs_farm_cropconfig';
import { highlightBlock, randomWholeNum } from '../sgs_farm_lib';
import * as mc from "@minecraft/server";
import * as irrigate from '../u1/sgs_farm_irrigate';

const SPRINKLER_RADIUS = 6;

export class sprinklerManager {
    static beforeplace(data) {
        const block = data.block;

        const north = block.north();
        const east = block.east();
        const south = block.south();
        const west = block.west();

        let northConnects = (north.hasTag("sgs_farm_pipe"));
        let eastConnects = (east.hasTag("sgs_farm_pipe"));
        let southConnects = (south.hasTag("sgs_farm_pipe"));
        let westConnects = (west.hasTag("sgs_farm_pipe"));

        mc.system.runTimeout(() => {
            if (northConnects && !north.hasTag("sgs_farm_pump")) north.setPermutation(north.permutation.withState('sgs_farm:pipe_south', 1));
            if (eastConnects && !east.hasTag("sgs_farm_pump")) east.setPermutation(east.permutation.withState('sgs_farm:pipe_west', 1));
            if (southConnects && !south.hasTag("sgs_farm_pump")) south.setPermutation(south.permutation.withState('sgs_farm:pipe_north', 1));
            if (westConnects && !west.hasTag("sgs_farm_pump")) west.setPermutation(west.permutation.withState('sgs_farm:pipe_east', 1));
        }, 0)

        if (north.hasTag("sgs_farm_pump") && north.permutation.getState('minecraft:cardinal_direction') == "north") northConnects = true;
        if (east.hasTag("sgs_farm_pump") && east.permutation.getState('minecraft:cardinal_direction') == "east") eastConnects = true;
        if (south.hasTag("sgs_farm_pump") && south.permutation.getState('minecraft:cardinal_direction') == "south") southConnects = true;
        if (west.hasTag("sgs_farm_pump") && west.permutation.getState('minecraft:cardinal_direction') == "west") westConnects = true;

        let network_range = 0;
        if (northConnects && network_range < north.permutation.getState("sgs_farm:network_range")) network_range = (north.permutation.getState("sgs_farm:network_range") - 1);
        if (eastConnects && network_range < east.permutation.getState("sgs_farm:network_range")) network_range = (east.permutation.getState("sgs_farm:network_range") - 1);
        if (southConnects && network_range < south.permutation.getState("sgs_farm:network_range")) network_range = (south.permutation.getState("sgs_farm:network_range") - 1);
        if (westConnects && network_range < west.permutation.getState("sgs_farm:network_range")) network_range = (west.permutation.getState("sgs_farm:network_range") - 1);

        if (network_range < 0) network_range = 0;

        data.permutationToPlace = mc.BlockPermutation.resolve(data.permutationToPlace.type.id, { 'sgs_farm:pipe_inventory': 1, 'sgs_farm:network_range': network_range, 'sgs_farm:pipe_north': northConnects ? 1 : 0, 'sgs_farm:pipe_south': southConnects ? 1 : 0, 'sgs_farm:pipe_east': eastConnects ? 1 : 0, 'sgs_farm:pipe_west': westConnects ? 1 : 0 });

        mc.system.runTimeout(() => {
            this.checkNetworkBlock(block, network_range);
        }, 1)

    }

    static destroy(data) {

        const network_range = data.destroyedBlockPermutation.getState("sgs_farm:network_range");
        const northConnects = data.destroyedBlockPermutation.getState("sgs_farm:pipe_north");
        const eastConnects = data.destroyedBlockPermutation.getState("sgs_farm:pipe_east");
        const southConnects = data.destroyedBlockPermutation.getState("sgs_farm:pipe_south");
        const westConnects = data.destroyedBlockPermutation.getState("sgs_farm:pipe_west");

        try {
            const block = data.block;
            const north = block.north();
            const east = block.east();
            const south = block.south();
            const west = block.west();

            if (northConnects && north.hasTag("sgs_farm_pipe") && !north.hasTag("sgs_farm_pump")) north.setPermutation(north.permutation.withState('sgs_farm:pipe_south', 0));
            if (eastConnects && east.hasTag("sgs_farm_pipe") && !east.hasTag("sgs_farm_pump")) east.setPermutation(east.permutation.withState('sgs_farm:pipe_west', 0));
            if (southConnects && south.hasTag("sgs_farm_pipe") && !south.hasTag("sgs_farm_pump")) south.setPermutation(south.permutation.withState('sgs_farm:pipe_north', 0));
            if (westConnects && west.hasTag("sgs_farm_pipe") && !west.hasTag("sgs_farm_pump")) west.setPermutation(west.permutation.withState('sgs_farm:pipe_east', 0));

            if (northConnects && north.permutation.getState("sgs_farm:network_range") < network_range) this.cutNetworkBlocks(north);
            if (eastConnects && east.permutation.getState("sgs_farm:network_range") < network_range) this.cutNetworkBlocks(east);
            if (southConnects && south.permutation.getState("sgs_farm:network_range") < network_range) this.cutNetworkBlocks(south);
            if (westConnects && west.permutation.getState("sgs_farm:network_range") < network_range) this.cutNetworkBlocks(west);

        } catch (error) { };
    }

    static destroysprinkler(data) {

        const block = data.block;
        const location = { x: block.location.x - SPRINKLER_RADIUS, y: block.location.y - 0.5, z: block.location.z - SPRINKLER_RADIUS };
        const dimension = block.dimension;

        for (let i = 0; i < SPRINKLER_RADIUS * 2 + 1; i++) {
            for (let j = 0; j < SPRINKLER_RADIUS * 2 + 1; j++) {
                for (let k = -1; k < 3; k++) {
                    const sprinklerblock = dimension.getBlock({ x: location.x + i, y: location.y + k, z: location.z + j });

                    if (sprinklerblock.typeId == "minecraft:farmland") {
                        irrigate.remove(sprinklerblock);
                    }
                }
            }
        };
    }

    static tick(block) {

        try {
            if (block.isAir) return;
            if (block.permutation.getState("sgs_farm:network_range") == 0) {
                const location = { x: block.location.x - SPRINKLER_RADIUS, y: block.location.y - 0.5, z: block.location.z - SPRINKLER_RADIUS };
                const dimension = block.dimension;
                for (let i = 0; i < SPRINKLER_RADIUS * 2 + 1; i++) {
                    for (let j = 0; j < SPRINKLER_RADIUS * 2 + 1; j++) {
                        for (let k = -1; k < 3; k++) {
                            const sprinklerblock = dimension.getBlock({ x: location.x + i, y: location.y + k, z: location.z + j });

                            if (sprinklerblock.typeId == "minecraft:farmland") {
                                irrigate.remove(sprinklerblock);
                            }
                        }
                    }
                };
                return;
            }

            const location = { x: block.location.x - SPRINKLER_RADIUS, y: block.location.y - 0.5, z: block.location.z - SPRINKLER_RADIUS };
            const dimension = block.dimension;
            mc.world.getDimension(dimension.id).spawnParticle("sgs_farm:sprinkler_action", block.center());
            block.dimension.playSound("liquid.water", block.center());

            for (let i = 0; i < SPRINKLER_RADIUS * 2 + 1; i++) {
                for (let j = 0; j < SPRINKLER_RADIUS * 2 + 1; j++) {
                    for (let k = -1; k < 3; k++) {
                        const sprinklerblock = dimension.getBlock({ x: location.x + i, y: location.y + k, z: location.z + j });

                        if (sprinklerblock.typeId == "minecraft:farmland") {
                            irrigate.add(sprinklerblock);
                        }

                        //50% chance to initiate a +1 growth tick
                        const num = randomWholeNum(0, 3);
                        if (num == 0) {
                            const cropData = cropsCombined().find((f) => f.blockID == sprinklerblock.typeId);
                            if (cropData != undefined) {

                                this.wateringGrowthTick(sprinklerblock, cropData, sprinklerblock.permutation.getState(cropData.stateID));
                            }
                        }
                    }
                }
            };
        } catch (error) { }
    }

    static interact(block) {
        try {
            if (block.isAir) return;

            const location = { x: block.location.x - SPRINKLER_RADIUS, y: block.location.y - 0.5, z: block.location.z - SPRINKLER_RADIUS };
            const dimension = block.dimension;
            for (let i = 0; i < SPRINKLER_RADIUS * 2 + 1; i++) {
                for (let j = 0; j < SPRINKLER_RADIUS * 2 + 1; j++) {
                    const sprinklerblock = dimension.getBlock({ x: location.x + i, y: location.y, z: location.z + j });
                    highlightBlock(sprinklerblock);
                }
            };
        } catch (error) { }
    }

    static beforeplacePump(data) {
        const block = data.block;

        const north = block.north();
        const east = block.east();
        const south = block.south();
        const west = block.west();
        const cardinal = data.permutationToPlace.getState('minecraft:cardinal_direction');

        let northConnects = (north.hasTag("sgs_farm_pipe"));
        let eastConnects = (east.hasTag("sgs_farm_pipe"));
        let southConnects = (south.hasTag("sgs_farm_pipe"));
        let westConnects = (west.hasTag("sgs_farm_pipe"));
        let network_range = 16;
        if (block.below().type.id != "minecraft:water") network_range = 0;


        if (cardinal == "south" && northConnects) north.setPermutation(north.permutation.withState('sgs_farm:pipe_south', 1));
        if (cardinal == "west" && eastConnects) east.setPermutation(east.permutation.withState('sgs_farm:pipe_west', 1));
        if (cardinal == "north" && southConnects) south.setPermutation(south.permutation.withState('sgs_farm:pipe_north', 1));
        if (cardinal == "east" && westConnects) west.setPermutation(west.permutation.withState('sgs_farm:pipe_east', 1));

        data.permutationToPlace = mc.BlockPermutation.resolve(data.permutationToPlace.type.id, { 'minecraft:cardinal_direction': data.permutationToPlace.getState('minecraft:cardinal_direction'), 'sgs_farm:network_range': network_range });

        if (network_range == 16) {
            mc.world.getDimension(block.dimension.id).spawnParticle("sgs_farm:water_splash", block.center());

            let connectblock;
            if (cardinal == "south" && north.hasTag("sgs_farm_pipe")) connectblock = north;
            if (cardinal == "west" && east.hasTag("sgs_farm_pipe")) connectblock = east;
            if (cardinal == "north" && south.hasTag("sgs_farm_pipe")) connectblock = south;
            if (cardinal == "east" && west.hasTag("sgs_farm_pipe")) connectblock = west;

            if (connectblock == undefined) return;
            connectblock.setPermutation(connectblock.permutation.withState('sgs_farm:network_range', 15));

            mc.system.runTimeout(() => {
                this.checkNetworkBlock(connectblock, 15);
            }, 1)
        }
    }

    static destroyPump(data) {
        const block = data.block;

        const north = block.north();
        const east = block.east();
        const south = block.south();
        const west = block.west();

        const cardinal = data.destroyedBlockPermutation.getState('minecraft:cardinal_direction');

        if (cardinal == "south" && north.hasTag("sgs_farm_pipe")) north.setPermutation(north.permutation.withState('sgs_farm:pipe_south', 0));
        if (cardinal == "west" && east.hasTag("sgs_farm_pipe")) east.setPermutation(east.permutation.withState('sgs_farm:pipe_west', 0));
        if (cardinal == "north" && south.hasTag("sgs_farm_pipe")) south.setPermutation(south.permutation.withState('sgs_farm:pipe_north', 0));
        if (cardinal == "east" && west.hasTag("sgs_farm_pipe")) west.setPermutation(west.permutation.withState('sgs_farm:pipe_east', 0));

        if (cardinal == "south" && north.hasTag("sgs_farm_pipe")) this.cutNetworkBlocks(north);
        if (cardinal == "west" && east.hasTag("sgs_farm_pipe")) this.cutNetworkBlocks(east);
        if (cardinal == "north" && south.hasTag("sgs_farm_pipe")) this.cutNetworkBlocks(south);
        if (cardinal == "east" && west.hasTag("sgs_farm_pipe")) this.cutNetworkBlocks(west);
    }

    static tickPump(block) {
        try {
            if (block.isAir) return;

            const north = block.north();
            const east = block.east();
            const south = block.south();
            const west = block.west();
            const cardinal = block.permutation.getState('minecraft:cardinal_direction');

            let connectblock;

            if (cardinal == "south" && north.hasTag("sgs_farm_pipe")) connectblock = north;
            if (cardinal == "west" && east.hasTag("sgs_farm_pipe")) connectblock = east;
            if (cardinal == "north" && south.hasTag("sgs_farm_pipe")) connectblock = south;
            if (cardinal == "east" && west.hasTag("sgs_farm_pipe")) connectblock = west;


            if (block.below().type.id == "minecraft:water") {
                //has water? set active
                block.setPermutation(block.permutation.withState('sgs_farm:network_range', 16));
                mc.world.getDimension(block.dimension.id).spawnParticle("sgs_farm:water_splash", block.center());
                if (connectblock == undefined) return;
                connectblock.setPermutation(connectblock.permutation.withState('sgs_farm:network_range', 15));
                this.checkNetworkBlock(connectblock, 15);
            }
            else {
                block.setPermutation(block.permutation.withState('sgs_farm:network_range', 0));
                if (connectblock == undefined) return;
                this.cutNetworkBlocks(connectblock);
            }
        } catch (error) { }

    }

    //recursively check network blocks to make range go up
    static checkNetworkBlock(block, network_range) {
        //if range is minimum no point in checking further
        if (network_range <= 1) return;

        const permutation = block.permutation;
        const north = block.north();
        const east = block.east();
        const south = block.south();
        const west = block.west();

        const northConnects = permutation.getState("sgs_farm:pipe_north");
        const eastConnects = permutation.getState("sgs_farm:pipe_east");
        const southConnects = permutation.getState("sgs_farm:pipe_south");
        const westConnects = permutation.getState("sgs_farm:pipe_west");

        if (northConnects && north.permutation.getState("sgs_farm:network_range") < network_range) {
            north.setPermutation(north.permutation.withState('sgs_farm:network_range', network_range - 1));
            this.checkNetworkBlock(north, network_range - 1);
        }
        if (eastConnects && east.permutation.getState("sgs_farm:network_range") < network_range) {
            east.setPermutation(east.permutation.withState('sgs_farm:network_range', network_range - 1));
            this.checkNetworkBlock(east, network_range - 1);
        }
        if (southConnects && south.permutation.getState("sgs_farm:network_range") < network_range) {
            south.setPermutation(south.permutation.withState('sgs_farm:network_range', network_range - 1));
            this.checkNetworkBlock(south, network_range - 1);
        }
        if (westConnects && west.permutation.getState("sgs_farm:network_range") < network_range) {
            west.setPermutation(west.permutation.withState('sgs_farm:network_range', network_range - 1));
            this.checkNetworkBlock(west, network_range - 1);
        }
    }

    //cut network, set range to 0
    static cutNetworkBlocks(block) {

        const permutation = block.permutation;
        const network_range = block.permutation.getState("sgs_farm:network_range");
        const north = block.north();
        const east = block.east();
        const south = block.south();
        const west = block.west();

        const northConnects = permutation.getState("sgs_farm:pipe_north");
        const eastConnects = permutation.getState("sgs_farm:pipe_east");
        const southConnects = permutation.getState("sgs_farm:pipe_south");
        const westConnects = permutation.getState("sgs_farm:pipe_west");

        if (northConnects && north.permutation.getState("sgs_farm:network_range") < network_range) this.cutNetworkBlocks(north);
        if (eastConnects && east.permutation.getState("sgs_farm:network_range") < network_range) this.cutNetworkBlocks(east);
        if (southConnects && south.permutation.getState("sgs_farm:network_range") < network_range) this.cutNetworkBlocks(south);
        if (westConnects && west.permutation.getState("sgs_farm:network_range") < network_range) this.cutNetworkBlocks(west);

        block.setPermutation(block.permutation.withState('sgs_farm:network_range', 0));
    }

    static wateringGrowthTick(block, data, stage) {

        let setStage = stage + 1;
        if (setStage > data.maxStage) {
            setStage = data.maxStage;
            return;
        }
        try {
            block.dimension.spawnParticle("minecraft:crop_growth_emitter", block.center());
        } catch { }
        if (data.height == 1) {
            block.setPermutation(block.permutation.withState(data.stateID, setStage));
        };
        if (data.height == 2) {
            let block_top = block.above(1);
            if (block_top.isAir || block_top.typeId == data.blockID + "_top") {
                block.setPermutation(block.permutation.withState(data.stateID, stage + 1));
                block_top.setPermutation(mc.BlockPermutation.resolve(data.blockID + "_top", { "sgs_farm:growth": stage + 1, "sgs_farm:shifted": block.permutation.getState("sgs_farm:shifted") }));
            }
        };
    }
}
