package Heuristics;

import java.util.HashMap;
import java.util.Map;

import FaultTree.*;
import Heuristics.Helpers.DepthFirstByWeightOrderer;

public class FaninHeuristic implements Heuristic {
    private class FaultTreeAltometer extends AbstractFaultTreeVisitor {
        private Map<FaultTree, Integer> depths = new HashMap<>();
        @Override
        public void visitIntermediateEvent(IntermediateEvent event) {
            visit(event.left);
            visit(event.right);
            var ld = depths.get(event.left);
            var rd = depths.get(event.right);
            depths.put(event, Math.max(ld, rd) + 1);
        }
        @Override
        public void visitBasicEvent(BasicEvent event) {
            depths.put(event, 0);
        }
        public int getDepth(FaultTree tree) {
            return depths.get(tree);
        }
    }

    private class FaultTreeDepthSurvey extends AbstractFaultTreeVisitor {
        private Map<FaultTree, Integer> depths = new HashMap<>();
        @Override
        public void visitAny(FaultTree event) {
            var altometer = new FaultTreeAltometer();
            altometer.visit(event);
            depths.put(event, altometer.getDepth(event));
        }
        public Map<FaultTree, Integer> getDepths() {
            return depths;
        }
    }

    @Override
    public Map<BasicEvent, Integer> getOrder(FaultTree tree) {
        var survey = new FaultTreeDepthSurvey();
        survey.visit(tree);
        var weights = survey.getDepths();
        var orderer = new DepthFirstByWeightOrderer(weights);
        orderer.visit(tree);
        return orderer.getOrder();
    }
    
}