/*
 * Copyright (C) 2010 Teleal GmbH, Switzerland
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as
 * published by the Free Software Foundation, either version 3 of the
 * License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

package org.teleal.cling.test.data;

import org.teleal.cling.model.Resource;
import org.teleal.cling.model.meta.Device;
import org.teleal.cling.model.meta.DeviceDetails;
import org.teleal.cling.model.meta.DeviceIdentity;
import org.teleal.cling.model.meta.DeviceService;
import org.teleal.cling.model.meta.Icon;
import org.teleal.cling.model.meta.ManufacturerDetails;
import org.teleal.cling.model.meta.ModelDetails;
import org.teleal.cling.model.meta.RemoteDevice;
import org.teleal.cling.model.meta.Service;
import org.teleal.cling.model.types.DeviceType;
import org.teleal.cling.model.types.ServiceId;
import org.teleal.cling.model.types.ServiceType;
import org.teleal.cling.model.types.UDADeviceType;
import org.teleal.cling.model.types.UDAServiceId;
import org.teleal.cling.model.types.UDAServiceType;
import org.teleal.cling.model.types.UDN;
import org.teleal.common.util.URIUtil;

import java.net.URI;
import java.net.URL;

import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertTrue;

/**
 * @author Christian Bauer
 */
public class SampleDeviceRoot extends SampleDevice {

    public SampleDeviceRoot(DeviceIdentity identity, Service service, Device[] embeddedDevices) {
        super(identity, service, embeddedDevices);
    }

    @Override
    public DeviceType getDeviceType() {
        return new UDADeviceType("MY-DEVICE-TYPE", 1);
    }

    @Override
    public DeviceDetails getDeviceDetails() {
        return new DeviceDetails(
                "My Testdevice",
                new ManufacturerDetails("TELEAL", "http://www.teleal.org/"),
                new ModelDetails("MYMODEL", "TEST Device", "ONE", "http://www.teleal.org/foo"),
                "000da201238c",
                "100000000001",
                "http://www.teleal.org/some_user_interface/");
    }

    @Override
    public Icon[] getIcons() {
        return new Icon[]{
                new Icon("image/png", 32, 32, 8, "icon.png"),
                new Icon("image/png", 32, 32, 8, "icon2.png")
        };
    }

    @Override
    public DeviceService[] getDeviceServices() {
        return new DeviceService[]{
                new DeviceService(
                        getServiceOneType(),
                        getServiceOneId(),
                        getServiceOneDescriptorURI(),
                        URI.create("service/upnp-org/MY-SERVICE-123/control"),
                        URI.create("service/upnp-org/MY-SERVICE-123/events"),
                        getService()
                )
        };
    }

    public static UDN getRootUDN() {
        return new UDN("MY-DEVICE-123");
    }

    public static URI getDeviceDescriptorURI() {
        return URI.create("/upnp/device/MY-DEVICE-123/desc.xml");
    }

    public static URL getDeviceDescriptorURL() {
        return URIUtil.createAbsoluteURL(SampleData.getLocalBaseURL(), getDeviceDescriptorURI());
    }

    public static ServiceId getServiceOneId() {
        return new UDAServiceId("MY-SERVICE-123");
    }

    public static ServiceType getServiceOneType() {
        return new UDAServiceType("MY-SERVICE-TYPE-ONE", 1);
    }

    public static URI getServiceOneDescriptorURI() {
        return URI.create("service/upnp-org/MY-SERVICE-123/desc.xml");
    }

    public static URL getServiceOneDescriptorURL() {
        return URIUtil.createAbsoluteURL(getDeviceDescriptorURL(), getServiceOneDescriptorURI());
    }

    public static void assertMatch(Device a, Device b) {
        assertTrue(a.isRoot());
        assertDeviceMatch(a, b);
    }

    public static void assertLocalResourcesMatch(RemoteDevice d) {
        assertEquals(
                d.getLocalResource(URI.create("/upnp/device/MY-DEVICE-123/service/upnp-org/MY-SERVICE-123/events/callback.xml")).getType(),
                Resource.Type.EVENT_CALLBACK
        );

        assertEquals(
                d.getLocalResource(URI.create("/upnp/device/MY-DEVICE-123/embedded/MY-DEVICE-456/service/upnp-org/MY-SERVICE-456/events/callback.xml")).getType(),
                Resource.Type.EVENT_CALLBACK
        );
        assertEquals(
                d.getLocalResource(URI.create("/upnp/device/MY-DEVICE-123/embedded/MY-DEVICE-456/embedded/MY-DEVICE-789/service/upnp-org/MY-SERVICE-789/events/callback.xml")).getType(),
                Resource.Type.EVENT_CALLBACK
        );
    }

    protected static void assertDeviceMatch(Device a, Device b) {

        assert (a.validate().size() == 0);
        assert (b.validate().size() == 0);

        assertEquals(a, b); // Checking equals() method
        assertEquals(a.getIdentity().getUdn(), b.getIdentity().getUdn());
        assertEquals(a.getVersion().getMajor(), b.getVersion().getMajor());
        assertEquals(a.getVersion().getMinor(), b.getVersion().getMinor());
        assertEquals(a.getType(), b.getType());
        assertEquals(a.getDetails().getFriendlyName(), b.getDetails().getFriendlyName());
        assertEquals(a.getDetails().getManufacturerDetails().getManufacturer(), b.getDetails().getManufacturerDetails().getManufacturer());
        assertEquals(a.getDetails().getManufacturerDetails().getManufacturerURI(), b.getDetails().getManufacturerDetails().getManufacturerURI());
        assertEquals(a.getDetails().getModelDetails().getModelDescription(), b.getDetails().getModelDetails().getModelDescription());
        assertEquals(a.getDetails().getModelDetails().getModelName(), b.getDetails().getModelDetails().getModelName());
        assertEquals(a.getDetails().getModelDetails().getModelNumber(), b.getDetails().getModelDetails().getModelNumber());
        assertEquals(a.getDetails().getModelDetails().getModelURI(), b.getDetails().getModelDetails().getModelURI());
        assertEquals(a.getDetails().getSerialNumber(), b.getDetails().getSerialNumber());
        assertEquals(a.getDetails().getUpc(), b.getDetails().getUpc());
        assertEquals(a.getDetails().getPresentationURI(), b.getDetails().getPresentationURI());

        assertEquals(a.getIcons() != null, b.getIcons() != null);
        if (a.getIcons() != null) {
            assertEquals(a.getIcons().length, b.getIcons().length);
            for (int i = 0; i < a.getIcons().length; i++) {
                assertEquals(a.getIcons()[i].getDevice(), a);
                assertEquals(b.getIcons()[i].getDevice(), b);
                assertEquals(a.getIcons()[i].getUri(), b.getIcons()[i].getUri());
                assertEquals(a.getIcons()[i].getMimeType(), b.getIcons()[i].getMimeType());
                assertEquals(a.getIcons()[i].getWidth(), b.getIcons()[i].getWidth());
                assertEquals(a.getIcons()[i].getHeight(), b.getIcons()[i].getHeight());
                assertEquals(a.getIcons()[i].getDepth(), b.getIcons()[i].getDepth());
            }
        }

        assertEquals(a.hasDeviceServices(), b.hasDeviceServices());
        if (a.getDeviceServices() != null) {
            assertEquals(a.getDeviceServices().length, b.getDeviceServices().length);
            for (int i = 0; i < a.getDeviceServices().length; i++) {
                DeviceService deviceService = a.getDeviceServices()[i];
                assertEquals(deviceService.getServiceType(), b.getDeviceServices()[i].getServiceType());
                assertEquals(deviceService.getServiceId(), b.getDeviceServices()[i].getServiceId());
                assertEquals(
                        deviceService.getEventSubscriptionURI(),
                        b.getDeviceServices()[i].getEventSubscriptionURI()
                );
                assertEquals(
                        deviceService.getControlURI(),
                        b.getDeviceServices()[i].getControlURI()
                );
                assertEquals(
                        deviceService.getDescriptorURI(),
                        b.getDeviceServices()[i].getDescriptorURI()
                );
            }
        }

        assertEquals(a.hasEmbeddedDevices(), b.hasEmbeddedDevices());
        if (a.getEmbeddedDevices() != null) {
            assertEquals(a.getEmbeddedDevices().length, b.getEmbeddedDevices().length);
            for (int i = 0; i < a.getEmbeddedDevices().length; i++) {
                Device aEmbedded = a.getEmbeddedDevices()[i];
                assertDeviceMatch(aEmbedded, b.getEmbeddedDevices()[i]);

            }
        }

    }


}