package net.onrc.onos.core.newintent;

import net.onrc.onos.api.flowmanager.FlowIdGenerator;
import net.onrc.onos.api.flowmanager.SingleDstTreeFlow;
import net.onrc.onos.api.flowmanager.Tree;
import net.onrc.onos.api.newintent.Intent;
import net.onrc.onos.api.newintent.IntentIdGenerator;
import net.onrc.onos.api.newintent.MultiPointToSinglePointIntent;
import net.onrc.onos.core.intent.ConstrainedBFSTree;
import net.onrc.onos.core.intent.Path;
import net.onrc.onos.core.matchaction.match.Match;
import net.onrc.onos.core.matchaction.match.PacketMatch;
import net.onrc.onos.core.topology.BaseTopology;
import net.onrc.onos.core.topology.ITopologyService;
import net.onrc.onos.core.topology.Switch;
import net.onrc.onos.core.util.SwitchPort;

import java.util.Arrays;
import java.util.List;
import java.util.Set;

import static com.google.common.base.Preconditions.checkNotNull;
import static net.onrc.onos.core.newintent.PointToPointIntentCompiler.convertPath;

/**
 * An intent compiler for {@link MultiPointToSinglePointIntent}.
 */
public class MultiPointToSinglePointIntentCompiler
        extends AbstractFlowGeneratingIntentCompiler<MultiPointToSinglePointIntent> {

    private final ITopologyService topologyService;

    /**
     * Constructs an intent compiler for {@link MultiPointToSinglePointIntent}.
     *
     * @param intentIdGenerator intent ID generator
     * @param flowIdGenerator flow ID generator
     * @param topologyService topology service
     */
    public MultiPointToSinglePointIntentCompiler(IntentIdGenerator intentIdGenerator,
                                                 FlowIdGenerator flowIdGenerator,
                                                 ITopologyService topologyService) {
        super(intentIdGenerator, flowIdGenerator);
        this.topologyService = checkNotNull(topologyService);
    }

    @Override
    public List<Intent> compile(MultiPointToSinglePointIntent intent) {
        Match match = intent.getMatch();
        if (!(match instanceof PacketMatch)) {
            throw new IntentCompilationException(
                    "intent has unsupported type of match object: " + match
            );
        }

        SingleDstTreeFlow treeFlow = new SingleDstTreeFlow(
                getNextFlowId(),
                (PacketMatch) intent.getMatch(), // down-cast, but it is safe due to the guard above
                intent.getIngressPorts(),
                calculateTree(intent.getIngressPorts(), intent.getEgressPort()),
                packActions(intent, intent.getEgressPort())
        );
        Intent compiled = new SingleDstTreeFlowIntent(getNextId(), treeFlow);
        return Arrays.asList(compiled);
    }

    /**
     * Calculates a tree with the specified ingress ports and egress port.
     *
     * {@link PathNotFoundException} is thrown when no tree found or
     * the specified egress port is not found in the topology.
     *
     * @param ingressPorts ingress ports
     * @param egressPort egress port
     * @return tree
     * @throws PathNotFoundException if the specified egress switch is not
     * found or no tree is found.
     */
    private Tree calculateTree(Set<SwitchPort> ingressPorts, SwitchPort egressPort) {
        BaseTopology topology = topologyService.getTopology();
        Switch egressSwitch = topology.getSwitch(egressPort.getDpid());
        if (egressSwitch == null) {
            throw new PathNotFoundException("destination switch not found: " + egressPort.getDpid());
        }

        ConstrainedBFSTree bfs = new ConstrainedBFSTree(egressSwitch);
        Tree tree = new Tree();

        for (SwitchPort ingressPort: ingressPorts) {
            Switch ingressSwitch = topology.getSwitch(ingressPort.getDpid());
            if (ingressSwitch == null) {
                continue;
            }

            Path path = bfs.getPath(ingressSwitch);
            if (path.isEmpty()) {
                continue;
            }

            tree.addAll(convertPath(path));
        }

        if (tree.isEmpty()) {
            throw new PathNotFoundException(
                    String.format("No tree found (ingress: %s, egress: %s", ingressPorts, egressPort)
            );
        }

        return tree;
    }
}
