import { MirMarkerTags } from "../../../../generator/MirMarkerTags.js";
import { MirMarkerTypes } from "../../../../generator/MirMarkerTypes.js";
import { bitwiseAnd } from "../../../src/core/binary/operations/bitwiseAnd.js";
import { Transform } from "../../../src/engine/ecs/transform/Transform.js";
import { CellFilterLiteralFloat } from "../../../src/generation/filtering/numeric/CellFilterLiteralFloat.js";
import { GridTaskActionRuleSet } from "../../../src/generation/grid/generation/discrete/GridTaskActionRuleSet.js";
import { MarkerNodeEmitterFromAction } from "../../../src/generation/markers/emitter/MarkerNodeEmitterFromAction.js";
import {
    MarkerNodeEmitterGridCellAction
} from "../../../src/generation/markers/emitter/MarkerNodeEmitterGridCellAction.js";
import { MarkerNodeEmitterPredicated } from "../../../src/generation/markers/emitter/MarkerNodeEmitterPredicated.js";
import { GridActionRuleSet } from "../../../src/generation/markers/GridActionRuleSet.js";
import { GridCellActionPlaceMarker } from "../../../src/generation/markers/GridCellActionPlaceMarker.js";
import { GridCellActionPlaceMarkerGroup } from "../../../src/generation/markers/GridCellActionPlaceMarkerGroup.js";
import { MarkerNodeMatcherAny } from "../../../src/generation/markers/matcher/MarkerNodeMatcherAny.js";
import { MarkerNodeMatcherByType } from "../../../src/generation/markers/matcher/MarkerNodeMatcherByType.js";
import { GridDataNodePredicateNot } from "../../../src/generation/markers/predicate/GridDataNodePredicateNot.js";
import {
    GridDataNodePredicateOverlaps
} from "../../../src/generation/markers/predicate/GridDataNodePredicateOverlaps.js";
import {
    MarkerNodeTransformerOffsetPosition
} from "../../../src/generation/markers/transform/MarkerNodeTransformerOffsetPosition.js";
import {
    MarkerNodeTransformerRecordUniqueRandomEnum
} from "../../../src/generation/markers/transform/MarkerNodeTransformerRecordUniqueRandomEnum.js";
import { GridCellActionPlaceTags } from "../../../src/generation/placement/action/GridCellActionPlaceTags.js";
import { GridCellActionSequence } from "../../../src/generation/placement/action/util/GridCellActionSequence.js";
import { GridCellPlacementRule } from "../../../src/generation/placement/GridCellPlacementRule.js";
import {
    CellMatcherContainsMarkerWithinRadius
} from "../../../src/generation/rules/cell/CellMatcherContainsMarkerWithinRadius.js";
import { CellMatcherGridPattern } from "../../../src/generation/rules/cell/CellMatcherGridPattern.js";
import { CellMatcherNot } from "../../../src/generation/rules/logic/CellMatcherNot.js";
import { GridTags } from "../grid/GridTags.js";
import { MirGridLayers } from "../grid/MirGridLayers.js";
import { matcher_tag_traversable_unoccupied } from "../rules/matcher_tag_traversable_unoccupied.js";

const pMatcher = new CellMatcherGridPattern();

pMatcher.addRule(0, 0, matcher_tag_traversable_unoccupied);
pMatcher.addRule(1, 0, matcher_tag_traversable_unoccupied);
pMatcher.addRule(0, 1, matcher_tag_traversable_unoccupied);
pMatcher.addRule(1, 1, matcher_tag_traversable_unoccupied);


//no other bases nearby
pMatcher.addRule(0, 0, CellMatcherNot.from(
    CellMatcherContainsMarkerWithinRadius.from(MarkerNodeMatcherByType.from(MirMarkerTypes.Base), 25)
));

const placeTags = new GridCellActionPlaceTags();

placeTags.layerId = MirGridLayers.Tags;
placeTags.resize(2, 2);
placeTags.fill(GridTags.Base | GridTags.Occupied);


const clearTags = new GridCellActionPlaceTags();

clearTags.layerId = MirGridLayers.Tags;
clearTags.resize(2, 2);
clearTags.fill(~GridTags.Traversable);
clearTags.operation = bitwiseAnd;

const placeRoadConnector0 = GridCellActionPlaceMarker.from({ type: 'Road Connector' });
placeRoadConnector0.offset.set(-1, 0);

const placeRoadConnector1 = GridCellActionPlaceMarker.from({ type: 'Road Connector' });
placeRoadConnector1.offset.set(2, 1);

const placeRoadConnector2 = GridCellActionPlaceMarker.from({ type: 'Road Connector' });
placeRoadConnector2.offset.set(1, -1);

const placeRoadConnector3 = GridCellActionPlaceMarker.from({ type: 'Road Connector' });
placeRoadConnector3.offset.set(0, 2);

const placeRoadConnectors = GridCellActionPlaceMarkerGroup.from([
    placeRoadConnector0,
    placeRoadConnector1,
    placeRoadConnector2,
    placeRoadConnector3
]);

const name_set = [];

for (let i = 0; i < 100; i++) {
    name_set.push(`base-${i}`);
}

const rule = GridCellPlacementRule.from({
    matcher: pMatcher,
    action: GridCellActionSequence.from([
        placeTags,
        clearTags,
        MarkerNodeEmitterGridCellAction.from(
            MarkerNodeEmitterPredicated.from({
                predicate: GridDataNodePredicateNot.from(GridDataNodePredicateOverlaps.from(MarkerNodeMatcherAny.INSTANCE)),
                source: MarkerNodeEmitterFromAction.from([
                    GridCellActionPlaceMarker.from({
                        type: MirMarkerTypes.Base,
                        size: 0.5,
                        tags: ['Town', MirMarkerTags.Encounter],
                        properties: {
                            // assign to enemy team
                            team: 1
                        },
                        transform: Transform.fromJSON({
                            position: {
                                x: 0.5,
                                y: 0,
                                z: 0.5
                            }
                        }),
                        transformers: [

                            MarkerNodeTransformerRecordUniqueRandomEnum.from(
                                'name',
                                name_set
                            )
                        ]
                    }),
                    GridCellActionPlaceMarker.from({
                        type: 'Virtual',
                        size: 0.5,
                        transformers: [
                            MarkerNodeTransformerOffsetPosition.from(1, 0)
                        ]
                    }),
                    GridCellActionPlaceMarker.from({
                        type: 'Virtual',
                        size: 0.5,
                        transformers: [
                            MarkerNodeTransformerOffsetPosition.from(0, 1)
                        ]
                    }),
                    GridCellActionPlaceMarker.from({
                        type: 'Virtual',
                        size: 0.5,
                        transformers: [
                            MarkerNodeTransformerOffsetPosition.from(1, 1)
                        ]
                    })
                ])
            })
        ),
        placeRoadConnectors
    ]),
    probability: CellFilterLiteralFloat.from(0.1)
});

rule.allowRotation = false;

/**
 *
 * @returns {GridTaskActionRuleSet}
 */
export const mir_generator_place_bases = () => GridTaskActionRuleSet.from({ rules: GridActionRuleSet.from({ rules: [rule] }) });
