/*
 * Copyright 2016-present Open Networking Laboratory
 *
 * 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.ui.impl.topo.model;

import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import org.onlab.packet.IpAddress;
import org.onlab.packet.MacAddress;
import org.onlab.packet.VlanId;
import org.onosproject.cluster.ClusterService;
import org.onosproject.cluster.ClusterServiceAdapter;
import org.onosproject.cluster.ControllerNode;
import org.onosproject.cluster.DefaultControllerNode;
import org.onosproject.cluster.NodeId;
import org.onosproject.cluster.RoleInfo;
import org.onosproject.mastership.MastershipService;
import org.onosproject.mastership.MastershipServiceAdapter;
import org.onosproject.net.ConnectPoint;
import org.onosproject.net.DefaultDevice;
import org.onosproject.net.DefaultHost;
import org.onosproject.net.DefaultLink;
import org.onosproject.net.Device;
import org.onosproject.net.DeviceId;
import org.onosproject.net.Host;
import org.onosproject.net.HostId;
import org.onosproject.net.HostLocation;
import org.onosproject.net.Link;
import org.onosproject.net.PortNumber;
import org.onosproject.net.device.DeviceService;
import org.onosproject.net.device.DeviceServiceAdapter;
import org.onosproject.net.flow.FlowRuleService;
import org.onosproject.net.host.HostService;
import org.onosproject.net.host.HostServiceAdapter;
import org.onosproject.net.intent.IntentService;
import org.onosproject.net.link.LinkService;
import org.onosproject.net.link.LinkServiceAdapter;
import org.onosproject.net.provider.ProviderId;
import org.onosproject.net.region.DefaultRegion;
import org.onosproject.net.region.Region;
import org.onosproject.net.region.RegionId;
import org.onosproject.net.region.RegionListener;
import org.onosproject.net.region.RegionService;
import org.onosproject.ui.impl.AbstractUiImplTest;
import org.onosproject.ui.model.ServiceBundle;

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import static org.onosproject.cluster.NodeId.nodeId;
import static org.onosproject.net.DeviceId.deviceId;
import static org.onosproject.net.HostId.hostId;
import static org.onosproject.net.PortNumber.portNumber;

/**
 * Base class for model test classes.
 */
abstract class AbstractTopoModelTest extends AbstractUiImplTest {

    /*
      Our mock environment:

      Three controllers: C1, C2, C3

      Nine devices: D1 .. D9

             D4 ---+              +--- D7
                   |              |
            D5 --- D1 --- D2 --- D3 --- D8
                   |              |
             D6 ---+              +--- D9

      Twelve hosts (two per D4 ... D9)  H4a, H4b, H5a, H5b, ...

      Regions:
        R1 : D1, D2, D3
        R2 : D4, D5, D6
        R3 : D7, D8, D9

      Mastership:
        C1 : D1, D2, D3
        C2 : D4, D5, D6
        C3 : D7, D8, D9

      Roles: (backups)
        C1 -> C2, C3
        C2 -> C1, C3
        C3 -> C1, C2
     */

    protected static final String C1 = "C1";
    protected static final String C2 = "C2";
    protected static final String C3 = "C3";

    protected static final NodeId CNID_1 = nodeId(C1);
    protected static final NodeId CNID_2 = nodeId(C2);
    protected static final NodeId CNID_3 = nodeId(C3);

    protected static final ControllerNode CNODE_1 = cnode(CNID_1, "10.0.0.1");
    protected static final ControllerNode CNODE_2 = cnode(CNID_2, "10.0.0.2");
    protected static final ControllerNode CNODE_3 = cnode(CNID_3, "10.0.0.3");

    protected static final String R1 = "R1";
    protected static final String R2 = "R2";
    protected static final String R3 = "R3";

    protected static final Set<NodeId> SET_C1 = ImmutableSet.of(CNID_1);
    protected static final Set<NodeId> SET_C2 = ImmutableSet.of(CNID_2);
    protected static final Set<NodeId> SET_C3 = ImmutableSet.of(CNID_3);

    protected static final Region REGION_1 =
            region(R1, Region.Type.METRO, ImmutableList.of(SET_C1, SET_C2));
    protected static final Region REGION_2 =
            region(R2, Region.Type.CAMPUS, ImmutableList.of(SET_C2, SET_C1));
    protected static final Region REGION_3 =
            region(R3, Region.Type.CAMPUS, ImmutableList.of(SET_C3, SET_C1));

    protected static final Set<Region> REGION_SET =
            ImmutableSet.of(REGION_1, REGION_2, REGION_3);

    protected static final String D1 = "d1";
    protected static final String D2 = "d2";
    protected static final String D3 = "d3";
    protected static final String D4 = "d4";
    protected static final String D5 = "d5";
    protected static final String D6 = "d6";
    protected static final String D7 = "d7";
    protected static final String D8 = "d8";
    protected static final String D9 = "d9";

    protected static final String MFR = "Mfr";
    protected static final String HW = "h/w";
    protected static final String SW = "s/w";
    protected static final String SERIAL = "ser123";

    protected static final DeviceId DEVID_1 = deviceId(D1);
    protected static final DeviceId DEVID_2 = deviceId(D2);
    protected static final DeviceId DEVID_3 = deviceId(D3);
    protected static final DeviceId DEVID_4 = deviceId(D4);
    protected static final DeviceId DEVID_5 = deviceId(D5);
    protected static final DeviceId DEVID_6 = deviceId(D6);
    protected static final DeviceId DEVID_7 = deviceId(D7);
    protected static final DeviceId DEVID_8 = deviceId(D8);
    protected static final DeviceId DEVID_9 = deviceId(D9);

    protected static final Device DEV_1 = device(D1);
    protected static final Device DEV_2 = device(D2);
    protected static final Device DEV_3 = device(D3);
    protected static final Device DEV_4 = device(D4);
    protected static final Device DEV_5 = device(D5);
    protected static final Device DEV_6 = device(D6);
    protected static final Device DEV_7 = device(D7);
    protected static final Device DEV_8 = device(D8);
    protected static final Device DEV_9 = device(D9);

    protected static final List<Device> ALL_DEVS =
            ImmutableList.of(
                    DEV_1, DEV_2, DEV_3,
                    DEV_4, DEV_5, DEV_6,
                    DEV_7, DEV_8, DEV_9
            );

    private static final Set<DeviceId> DEVS_TRUNK =
            ImmutableSet.of(DEVID_1, DEVID_2, DEVID_3);

    private static final Set<DeviceId> DEVS_LEFT =
            ImmutableSet.of(DEVID_4, DEVID_5, DEVID_6);

    private static final Set<DeviceId> DEVS_RIGHT =
            ImmutableSet.of(DEVID_7, DEVID_8, DEVID_9);

    private static final String[][] LINK_CONNECT_DATA = {
            {D1, "12", D2, "21"},
            {D2, "23", D3, "32"},
            {D4, "41", D1, "14"},
            {D5, "51", D1, "15"},
            {D6, "61", D1, "16"},
            {D7, "73", D3, "37"},
            {D8, "83", D3, "38"},
            {D9, "93", D3, "39"},
    };

    private static final String HOST_MAC_PREFIX = "aa:00:00:00:00:";

    /**
     * Returns IP address instance for given string.
     *
     * @param s string
     * @return IP address
     */
    protected static IpAddress ip(String s) {
        return IpAddress.valueOf(s);
    }

    /**
     * Returns controller node instance for given ID and IP.
     *
     * @param id identifier
     * @param ip IP address
     * @return controller node instance
     */
    protected static ControllerNode cnode(NodeId id, String ip) {
        return new DefaultControllerNode(id, ip(ip));
    }

    /**
     * Returns a region instance with specified parameters.
     *
     * @param id      region id
     * @param type    region type
     * @param masters ordered list of master sets
     * @return region instance
     */
    protected static Region region(String id, Region.Type type,
                                   List<Set<NodeId>> masters) {
        return new DefaultRegion(RegionId.regionId(id), "Region-" + id,
                type, masters);
    }

    /**
     * Returns device with given ID.
     *
     * @param id device ID
     * @return device instance
     */
    protected static Device device(String id) {
        return new DefaultDevice(ProviderId.NONE, deviceId(id),
                Device.Type.SWITCH, MFR, HW, SW, SERIAL, null);
    }

    /**
     * Returns canned results.
     * <p>
     * At some future point, we may make this "programmable", so that
     * its state can be changed over the course of a unit test.
     */
    protected static final ServiceBundle MOCK_SERVICES =
            new ServiceBundle() {
                @Override
                public ClusterService cluster() {
                    return MOCK_CLUSTER;
                }

                @Override
                public MastershipService mastership() {
                    return MOCK_MASTER;
                }

                @Override
                public RegionService region() {
                    return MOCK_REGION;
                }

                @Override
                public DeviceService device() {
                    return MOCK_DEVICE;
                }

                @Override
                public LinkService link() {
                    return MOCK_LINK;
                }

                @Override
                public HostService host() {
                    return MOCK_HOST;
                }

                @Override
                public IntentService intent() {
                    return null;
                }

                @Override
                public FlowRuleService flow() {
                    return null;
                }
            };

    private static final ClusterService MOCK_CLUSTER = new MockClusterService();
    private static final MastershipService MOCK_MASTER = new MockMasterService();
    private static final RegionService MOCK_REGION = new MockRegionService();
    private static final DeviceService MOCK_DEVICE = new MockDeviceService();
    private static final LinkService MOCK_LINK = new MockLinkService();
    private static final HostService MOCK_HOST = new MockHostService();


    private static class MockClusterService extends ClusterServiceAdapter {
        private final Map<NodeId, ControllerNode> nodes = new HashMap<>();
        private final Map<NodeId, ControllerNode.State> states = new HashMap<>();

        MockClusterService() {
            nodes.put(CNODE_1.id(), CNODE_1);
            nodes.put(CNODE_2.id(), CNODE_2);
            nodes.put(CNODE_3.id(), CNODE_3);

            states.put(CNODE_1.id(), ControllerNode.State.READY);
            states.put(CNODE_2.id(), ControllerNode.State.ACTIVE);
            states.put(CNODE_3.id(), ControllerNode.State.ACTIVE);
        }

        @Override
        public Set<ControllerNode> getNodes() {
            return ImmutableSet.copyOf(nodes.values());
        }

        @Override
        public ControllerNode getNode(NodeId nodeId) {
            return nodes.get(nodeId);
        }

        @Override
        public ControllerNode.State getState(NodeId nodeId) {
            return states.get(nodeId);
        }
    }


    private static class MockMasterService extends MastershipServiceAdapter {
        private final Map<NodeId, Set<DeviceId>> masterOf = new HashMap<>();

        MockMasterService() {
            masterOf.put(CNODE_1.id(), DEVS_TRUNK);
            masterOf.put(CNODE_2.id(), DEVS_LEFT);
            masterOf.put(CNODE_3.id(), DEVS_RIGHT);
        }

        @Override
        public NodeId getMasterFor(DeviceId deviceId) {
            if (DEVS_TRUNK.contains(deviceId)) {
                return CNID_1;
            }
            if (DEVS_LEFT.contains(deviceId)) {
                return CNID_2;
            }
            if (DEVS_RIGHT.contains(deviceId)) {
                return CNID_3;
            }
            return null;
        }

        @Override
        public Set<DeviceId> getDevicesOf(NodeId nodeId) {
            return masterOf.get(nodeId);
        }

        @Override
        public RoleInfo getNodesFor(DeviceId deviceId) {
            NodeId master = null;
            List<NodeId> backups = new ArrayList<>();

            if (DEVS_TRUNK.contains(deviceId)) {
                master = CNID_1;
                backups.add(CNID_2);
                backups.add(CNID_3);
            } else if (DEVS_LEFT.contains(deviceId)) {
                master = CNID_2;
                backups.add(CNID_1);
                backups.add(CNID_3);
            } else if (DEVS_RIGHT.contains(deviceId)) {
                master = CNID_3;
                backups.add(CNID_1);
                backups.add(CNID_2);
            }
            return new RoleInfo(master, backups);
        }
    }

    // TODO: consider implementing RegionServiceAdapter and extending that here
    private static class MockRegionService implements RegionService {

        private final Map<RegionId, Region> lookup = new HashMap<>();

        MockRegionService() {
            lookup.put(REGION_1.id(), REGION_1);
            lookup.put(REGION_2.id(), REGION_2);
            lookup.put(REGION_3.id(), REGION_3);
        }

        @Override
        public Set<Region> getRegions() {
            return REGION_SET;
        }

        @Override
        public Region getRegion(RegionId regionId) {
            return lookup.get(regionId);
        }

        @Override
        public Region getRegionForDevice(DeviceId deviceId) {
            if (DEVS_TRUNK.contains(deviceId)) {
                return REGION_1;
            }
            if (DEVS_LEFT.contains(deviceId)) {
                return REGION_2;
            }
            if (DEVS_RIGHT.contains(deviceId)) {
                return REGION_3;
            }
            return null;
        }

        @Override
        public Set<DeviceId> getRegionDevices(RegionId regionId) {
            if (REGION_1.id().equals(regionId)) {
                return DEVS_TRUNK;
            }
            if (REGION_2.id().equals(regionId)) {
                return DEVS_LEFT;
            }
            if (REGION_3.id().equals(regionId)) {
                return DEVS_RIGHT;
            }
            return Collections.emptySet();
        }

        @Override
        public void addListener(RegionListener listener) {
        }

        @Override
        public void removeListener(RegionListener listener) {
        }
    }


    private static class MockDeviceService extends DeviceServiceAdapter {
        private final Map<DeviceId, Device> devices = new HashMap<>();

        MockDeviceService() {
            for (Device dev : ALL_DEVS) {
                devices.put(dev.id(), dev);
            }
        }

        @Override
        public int getDeviceCount() {
            return devices.size();
        }

        @Override
        public Iterable<Device> getDevices() {
            return ImmutableList.copyOf(devices.values());
        }

        @Override
        public Device getDevice(DeviceId deviceId) {
            return devices.get(deviceId);
        }

    }

    /**
     * Synthesizes a pair of unidirectional links between two devices. The
     * string array should be of the form:
     * <pre>
     *     { "device-A-id", "device-A-port", "device-B-id", "device-B-port" }
     * </pre>
     *
     * @param linkPairData device ids and ports
     * @return pair of synthesized links
     */
    protected static List<Link> makeLinkPair(String[] linkPairData) {
        DeviceId devA = deviceId(linkPairData[0]);
        PortNumber portA = portNumber(Long.valueOf(linkPairData[1]));
        DeviceId devB = deviceId(linkPairData[2]);
        PortNumber portB = portNumber(Long.valueOf(linkPairData[3]));

        Link linkA = DefaultLink.builder()
                .providerId(ProviderId.NONE)
                .type(Link.Type.DIRECT)
                .src(new ConnectPoint(devA, portA))
                .dst(new ConnectPoint(devB, portB))
                .build();

        Link linkB = DefaultLink.builder()
                .providerId(ProviderId.NONE)
                .type(Link.Type.DIRECT)
                .src(new ConnectPoint(devB, portB))
                .dst(new ConnectPoint(devA, portA))
                .build();

        return ImmutableList.of(linkA, linkB);
    }

    private static class MockLinkService extends LinkServiceAdapter {
        private final Set<Link> links = new HashSet<>();

        MockLinkService() {
            for (String[] linkPair : LINK_CONNECT_DATA) {
                links.addAll(makeLinkPair(linkPair));
            }
        }

        @Override
        public int getLinkCount() {
            return links.size();
        }

        @Override
        public Iterable<Link> getLinks() {
            return ImmutableSet.copyOf(links);
        }

        // TODO: possibly fill out other methods if we find the model uses them
    }


    private static class MockHostService extends HostServiceAdapter {
        private final Map<HostId, Host> hosts = new HashMap<>();

        MockHostService() {
            for (Device d : ALL_DEVS) {
                // two hosts per device
                createHosts(hosts, d);
            }
        }

        private void createHosts(Map<HostId, Host> hosts, Device d) {
            DeviceId deviceId = d.id();
            String devNum = deviceId.toString().substring(1);

            String ha = devNum + "a";
            String hb = devNum + "b";

            MacAddress macA = MacAddress.valueOf(HOST_MAC_PREFIX + ha);
            MacAddress macB = MacAddress.valueOf(HOST_MAC_PREFIX + hb);

            HostId hostA = hostId(String.format("%s/-1", macA));
            HostId hostB = hostId(String.format("%s/-1", macB));

            PortNumber portA = portNumber(101);
            PortNumber portB = portNumber(102);

            HostLocation locA = new HostLocation(deviceId, portA, 0);
            HostLocation locB = new HostLocation(deviceId, portB, 0);

            IpAddress ipA = ip("10." + devNum + ".0.1");
            IpAddress ipB = ip("10." + devNum + ".0.2");

            Host host = new DefaultHost(ProviderId.NONE,
                    hostA, macA, VlanId.NONE, locA,
                    ImmutableSet.of(ipA));
            hosts.put(hostA, host);

            host = new DefaultHost(ProviderId.NONE,
                    hostB, macB, VlanId.NONE, locB,
                    ImmutableSet.of(ipB));
            hosts.put(hostB, host);
        }

        @Override
        public int getHostCount() {
            return hosts.size();
        }

        @Override
        public Iterable<Host> getHosts() {
            return ImmutableSet.copyOf(hosts.values());
        }

        @Override
        public Host getHost(HostId hostId) {
            return hosts.get(hostId);
        }

        // TODO: possibly fill out other methods, should the model require them
    }

}
