package org.teleal.cling.test.model;

import org.teleal.cling.model.meta.DeviceService;
import org.teleal.cling.model.meta.LocalDevice;
import org.teleal.cling.model.meta.RemoteDevice;
import org.teleal.cling.model.types.ServiceType;
import org.teleal.cling.test.data.SampleData;
import org.teleal.cling.test.data.SampleDeviceEmbeddedOneLocal;
import org.teleal.cling.test.data.SampleDeviceEmbeddedTwoLocal;
import org.teleal.cling.test.data.SampleDeviceRootLocal;
import org.testng.annotations.Test;

import static org.testng.Assert.assertEquals;

/**
 * @author Christian Bauer
 */
public class DeviceGraphTest {

    @Test
    public void constructDescriptorURI() throws Exception {
        LocalDevice ld = SampleData.createLocalDevice();

        LocalDevice root = ld.getEmbeddedDevices()[0].getRoot();
        assertEquals(root.getEmbeddedDevices()[0].getDescriptorURI(), root.getDescriptorURI());
        assertEquals(root.getEmbeddedDevices()[0].getEmbeddedDevices()[0].getDescriptorURI(), root.getDescriptorURI());

    }

    @Test
    public void findRoot() throws Exception {
        LocalDevice ld = SampleData.createLocalDevice();

        LocalDevice root = ld.getEmbeddedDevices()[0].getRoot();
        assertEquals(root.getIdentity().getUdn(), SampleDeviceRootLocal.getRootUDN());

        root = ld.getEmbeddedDevices()[0].getEmbeddedDevices()[0].getRoot();
        assertEquals(root.getIdentity().getUdn(), SampleDeviceRootLocal.getRootUDN());

    }

    @Test
    public void findEmbeddedDevices() throws Exception {
        LocalDevice ld = SampleData.createLocalDevice();

        LocalDevice[] embedded = ld.findEmbeddedDevices();
        assertEquals(embedded.length, 2);

        boolean haveOne = false, haveTwo = false;

        for (LocalDevice em : embedded) {
            if (em.getIdentity().getUdn().equals(ld.getEmbeddedDevices()[0].getIdentity().getUdn())) haveOne = true;
            if (em.getIdentity().getUdn().equals(ld.getEmbeddedDevices()[0].getEmbeddedDevices()[0].getIdentity().getUdn())) haveTwo = true;
        }

        assert haveOne;
        assert haveTwo;
    }

    @Test
    public void findDevicesWithUDN() throws Exception {
        LocalDevice ld = SampleData.createLocalDevice();

        LocalDevice ldOne = ld.findDevice(SampleDeviceRootLocal.getRootUDN());
        assertEquals(ldOne.getIdentity().getUdn(), SampleDeviceRootLocal.getRootUDN());

        LocalDevice ldTwo = ld.findDevice(SampleDeviceEmbeddedOneLocal.getEmbeddedOneUDN());
        assertEquals(ldTwo.getIdentity().getUdn(), SampleDeviceEmbeddedOneLocal.getEmbeddedOneUDN());

        LocalDevice ldThree = ld.findDevice(SampleDeviceEmbeddedTwoLocal.getEmbeddedTwoUDN());
        assertEquals(ldThree.getIdentity().getUdn(), SampleDeviceEmbeddedTwoLocal.getEmbeddedTwoUDN());

        RemoteDevice rd = SampleData.createRemoteDevice();

        RemoteDevice rdOne = rd.findDevice(SampleDeviceRootLocal.getRootUDN());
        assertEquals(rdOne.getIdentity().getUdn(), SampleDeviceRootLocal.getRootUDN());

        RemoteDevice rdTwo = rd.findDevice(SampleDeviceEmbeddedOneLocal.getEmbeddedOneUDN());
        assertEquals(rdTwo.getIdentity().getUdn(), SampleDeviceEmbeddedOneLocal.getEmbeddedOneUDN());

        RemoteDevice rdThree = rd.findDevice(SampleDeviceEmbeddedTwoLocal.getEmbeddedTwoUDN());
        assertEquals(rdThree.getIdentity().getUdn(), SampleDeviceEmbeddedTwoLocal.getEmbeddedTwoUDN());

    }

    @Test
    public void findDevicesWithDeviceType() throws Exception {
        LocalDevice ld = SampleData.createLocalDevice();

        LocalDevice[] ldOne = ld.findDevices(ld.getType());
        assertEquals(ldOne.length, 1);
        assertEquals(ldOne[0].getIdentity().getUdn(), SampleDeviceRootLocal.getRootUDN());

        LocalDevice[] ldTwo = ld.findDevices(ld.getEmbeddedDevices()[0].getType());
        assertEquals(ldTwo.length, 1);
        assertEquals(ldTwo[0].getIdentity().getUdn(), SampleDeviceEmbeddedOneLocal.getEmbeddedOneUDN());

        LocalDevice[] ldThree = ld.findDevices(ld.getEmbeddedDevices()[0].getEmbeddedDevices()[0].getType());
        assertEquals(ldThree.length, 1);
        assertEquals(ldThree[0].getIdentity().getUdn(), SampleDeviceEmbeddedTwoLocal.getEmbeddedTwoUDN());

        RemoteDevice rd = SampleData.createRemoteDevice();

        RemoteDevice[] rdOne = rd.findDevices(rd.getType());
        assertEquals(rdOne.length, 1);
        assertEquals(rdOne[0].getIdentity().getUdn(), SampleDeviceRootLocal.getRootUDN());

        RemoteDevice[] rdTwo = rd.findDevices(rd.getEmbeddedDevices()[0].getType());
        assertEquals(rdTwo.length, 1);
        assertEquals(rdTwo[0].getIdentity().getUdn(), SampleDeviceEmbeddedOneLocal.getEmbeddedOneUDN());

        RemoteDevice[] rdThree = rd.findDevices(rd.getEmbeddedDevices()[0].getEmbeddedDevices()[0].getType());
        assertEquals(rdThree.length, 1);
        assertEquals(rdThree[0].getIdentity().getUdn(), SampleDeviceEmbeddedTwoLocal.getEmbeddedTwoUDN());

    }

    @Test
    public void findDeviceServicesAll() throws Exception {
        LocalDevice ld = SampleData.createLocalDevice();

        DeviceService one = ld.getDeviceServices()[0];
        DeviceService two = ld.getEmbeddedDevices()[0].getDeviceServices()[0];
        DeviceService three  = ld.getEmbeddedDevices()[0].getEmbeddedDevices()[0].getDeviceServices()[0];

        DeviceService[] deviceServices = ld.findDeviceServices();

        boolean haveOne = false, haveTwo = false, haveThree = false;
        for (DeviceService deviceService : deviceServices) {
            if (deviceService.getServiceId().equals(one.getServiceId())) haveOne = true;
            if (deviceService.getServiceId().equals(two.getServiceId())) haveTwo = true;
            if (deviceService.getServiceId().equals(three.getServiceId())) haveThree = true;
        }
        assert haveOne;
        assert haveTwo;
        assert haveThree;
    }

    @Test
    public void findDeviceServicesType() throws Exception {
        LocalDevice ld = SampleData.createLocalDevice();

        DeviceService one = ld.getDeviceServices()[0];
        DeviceService two = ld.getEmbeddedDevices()[0].getDeviceServices()[0];
        DeviceService three  = ld.getEmbeddedDevices()[0].getEmbeddedDevices()[0].getDeviceServices()[0];

        DeviceService[] deviceServices = ld.findDeviceServices(one.getServiceType());
        assertEquals(deviceServices.length, 1);
        assertEquals(deviceServices[0].getServiceId(), one.getServiceId());

        deviceServices = ld.findDeviceServices(two.getServiceType());
        assertEquals(deviceServices.length, 1);
        assertEquals(deviceServices[0].getServiceId(), two.getServiceId());

        deviceServices = ld.findDeviceServices(three.getServiceType());
        assertEquals(deviceServices.length, 1);
        assertEquals(deviceServices[0].getServiceId(), three.getServiceId());
    }

    @Test
    public void findDeviceServicesId() throws Exception {
        LocalDevice ld = SampleData.createLocalDevice();

        DeviceService one = ld.getDeviceServices()[0];
        DeviceService two = ld.getEmbeddedDevices()[0].getDeviceServices()[0];
        DeviceService three  = ld.getEmbeddedDevices()[0].getEmbeddedDevices()[0].getDeviceServices()[0];

        DeviceService deviceService = ld.findDeviceService(one.getServiceId());
        assertEquals(deviceService.getServiceId(), one.getServiceId());

        deviceService = ld.findDeviceService(two.getServiceId());
        assertEquals(deviceService.getServiceId(), two.getServiceId());

        deviceService = ld.findDeviceService(three.getServiceId());
        assertEquals(deviceService.getServiceId(), three.getServiceId());
    }

    @Test
    public void findDeviceServicesFirst() throws Exception {
        LocalDevice ld = SampleData.createLocalDevice();

        DeviceService one = ld.getDeviceServices()[0];
        DeviceService two = ld.getEmbeddedDevices()[0].getDeviceServices()[0];
        DeviceService three  = ld.getEmbeddedDevices()[0].getEmbeddedDevices()[0].getDeviceServices()[0];

        DeviceService deviceService = ld.findFirstDeviceService(one.getServiceType());
        assertEquals(deviceService.getServiceId(), one.getServiceId());

        deviceService = ld.findFirstDeviceService(two.getServiceType());
        assertEquals(deviceService.getServiceId(), two.getServiceId());

        deviceService = ld.findFirstDeviceService(three.getServiceType());
        assertEquals(deviceService.getServiceId(), three.getServiceId());
    }

    @Test
    public void findServiceTypes() throws Exception {
        LocalDevice ld = SampleData.createLocalDevice();

        ServiceType[] svcTypes = ld.findServiceTypes();
        assertEquals(svcTypes.length, 3);

        boolean haveOne = false, haveTwo = false, haveThree = false;

        for (ServiceType svcType : svcTypes) {
            if (svcType.equals(ld.getDeviceServices()[0].getServiceType())) haveOne = true;
            if (svcType.equals(ld.getEmbeddedDevices()[0].getDeviceServices()[0].getServiceType())) haveTwo = true;
            if (svcType.equals(ld.getEmbeddedDevices()[0].getEmbeddedDevices()[0].getDeviceServices()[0].getServiceType())) haveThree = true;
        }

        assert haveOne;
        assert haveTwo;
        assert haveThree;

    }
}
