<commit_before>/**
 * Copyright (c) 2010-2020 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.binding.dwdunwetter.internal.handler;

import static org.openhab.binding.dwdunwetter.internal.DwdUnwetterBindingConstants.*;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
import org.openhab.binding.dwdunwetter.internal.config.DwdUnwetterConfiguration;
import org.openhab.binding.dwdunwetter.internal.data.DwdWarningsData;
import org.openhab.core.library.types.DateTimeType;
import org.openhab.core.library.types.OnOffType;
import org.openhab.core.thing.Channel;
import org.openhab.core.thing.ChannelUID;
import org.openhab.core.thing.Thing;
import org.openhab.core.thing.ThingStatus;
import org.openhab.core.thing.binding.BaseThingHandler;
import org.openhab.core.thing.binding.ThingHandlerCallback;
import org.openhab.core.thing.binding.builder.ThingBuilder;
import org.openhab.core.thing.type.ChannelTypeUID;
import org.openhab.core.thing.util.ThingHandlerHelper;
import org.openhab.core.types.Command;
import org.openhab.core.types.RefreshType;
import org.openhab.core.types.State;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * The {@link DwdUnwetterHandler} is responsible for handling commands, which are sent to one of the channels.
 *
 * @author <NAME> - Initial contribution
 */
@NonNullByDefault
public class DwdUnwetterHandler extends BaseThingHandler {

    private final Logger logger = LoggerFactory.getLogger(DwdUnwetterHandler.class);

    private @Nullable ScheduledFuture<?> refreshJob;
    private int warningCount;
    private @Nullable DwdWarningsData data;

    private boolean inRefresh;

    public DwdUnwetterHandler(Thing thing) {
        super(thing);
    }

    @Override
    public void handleCommand(ChannelUID channelUID, Command command) {
        if (command instanceof RefreshType) {
            scheduler.submit(this::refresh);
        }
    }

    /**
     * Refreshes the Warning Data.
     *
     * The Switch Channel is switched to ON only after all other Channels are updated.
     * The Switch Channel is switched to OFF before all other Channels are updated.
     */
    private void refresh() {
        if (inRefresh) {
            logger.trace("Already refreshing. Ignoring refresh request.");
            return;
        }

        if (!ThingHandlerHelper.isHandlerInitialized(getThing())) {
            logger.debug("Unable to refresh. Thing status is '{}'", getThing().getStatus());
            return;
        }

        final DwdWarningsData warningsData = data;
        if (warningsData == null) {
            logger.debug("Unable to refresh. No data to use.");
            return;
        }

        inRefresh = true;

        boolean refreshSucceeded = warningsData.refresh();
        if (!refreshSucceeded) {
            logger.debug("Failed to retrieve new data from the server.");
            inRefresh = false;
            return;
        }

        updateStatus(ThingStatus.ONLINE);

        updateState(getChannelUuid(CHANNEL_LAST_UPDATED), new DateTimeType());

        for (int i = 0; i < warningCount; i++) {
            State warning = warningsData.getWarning(i);
            if (warning == OnOffType.OFF) {
                updateState(getChannelUuid(CHANNEL_WARNING, i), warning);
            }
            updateState(getChannelUuid(CHANNEL_SEVERITY, i), warningsData.getSeverity(i));
            updateState(getChannelUuid(CHANNEL_DESCRIPTION, i), warningsData.getDescription(i));
            updateState(getChannelUuid(CHANNEL_EFFECTIVE, i), warningsData.getEffective(i));
            updateState(getChannelUuid(CHANNEL_EXPIRES, i), warningsData.getExpires(i));
            updateState(getChannelUuid(CHANNEL_ONSET, i), warningsData.getOnset(i));
            updateState(getChannelUuid(CHANNEL_EVENT, i), warningsData.getEvent(i));
            updateState(getChannelUuid(CHANNEL_HEADLINE, i), warningsData.getHeadline(i));
            updateState(getChannelUuid(CHANNEL_ALTITUDE, i), warningsData.getAltitude(i));
            updateState(getChannelUuid(CHANNEL_CEILING, i), warningsData.getCeiling(i));
            updateState(getChannelUuid(CHANNEL_INSTRUCTION, i), warningsData.getInstruction(i));
            updateState(getChannelUuid(CHANNEL_URGENCY, i), warningsData.getUrgency(i));
            if (warning == OnOffType.ON) {
                updateState(getChannelUuid(CHANNEL_WARNING, i), warning);
            }
            if (warningsData.isNew(i)) {
                triggerChannel(getChannelUuid(CHANNEL_UPDATED, i), "NEW");
            }
        }

        warningsData.updateCache();
        inRefresh = false;
    }

    @Override
    public void initialize() {
        logger.debug("Start initializing!");
        updateStatus(ThingStatus.UNKNOWN);

        DwdUnwetterConfiguration config = getConfigAs(DwdUnwetterConfiguration.class);
        int newWarningCount = config.warningCount;

        if (warningCount != newWarningCount) {
            List<Channel> toBeAddedChannels = new ArrayList<>();<commit_msg>[dwdunwetter] Fixed channel update (#9594)<commit_after>/**
 * Copyright (c) 2010-2020 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.binding.dwdunwetter.internal.handler;

import static org.openhab.binding.dwdunwetter.internal.DwdUnwetterBindingConstants.*;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
import org.openhab.binding.dwdunwetter.internal.config.DwdUnwetterConfiguration;
import org.openhab.binding.dwdunwetter.internal.data.DwdWarningsData;
import org.openhab.core.library.types.DateTimeType;
import org.openhab.core.library.types.OnOffType;
import org.openhab.core.thing.Channel;
import org.openhab.core.thing.ChannelUID;
import org.openhab.core.thing.Thing;
import org.openhab.core.thing.ThingStatus;
import org.openhab.core.thing.binding.BaseThingHandler;
import org.openhab.core.thing.binding.ThingHandlerCallback;
import org.openhab.core.thing.binding.builder.ThingBuilder;
import org.openhab.core.thing.type.ChannelTypeUID;
import org.openhab.core.thing.util.ThingHandlerHelper;
import org.openhab.core.types.Command;
import org.openhab.core.types.RefreshType;
import org.openhab.core.types.State;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * The {@link DwdUnwetterHandler} is responsible for handling commands, which are sent to one of the channels.
 *
 * @author <NAME> - Initial contribution
 */
@NonNullByDefault
public class DwdUnwetterHandler extends BaseThingHandler {

    private final Logger logger = LoggerFactory.getLogger(DwdUnwetterHandler.class);

    private @Nullable ScheduledFuture<?> refreshJob;
    private int warningCount;
    private @Nullable DwdWarningsData data;

    private boolean inRefresh;

    public DwdUnwetterHandler(Thing thing) {
        super(thing);
    }

    @Override
    public void handleCommand(ChannelUID channelUID, Command command) {
        if (command instanceof RefreshType) {
            scheduler.submit(this::refresh);
        }
    }

    /**
     * Refreshes the Warning Data.
     *
     * The Switch Channel is switched to ON only after all other Channels are updated.
     * The Switch Channel is switched to OFF before all other Channels are updated.
     */
    private void refresh() {
        if (inRefresh) {
            logger.trace("Already refreshing. Ignoring refresh request.");
            return;
        }

        if (!ThingHandlerHelper.isHandlerInitialized(getThing())) {
            logger.debug("Unable to refresh. Thing status is '{}'", getThing().getStatus());
            return;
        }

        final DwdWarningsData warningsData = data;
        if (warningsData == null) {
            logger.debug("Unable to refresh. No data to use.");
            return;
        }

        inRefresh = true;

        boolean refreshSucceeded = warningsData.refresh();
        if (!refreshSucceeded) {
            logger.debug("Failed to retrieve new data from the server.");
            inRefresh = false;
            return;
        }

        updateStatus(ThingStatus.ONLINE);

        updateState(getChannelUuid(CHANNEL_LAST_UPDATED), new DateTimeType());

        for (int i = 0; i < warningCount; i++) {
            State warning = warningsData.getWarning(i);
            int warningNumber = i + 1;
            if (warning == OnOffType.OFF) {
                updateState(getChannelUuid(CHANNEL_WARNING, warningNumber), warning);
            }
            updateState(getChannelUuid(CHANNEL_SEVERITY, warningNumber), warningsData.getSeverity(i));
            updateState(getChannelUuid(CHANNEL_DESCRIPTION, warningNumber), warningsData.getDescription(i));
            updateState(getChannelUuid(CHANNEL_EFFECTIVE, warningNumber), warningsData.getEffective(i));
            updateState(getChannelUuid(CHANNEL_EXPIRES, warningNumber), warningsData.getExpires(i));
            updateState(getChannelUuid(CHANNEL_ONSET, warningNumber), warningsData.getOnset(i));
            updateState(getChannelUuid(CHANNEL_EVENT, warningNumber), warningsData.getEvent(i));
            updateState(getChannelUuid(CHANNEL_HEADLINE, warningNumber), warningsData.getHeadline(i));
            updateState(getChannelUuid(CHANNEL_ALTITUDE, warningNumber), warningsData.getAltitude(i));
            updateState(getChannelUuid(CHANNEL_CEILING, warningNumber), warningsData.getCeiling(i));
            updateState(getChannelUuid(CHANNEL_INSTRUCTION, warningNumber), warningsData.getInstruction(i));
            updateState(getChannelUuid(CHANNEL_URGENCY, warningNumber), warningsData.getUrgency(i));
            if (warning == OnOffType.ON) {
                updateState(getChannelUuid(CHANNEL_WARNING, warningNumber), warning);
            }
            if (warningsData.isNew(i)) {
                triggerChannel(getChannelUuid(CHANNEL_UPDATED, warningNumber), "NEW");
            }
        }

        warningsData.updateCache();
        inRefresh = false;
    }

    @Override
    public void initialize() {
        logger.debug("Start initializing!");
        updateStatus(ThingStatus.UNKNOWN);

        DwdUnwetterConfiguration config = getConfigAs(DwdUnwetterConfiguration.class);
        int newWarningCount = config.warningCount;

        if (warningCount != newWarningCount) {
            List<Channel> toBeAddedChannels = new ArrayList<>();
{'fraction_non_alphanumeric': 0.09864125639668254, 'fraction_numerical': 0.003440974060349391, 'mean_word_length': 3.3512476007677545, 'pattern_counts': {'":': 0, '<': 13, '<?xml version=': 0, '>': 11, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5716966', 'n_tokens_mistral': 3238, 'n_tokens_neox': 3157, 'n_words': 673}