/*
 * Copyright 2014-present Open Networking Foundation
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.onosproject.net.intent;

import com.google.common.base.MoreObjects;
import com.google.common.collect.Sets;
import org.onlab.graph.ScalarWeight;
import org.onlab.graph.Weight;
import org.onosproject.core.ApplicationId;
import org.onosproject.core.GroupId;
import org.onosproject.net.ConnectPoint;
import org.onosproject.net.DefaultLink;
import org.onosproject.net.DefaultPath;
import org.onosproject.net.DeviceId;
import org.onosproject.net.ElementId;
import org.onosproject.net.HostId;
import org.onosproject.net.Link;
import org.onosproject.net.NetTestTools;
import org.onosproject.net.NetworkResource;
import org.onosproject.net.Path;
import org.onosproject.net.device.DeviceServiceAdapter;
import org.onosproject.net.flow.FlowId;
import org.onosproject.net.flow.FlowRule;
import org.onosproject.net.flow.IndexTableId;
import org.onosproject.net.flow.TableId;
import org.onosproject.net.flow.TrafficSelector;
import org.onosproject.net.flow.TrafficTreatment;
import org.onosproject.net.flow.criteria.Criterion;
import org.onosproject.net.flow.criteria.Criterion.Type;
import org.onosproject.net.flow.instructions.Instruction;
import org.onosproject.net.flow.instructions.Instructions;
import org.onosproject.net.flow.instructions.Instructions.MetadataInstruction;
import org.onosproject.net.link.LinkServiceAdapter;
import org.onosproject.net.provider.ProviderId;
import org.onosproject.net.topology.DefaultTopologyEdge;
import org.onosproject.net.topology.DefaultTopologyVertex;
import org.onosproject.net.topology.LinkWeigher;
import org.onosproject.net.topology.PathServiceAdapter;
import org.onosproject.net.topology.TopologyVertex;
import org.onosproject.store.Timestamp;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Objects;
import java.util.Set;
import java.util.concurrent.atomic.AtomicLong;
import java.util.stream.Collectors;
import java.util.stream.IntStream;

import static org.onosproject.net.Link.Type.DIRECT;
import static org.onosproject.net.NetTestTools.*;

/**
 * Common mocks used by the intent framework tests.
 */
public class IntentTestsMocks {
    /**
     * Mock traffic selector class used for satisfying API requirements.
     */
    public static class MockSelector implements TrafficSelector {
        @Override
        public Set<Criterion> criteria() {
            return new HashSet<>();
        }

        @Override
        public Criterion getCriterion(Type type) {
            return null;
        }
    }

    /**
     * Mock traffic treatment class used for satisfying API requirements.
     */
    public static class MockTreatment implements TrafficTreatment {
        @Override
        public List<Instruction> deferred() {
            return Collections.emptyList();
        }

        @Override
        public List<Instruction> immediate() {
            return Collections.emptyList();
        }

        @Override
        public List<Instruction> allInstructions() {
            return Collections.emptyList();
        }

        @Override
        public Instructions.TableTypeTransition tableTransition() {
            return null;
        }

        @Override
        public boolean clearedDeferred() {
            return false;
        }

        @Override
        public MetadataInstruction writeMetadata() {
            return null;
        }

        @Override
        public Instructions.StatTriggerInstruction statTrigger() {
            return null;
        }

        @Override
        public Instructions.MeterInstruction metered() {
            return null;
        }

        @Override
        public Set<Instructions.MeterInstruction> meters() {
            return Sets.newHashSet();
        }
    }

    /**
     * Mock path service for creating paths within the test.
     */
    public static class MockPathService extends PathServiceAdapter {

        final String[] pathHops;
        final String[] reversePathHops;

        /**
         * Constructor that provides a set of hops to mock.
         *
         * @param pathHops path hops to mock
         */
        public MockPathService(String[] pathHops) {
            this.pathHops = pathHops;
            String[] reversed = pathHops.clone();
            Collections.reverse(Arrays.asList(reversed));
            reversePathHops = reversed;
        }

        @Override
        public Set<Path> getPaths(ElementId src, ElementId dst) {
            Set<Path> result = new HashSet<>();

            String[] allHops = new String[pathHops.length];

            if (src.toString().endsWith(pathHops[0])) {
                System.arraycopy(pathHops, 0, allHops, 0, pathHops.length);
            } else {
                System.arraycopy(reversePathHops, 0, allHops, 0, pathHops.length);
            }

            result.add(createPath(src instanceof HostId, dst instanceof HostId, allHops));
            return result;
        }

        @Override
        public Set<Path> getPaths(ElementId src, ElementId dst, LinkWeigher weigher) {
            Set<Path> paths = getPaths(src, dst);

            for (Path path : paths) {
                DeviceId srcDevice = path.src().elementId() instanceof DeviceId ? path.src().deviceId() : null;
                DeviceId dstDevice = path.dst().elementId() instanceof DeviceId ? path.dst().deviceId() : null;
                if (srcDevice != null && dstDevice != null) {
                    TopologyVertex srcVertex = new DefaultTopologyVertex(srcDevice);
                    TopologyVertex dstVertex = new DefaultTopologyVertex(dstDevice);
                    Link link = link(src.toString(), 1, dst.toString(), 1);

                    Weight weightValue = weigher.weight(new DefaultTopologyEdge(srcVertex, dstVertex, link));
                    if (weightValue.isNegative()) {
                        return new HashSet<>();
                    }
                }
            }
            return paths;
        }
    }

    /**
     * Mock path service for creating paths within the test with multiple possible paths.
     */
    public static class MockMultiplePathService extends PathServiceAdapter {

        final String[][] pathsHops;

        /**
         * Constructor that provides a set of hops to mock.
         *
         * @param pathHops multiple path hops to mock
         */
        public MockMultiplePathService(String[][] pathHops) {
            this.pathsHops = pathHops;
        }

        @Override
        public Set<Path> getPaths(ElementId src, ElementId dst) {

            //Extracts all the paths that goes from src to dst
            Set<Path> allPaths = new HashSet<>();
            allPaths.addAll(IntStream.range(0, pathsHops.length)
                    .filter(i -> src.toString().endsWith(pathsHops[i][0])
                            && dst.toString().endsWith(pathsHops[i][pathsHops[i].length - 1]))
                    .mapToObj(i -> createPath(src instanceof HostId,
                                              dst instanceof HostId,
                                              pathsHops[i]))
                    .collect(Collectors.toSet()));

            // Maintain only the shortest paths
            int minPathLength = allPaths.stream()
                    .mapToInt(o -> o.links().size())
                    .min()
                    .orElse(Integer.MAX_VALUE);
            Set<Path> shortestPaths = allPaths.stream()
                    .filter(path -> path.links().size() <= minPathLength)
                    .collect(Collectors.toSet());

            return shortestPaths;
        }


        @Override
        public Set<Path> getPaths(ElementId src, ElementId dst, LinkWeigher weigher) {
            Set<Path> paths = getPaths(src, dst);

            for (Path path : paths) {
                DeviceId srcDevice = path.src().elementId() instanceof DeviceId ? path.src().deviceId() : null;
                DeviceId dstDevice = path.dst().elementId() instanceof DeviceId ? path.dst().deviceId() : null;
                if (srcDevice != null && dstDevice != null) {
                    TopologyVertex srcVertex = new DefaultTopologyVertex(srcDevice);
                    TopologyVertex dstVertex = new DefaultTopologyVertex(dstDevice);
                    Link link = link(src.toString(), 1, dst.toString(), 1);

                    Weight weightValue = weigher.weight(new DefaultTopologyEdge(srcVertex, dstVertex, link));
                    if (weightValue.isNegative()) {
                        return new HashSet<>();
                    }
                }
            }
            return paths;
        }
    }


    /**
     * Mock path service for creating paths within the test.
     *
     */
    public static class Mp2MpMockPathService extends PathServiceAdapter {

        final String[] pathHops;
        final String[] reversePathHops;

        /**
         * Constructor that provides a set of hops to mock.
         *
         * @param pathHops path hops to mock
         */
        public Mp2MpMockPathService(String[] pathHops) {
            this.pathHops = pathHops;
            String[] reversed = pathHops.clone();
            Collections.reverse(Arrays.asList(reversed));
            reversePathHops = reversed;
        }

        @Override
        public Set<Path> getPaths(ElementId src, ElementId dst) {
            Set<Path> result = new HashSet<>();

            String[] allHops = new String[pathHops.length + 2];
            allHops[0] = src.toString();
            allHops[allHops.length - 1] = dst.toString();

            if (pathHops.length != 0) {
                System.arraycopy(pathHops, 0, allHops, 1, pathHops.length);
            }

            result.add(createPath(allHops));

            return result;
        }

        @Override
        public Set<Path> getPaths(ElementId src, ElementId dst, LinkWeigher weigher) {
            final Set<Path> paths = getPaths(src, dst);

            for (Path path : paths) {
                final DeviceId srcDevice = path.src().elementId() instanceof DeviceId ? path.src().deviceId() : null;
                final DeviceId dstDevice = path.dst().elementId() instanceof DeviceId ? path.dst().deviceId() : null;
                if (srcDevice != null && dstDevice != null) {
                    final TopologyVertex srcVertex = new DefaultTopologyVertex(srcDevice);
                    final TopologyVertex dstVertex = new DefaultTopologyVertex(dstDevice);
                    final Link link = link(src.toString(), 1, dst.toString(), 1);

                    final Weight weightValue = weigher.weight(new DefaultTopologyEdge(srcVertex, dstVertex, link));
                    if (weightValue.isNegative()) {
                        return new HashSet<>();
                    }
                }
            }
            return paths;
        }
    }

    /**
     * Mock active and direct link.
     */
    public static class FakeLink extends DefaultLink {

        /**
         * Constructor that provides source and destination of the fake link.
         *
         * @param src Source connect point of the fake link
         * @param dst Destination connect point of the fake link
         */
        public FakeLink(ConnectPoint src, ConnectPoint dst) {
            super(null, src, dst, DIRECT, Link.State.ACTIVE);
        }
    }

    /**
     * Mock path service for creating paths for MP2SP intent tests, returning
     * pre-determined paths.
     */
    public static class FixedMP2MPMockPathService extends PathServiceAdapter {

        final String[] pathHops;

        public static final String DPID_1 = "of:s1";
        public static final String DPID_2 = "of:s2";
        public static final String DPID_3 = "of:s3";
        public static final String DPID_4 = "of:s4";

        /**
         * Constructor that provides a set of hops to mock.
         *
         * @param pathHops path hops to mock
         */
        public FixedMP2MPMockPathService(String[] pathHops) {
            this.pathHops = pathHops;
        }

        @Override
        public Set<Path> getPaths(ElementId src, ElementId dst) {
            List<Link> links = new ArrayList<>();
            Set<Path> result = new HashSet<>();
            ProviderId providerId = new ProviderId("of", "foo");
            DefaultPath path;
            if (src.toString().equals(DPID_1) && dst.toString().equals(DPID_4)) {
                links.add(NetTestTools.linkNoPrefixes(src.toString(), 2, pathHops[0], 1));
                links.add(NetTestTools.linkNoPrefixes(pathHops[0], 2, dst.toString(), 1));
            } else if (src.toString().equals(DPID_2) && dst.toString().equals(DPID_4)) {
                links.add(NetTestTools.linkNoPrefixes(src.toString(), 2, pathHops[0], 3));
                links.add(NetTestTools.linkNoPrefixes(pathHops[0], 2, dst.toString(), 1));
            } else if (src.toString().equals(DPID_4) && dst.toString().equals(DPID_1)) {
                links.add(NetTestTools.linkNoPrefixes(src.toString(), 2, pathHops[0], 1));
                links.add(NetTestTools.linkNoPrefixes(pathHops[0], 2, dst.toString(), 1));
            } else if (src.toString().equals(DPID_4) && dst.toString().equals(DPID_2)) {
                links.add(NetTestTools.linkNoPrefixes(src.toString(), 2, pathHops[0], 1));
                links.add(NetTestTools.linkNoPrefixes(pathHops[0], 3, dst.toString(), 1));
            } else {
                return result;
            }
            path = new DefaultPath(providerId, links, ScalarWeight.toWeight(3));
            result.add(path);

            return result;
        }

        @Override
        public Set<Path> getPaths(ElementId src, ElementId dst, LinkWeigher weigher) {
            final Set<Path> paths = getPaths(src, dst);

            for (Path path : paths) {
                final DeviceId srcDevice = path.src().elementId() instanceof DeviceId ? path.src().deviceId() : null;
                final DeviceId dstDevice = path.dst().elementId() instanceof DeviceId ? path.dst().deviceId() : null;
                if (srcDevice != null && dstDevice != null) {
                    final TopologyVertex srcVertex = new DefaultTopologyVertex(srcDevice);
                    final TopologyVertex dstVertex = new DefaultTopologyVertex(dstDevice);
                    final Link link = link(src.toString(), 1, dst.toString(), 1);

                    final Weight weightValue = weigher.weight(new DefaultTopologyEdge(srcVertex, dstVertex, link));
                    if (weightValue.isNegative()) {
                        return new HashSet<>();
                    }
                }
            }
            return paths;
        }
    }

    /**
     * Mock link service for getting links to check path availability
     * when a suggested path is submitted.
     */
    public static class MockLinkService extends LinkServiceAdapter {
        final String[][] linksHops;

        /**
         * Constructor that provides a set of links (as a list of hops).
         *
         * @param linksHops links to to mock (link as a set of hops)
         */
        public MockLinkService(String[][] linksHops) {
            this.linksHops = linksHops;
        }

        @Override
        public Set<Link> getLinks() {
            return Arrays.asList(linksHops).stream()
                    .map(path -> createPath(path).links())
                    .flatMap(List::stream)
                    .collect(Collectors.toSet());
        }
        @Override
        public Set<Link> getLinks(ConnectPoint connectPoint) {
            return getLinks().stream()
                    .filter(link -> link.src().deviceId().equals(connectPoint.deviceId())
                    || link.dst().deviceId().equals(connectPoint.deviceId()))
                    .collect(Collectors.toSet());
        }
    }

    private static final IntentTestsMocks.MockSelector SELECTOR =
            new IntentTestsMocks.MockSelector();
    private static final IntentTestsMocks.MockTreatment TREATMENT =
            new IntentTestsMocks.MockTreatment();

    public static class MockFlowRule implements FlowRule {
        static int nextId = 0;

        int priority;
        IndexTableId tableId;
        long timestamp;
        int id;

        public MockFlowRule(int priority) {
            this.priority = priority;
            this.tableId = DEFAULT_TABLE;
            this.timestamp = System.currentTimeMillis();
            this.id = nextId++;
        }

        @Override
        public FlowId id() {
            return FlowId.valueOf(id);
        }

        @Override
        public short appId() {
            return 0;
        }

        @Override
        public GroupId groupId() {
            return new GroupId(0);
        }

        @Override
        public int priority() {
            return priority;
        }

        @Override
        public DeviceId deviceId() {
            return did("1");
        }

        @Override
        public TrafficSelector selector() {
            return SELECTOR;
        }

        @Override
        public TrafficTreatment treatment() {
            return TREATMENT;
        }

        @Override
        public int timeout() {
            return 0;
        }

        @Override
        public int hardTimeout() {
            return 0;
        }

        @Override
        public FlowRemoveReason reason() {
            return FlowRemoveReason.NO_REASON;
        }

        @Override
        public boolean isPermanent() {
            return false;
        }

        @Override
        public int hashCode() {
            return priority;
        }

        @Override
        public boolean equals(Object obj) {
            if (this == obj) {
                return true;
            }
            if (obj == null || getClass() != obj.getClass()) {
                return false;
            }
            final MockFlowRule other = (MockFlowRule) obj;
            return Objects.equals(this.timestamp, other.timestamp) &&
                    this.id == other.id;
        }

        @Override
        public boolean exactMatch(FlowRule rule) {
            return this.equals(rule);
        }

        @Override
        public int tableId() {
            return tableId.id();
        }

        @Override
        public TableId table() {
            return tableId;
        }
    }

    public static class MockIntent extends Intent {
        private static AtomicLong counter = new AtomicLong(0);

        private final Long number;

        public MockIntent(Long number) {
            super(NetTestTools.APP_ID, null, Collections.emptyList(),
                  Intent.DEFAULT_INTENT_PRIORITY, null);
            this.number = number;
        }

        public MockIntent(Long number, ApplicationId appId) {
            super(appId, null, Collections.emptyList(),
                    Intent.DEFAULT_INTENT_PRIORITY, null);
            this.number = number;
        }

        public MockIntent(Long number, Collection<NetworkResource> resources) {
            super(NetTestTools.APP_ID, null, resources, Intent.DEFAULT_INTENT_PRIORITY, null);
            this.number = number;
        }

        public Long number() {
            return number;
        }

        public static Long nextId() {
            return counter.getAndIncrement();
        }

        @Override
        public String toString() {
            return MoreObjects.toStringHelper(getClass())
                    .add("id", id())
                    .add("appId", appId())
                    .toString();
        }
    }

    public static class MockTimestamp implements Timestamp {
        final int value;

        public MockTimestamp(int value) {
            this.value = value;
        }

        @Override
        public int compareTo(Timestamp o) {
            if (!(o instanceof MockTimestamp)) {
                return -1;
            }
            MockTimestamp that = (MockTimestamp) o;
            return this.value - that.value;
        }

        @Override
        public int hashCode() {
            return value;
        }

        @Override
        public boolean equals(Object obj) {
            if (obj instanceof MockTimestamp) {
                return this.compareTo((MockTimestamp) obj) == 0;
            }
            return false;
        }
    }

    /**
     * Mocks the device service so that a device appears available in the test.
     */
    public static class MockDeviceService extends DeviceServiceAdapter {
        @Override
        public boolean isAvailable(DeviceId deviceId) {
            return true;
        }
    }
}
