package mhtree;

import messif.operations.Approximate;

public class ApproximateState {
    public int limit;
    protected int objectsChecked;
    protected int bucketsVisited;

    protected ApproximateState(int limit) {
        this.limit = limit;
    }

    public static ApproximateState create(Approximate limits, MHTree mhTree) {
        switch (limits.getLocalSearchType()) {
            case PERCENTAGE:
                return new ApproximateStateObjects(Math.round((float) mhTree.getObjectCount() * (float) limits.getLocalSearchParam() / 100f));
            case ABS_OBJ_COUNT:
                return new ApproximateStateObjects(limits.getLocalSearchParam());
            case DATA_PARTITIONS:
                return new ApproximateStateBuckets(limits.getLocalSearchParam());
            default:
                throw new IllegalArgumentException("Unsupported approximation type: " + limits.getLocalSearchType());
        }
    }

    public void update(LeafNode node) {
        objectsChecked += node.getObjectCount();
        bucketsVisited++;
    }

    public boolean stop() {
        throw new IllegalStateException("ApproxState.stop must be implemented and must not be called!");
    }

    private static class ApproximateStateBuckets extends ApproximateState {
        private ApproximateStateBuckets(int limit) {
            super(limit);
        }

        @Override
        public boolean stop() {
            return bucketsVisited >= limit;
        }
    }

    private static class ApproximateStateObjects extends ApproximateState {
        private ApproximateStateObjects(int limit) {
            super(limit);
        }

        @Override
        public boolean stop() {
            return objectsChecked >= limit;
        }
    }
}
