/*
 * Copyright (c) 2010-2025 Contributors to the openHAB project
 *
 * See the NOTICE file(s) distributed with this work for additional
 * information.
 *
 * This program and the accompanying materials are made available under the
 * terms of the Eclipse Public License 2.0 which is available at
 * http://www.eclipse.org/legal/epl-2.0
 *
 * SPDX-License-Identifier: EPL-2.0
 */
package org.openhab.core.thing.binding.builder;

import static org.hamcrest.CoreMatchers.*;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.collection.IsCollectionWithSize.hasSize;
import static org.openhab.core.thing.DefaultSystemChannelTypeProvider.SYSTEM_OUTDOOR_TEMPERATURE;

import java.util.Map;

import org.eclipse.jdt.annotation.NonNullByDefault;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.openhab.core.library.CoreItemFactory;
import org.openhab.core.thing.Channel;
import org.openhab.core.thing.ChannelUID;
import org.openhab.core.thing.ThingTypeUID;
import org.openhab.core.thing.ThingUID;
import org.openhab.core.thing.type.ChannelKind;
import org.openhab.core.thing.type.ThingType;
import org.openhab.core.thing.type.ThingTypeBuilder;

/**
 * Tests the {@link ChannelBuilder}.
 *
 * @author Christoph Weitkamp - Initial contribution
 */
@NonNullByDefault
public class ChannelBuilderTest {

    private static final String KEY1 = "key1";
    private static final String KEY2 = "key2";
    private static final String VALUE1 = "value1";
    private static final String VALUE2 = "value2";

    private static final Map<String, String> PROPERTIES = Map.of(KEY1, VALUE1, KEY2, VALUE2);

    private @NonNullByDefault({}) ChannelBuilder builder;
    private @NonNullByDefault({}) Channel channel;

    @BeforeEach
    public void setup() {
        ThingType thingType = ThingTypeBuilder.instance(new ThingTypeUID("bindingId", "thingTypeId"), "thingLabel")
                .build();
        ChannelUID channelUID = new ChannelUID(new ThingUID(thingType.getUID(), "thingId"), "temperature");
        builder = ChannelBuilder.create(channelUID, SYSTEM_OUTDOOR_TEMPERATURE.getItemType()).withLabel("Test")
                .withDescription("My test channel").withType(SYSTEM_OUTDOOR_TEMPERATURE.getUID())
                .withProperties(PROPERTIES);
        channel = builder.build();
    }

    @Test
    public void testChannelBuilder() {
        assertThat(channel.getAcceptedItemType(), is(SYSTEM_OUTDOOR_TEMPERATURE.getItemType()));
        assertThat(channel.getChannelTypeUID(), is(SYSTEM_OUTDOOR_TEMPERATURE.getUID()));
        assertThat(channel.getDefaultTags(), hasSize(0));
        assertThat(channel.getDescription(), is("My test channel"));
        assertThat(channel.getKind(), is(ChannelKind.STATE));
        assertThat(channel.getLabel(), is("Test"));
        assertThat(channel.getProperties().size(), is(2));
        assertThat(channel.getProperties().get(KEY1), is(VALUE1));
        assertThat(channel.getProperties().get(KEY2), is(VALUE2));
    }

    @Test
    public void testChannelBuilderFromChannel() {
        Channel otherChannel = ChannelBuilder.create(channel).build();

        assertThat(otherChannel.getAcceptedItemType(), is(channel.getAcceptedItemType()));
        assertThat(otherChannel.getChannelTypeUID(), is(channel.getChannelTypeUID()));
        assertThat(otherChannel.getConfiguration(), is(channel.getConfiguration()));
        assertThat(otherChannel.getDefaultTags(), hasSize(channel.getDefaultTags().size()));
        assertThat(otherChannel.getDescription(), is(channel.getDescription()));
        assertThat(otherChannel.getKind(), is(channel.getKind()));
        assertThat(otherChannel.getLabel(), is(channel.getLabel()));
        assertThat(otherChannel.getAutoUpdatePolicy(), is(channel.getAutoUpdatePolicy()));
        assertThat(otherChannel.getProperties().size(), is(channel.getProperties().size()));
        assertThat(otherChannel.getProperties().get(KEY1), is(channel.getProperties().get(KEY1)));
        assertThat(otherChannel.getProperties().get(KEY2), is(channel.getProperties().get(KEY2)));
        assertThat(otherChannel.getUID(), is(channel.getUID()));
    }

    @Test
    public void subsequentBuildsCreateIndependentChannels() {
        Channel otherChannel = builder.withLabel("Second Test").withDescription("My second test channel")
                .withAcceptedItemType(CoreItemFactory.NUMBER).withProperties(Map.of()).build();

        assertThat(otherChannel.getDescription(), is(not(channel.getDescription())));
        assertThat(otherChannel.getLabel(), is(not(channel.getLabel())));
        assertThat(otherChannel.getAcceptedItemType(), is(not(channel.getAcceptedItemType())));
        assertThat(otherChannel.getProperties().size(), is(not(channel.getProperties().size())));
    }
}
