/*
 * 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);
        }

    }


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

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

        }

        private Set<Link> makeLinks(String[] linkPair) {
            DeviceId devA = deviceId(linkPair[0]);
            PortNumber portA = portNumber(Long.valueOf(linkPair[1]));
            DeviceId devB = deviceId(linkPair[2]);
            PortNumber portB = portNumber(Long.valueOf(linkPair[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 ImmutableSet.of(linkA, linkB);
        }

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

}
