package org.drools.compiler.integrationtests;

import org.junit.Assert;
import org.junit.Test;
import org.kie.api.io.ResourceType;
import org.kie.api.runtime.KieSession;
import org.kie.api.runtime.rule.FactHandle;
import org.kie.internal.utils.KieHelper;

public class Drools1326Test {

    @Test
    public void testDrools1326() {
        String drl = "import " + Drools1326Test.Queen.class.getCanonicalName() + ";\n"
                + "\n"
                + "rule \"multipleQueensHorizontal\"\n"
                + "when\n"
                + "    Queen($id : id, row != null, $i : rowIndex)\n"
                + "    Queen(id > $id, rowIndex == $i)\n"
                + "then\n"
                + "end\n";
        KieSession kieSession = new KieHelper().addContent(drl, ResourceType.DRL).build().newKieSession();

        Queen queen1 = new Queen(1);
        Queen queen2 = new Queen(2);
        Integer row1 = 1;
        Integer row2 = 2;

        FactHandle fq1 = kieSession.insert(queen1);
        FactHandle fq2 = kieSession.insert(queen2);
        // initially both queens have null row
        Assert.assertEquals(0, kieSession.fireAllRules());

        // now Q1 is the only queen on row1
        kieSession.update(fq1, queen1.setRow(row1));
        Assert.assertEquals(0, kieSession.fireAllRules());

        // Q1 moved to row2 but it's still alone
        kieSession.update(fq1, queen1.setRow(row2));
        Assert.assertEquals(0, kieSession.fireAllRules());

        // now Q2 is on row2 together with Q1 -> rule should fire
        kieSession.update(fq2, queen2.setRow(row2));
        Assert.assertEquals(1, kieSession.fireAllRules());

        // Insert everything into a fresh session to prove the expected rule fires
        KieSession kieSession2 = new KieHelper().addContent(drl, ResourceType.DRL).build().newKieSession();
        kieSession2.insert(queen1);
        kieSession2.insert(queen2);
        Assert.assertEquals(1, kieSession2.fireAllRules());
    }

    public static class Queen {

        private final int id;
        private Integer row;

        public Queen(int id) {
            this.id = id;
        }

        public int getId() {
            return id;
        }

        public Integer getRow() {
            return row;
        }

        public Queen setRow(Integer row) {
            this.row = row;
            return this;
        }

        public int getRowIndex() {
            if (row == null) {
                return Integer.MIN_VALUE;
            }
            return row;
        }
    }
}
