/*
 * 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.UiTopoLayoutService;
import org.onosproject.ui.impl.AbstractUiImplTest;
import org.onosproject.ui.model.ServiceBundle;
import org.onosproject.ui.model.topo.UiTopoLayout;
import org.onosproject.ui.model.topo.UiTopoLayoutId;

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;
import static org.onosproject.ui.model.topo.UiTopoLayoutId.layoutId;

/**
 * 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, ...

      Layouts:
        LROOT : (default)
        +-- L1 : R1
        +-- L2 : R2
        +-- L3 : R3

      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 LROOT = "LROOT";
    protected static final String L1 = "L1";
    protected static final String L2 = "L2";
    protected static final String L3 = "L3";

    protected static final UiTopoLayout LAYOUT_ROOT = layout(LROOT, null, null);
    protected static final UiTopoLayout LAYOUT_1 = layout(L1, REGION_1, LROOT);
    protected static final UiTopoLayout LAYOUT_2 = layout(L2, REGION_2, LROOT);
    protected static final UiTopoLayout LAYOUT_3 = layout(L3, REGION_3, LROOT);

    protected static final Set<UiTopoLayout> LAYOUT_SET =
            ImmutableSet.of(LAYOUT_ROOT, LAYOUT_1, LAYOUT_2, LAYOUT_3);
    protected static final Set<UiTopoLayout> ROOT_KIDS =
            ImmutableSet.of(LAYOUT_1, LAYOUT_2, LAYOUT_3);
    protected static final Set<UiTopoLayout> PEERS_OF_1 =
            ImmutableSet.of(LAYOUT_2, LAYOUT_3);
    protected static final Set<UiTopoLayout> PEERS_OF_2 =
            ImmutableSet.of(LAYOUT_1, LAYOUT_3);
    protected static final Set<UiTopoLayout> PEERS_OF_3 =
            ImmutableSet.of(LAYOUT_1, LAYOUT_2);

    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 UI topology layout instance with the specified parameters.
     *
     * @param layoutId the layout ID
     * @param region   the backing region
     * @param parentId the parent layout ID
     * @return layout instance
     */
    protected static UiTopoLayout layout(String layoutId, Region region,
                                         String parentId) {
        UiTopoLayoutId pid = parentId == null
                ? UiTopoLayoutId.DEFAULT_ID : layoutId(parentId);
        return new UiTopoLayout(layoutId(layoutId), region, pid);
    }

    /**
     * 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 UiTopoLayoutService layout() {
                    return MOCK_LAYOUT;
                }

                @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 UiTopoLayoutService MOCK_LAYOUT = new MockLayoutService();
    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 UiTopoLayoutServiceAdapter and extending that here
    private static class MockLayoutService implements UiTopoLayoutService {
        private final Map<UiTopoLayoutId, UiTopoLayout> map = new HashMap<>();
        private final Map<UiTopoLayoutId, Set<UiTopoLayout>> peers = new HashMap<>();
        private final Map<RegionId, UiTopoLayout> byRegion = new HashMap<>();

        MockLayoutService() {
            map.put(LAYOUT_ROOT.id(), LAYOUT_ROOT);
            map.put(LAYOUT_1.id(), LAYOUT_1);
            map.put(LAYOUT_2.id(), LAYOUT_2);
            map.put(LAYOUT_3.id(), LAYOUT_3);

            peers.put(LAYOUT_ROOT.id(), ImmutableSet.of());
            peers.put(LAYOUT_1.id(), ImmutableSet.of(LAYOUT_2, LAYOUT_3));
            peers.put(LAYOUT_2.id(), ImmutableSet.of(LAYOUT_1, LAYOUT_3));
            peers.put(LAYOUT_3.id(), ImmutableSet.of(LAYOUT_1, LAYOUT_2));

            byRegion.put(REGION_1.id(), LAYOUT_1);
            byRegion.put(REGION_2.id(), LAYOUT_2);
            byRegion.put(REGION_3.id(), LAYOUT_3);
        }

        @Override
        public UiTopoLayout getRootLayout() {
            return LAYOUT_ROOT;
        }

        @Override
        public Set<UiTopoLayout> getLayouts() {
            return LAYOUT_SET;
        }

        @Override
        public boolean addLayout(UiTopoLayout layout) {
            return false;
        }

        @Override
        public UiTopoLayout getLayout(UiTopoLayoutId layoutId) {
            return map.get(layoutId);
        }

        @Override
        public UiTopoLayout getLayout(RegionId regionId) {
            return byRegion.get(regionId);
        }

        @Override
        public Set<UiTopoLayout> getPeerLayouts(UiTopoLayoutId layoutId) {
            return peers.get(layoutId);
        }

        @Override
        public Set<UiTopoLayout> getChildren(UiTopoLayoutId layoutId) {
            return LAYOUT_ROOT.id().equals(layoutId)
                    ? ROOT_KIDS
                    : Collections.emptySet();
        }

        @Override
        public boolean removeLayout(UiTopoLayout layout) {
            return false;
        }
    }

    // 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
    }


    /**
     * Creates a default host connected at the given edge device and port. Note
     * that an identifying hex character ("a" - "f") should be supplied. This
     * will be included in the MAC address of the host (and equivalent value
     * as last byte in IP address).
     *
     * @param device  edge device
     * @param port    port number
     * @param hexChar identifying hex character
     * @return host connected at that location
     */
    protected static Host createHost(Device device, int port, String hexChar) {
        DeviceId deviceId = device.id();
        String devNum = deviceId.toString().substring(1);

        MacAddress mac = MacAddress.valueOf(HOST_MAC_PREFIX + devNum + hexChar);
        HostId hostId = hostId(String.format("%s/-1", mac));

        int ipByte = Integer.valueOf(hexChar, 16);
        if (ipByte < 10 || ipByte > 15) {
            throw new IllegalArgumentException("hexChar must be a-f");
        }
        HostLocation loc = new HostLocation(deviceId, portNumber(port), 0);

        IpAddress ip = ip("10." + devNum + ".0." + ipByte);

        return new DefaultHost(ProviderId.NONE, hostId, mac, VlanId.NONE,
                loc, ImmutableSet.of(ip));
    }

    /**
     * Creates a pair of hosts connected to the specified device.
     *
     * @param d edge device
     * @return pair of hosts
     */
    protected static List<Host> createHostPair(Device d) {
        List<Host> hosts = new ArrayList<>();
        hosts.add(createHost(d, 101, "a"));
        hosts.add(createHost(d, 102, "b"));
        return hosts;
    }

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

        MockHostService() {
            for (Device d : ALL_DEVS) {
                for (Host h : createHostPair(d)) {
                    hosts.put(h.id(), h);
                }
            }
        }

        @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
    }

}
