/**
 * 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
 */

 /* ***********************************************************
 * This file was automatically generated on 2022-01-03.      *
 *                                                           *
 * openHAB Bindings Version 2.0.0                            *
 *                                                           *
 * If you have a bugfix for this file and want to commit it, *
 * please fix the bug in the generator. You can find a link  *
 * to the generators git repository on tinkerforge.com       *
 *************************************************************/

package org.openhab.binding.tinkerforge.internal.device;

import java.net.URI;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.function.BiConsumer;
import java.util.function.Consumer;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;
import org.eclipse.smarthome.config.core.Configuration;
import org.eclipse.smarthome.config.core.ConfigDescription;
import org.eclipse.smarthome.config.core.ConfigDescriptionBuilder;
import org.eclipse.smarthome.config.core.ConfigDescriptionParameter.Type;
import org.eclipse.smarthome.config.core.ConfigDescriptionParameterBuilder;
import org.eclipse.smarthome.config.core.ConfigDescriptionParameterGroup;
import org.eclipse.smarthome.config.core.ParameterOption;
import org.eclipse.smarthome.core.types.State;
import org.eclipse.smarthome.core.types.StateOption;
import org.eclipse.smarthome.core.types.Command;
import org.eclipse.smarthome.core.types.CommandDescriptionBuilder;
import org.eclipse.smarthome.core.types.CommandOption;
import org.eclipse.smarthome.core.thing.ChannelUID;
import org.eclipse.smarthome.core.thing.ThingStatus;
import org.eclipse.smarthome.core.thing.ThingTypeUID;
import org.eclipse.smarthome.core.thing.binding.BaseThingHandler;
import org.eclipse.smarthome.core.thing.type.ChannelDefinitionBuilder;
import org.eclipse.smarthome.core.thing.type.ChannelType;
import org.eclipse.smarthome.core.thing.type.ChannelTypeBuilder;
import org.eclipse.smarthome.core.thing.type.ChannelTypeUID;
import org.eclipse.smarthome.core.types.RefreshType;
import org.eclipse.smarthome.core.thing.type.ThingType;
import org.eclipse.smarthome.core.thing.type.ThingTypeBuilder;
import org.eclipse.smarthome.core.types.StateDescriptionFragmentBuilder;
import org.openhab.binding.tinkerforge.internal.TinkerforgeBindingConstants;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.eclipse.smarthome.core.library.types.DecimalType;
import org.eclipse.smarthome.core.library.types.QuantityType;
import org.eclipse.smarthome.core.library.unit.MetricPrefix;
import org.eclipse.smarthome.core.library.unit.SIUnits;
import org.eclipse.smarthome.core.library.unit.SmartHomeUnits;
import org.eclipse.smarthome.core.thing.CommonTriggerEvents;
import org.eclipse.smarthome.core.library.types.StringType;

import com.tinkerforge.BrickletLCD128x64;
import com.tinkerforge.IPConnection;
import com.tinkerforge.TinkerforgeException;

import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;

/**
 * Wraps the Java Bindings of the LCD 128x64 Bricklet.
 * @author Erik Fleckstein - Initial contribution
 */
@NonNullByDefault
public class BrickletLCD128x64Wrapper extends BrickletLCD128x64 implements CoMCUFlashable, DeviceWrapper {
    public static final DeviceInfo DEVICE_INFO = new DeviceInfo(BrickletLCD128x64.DEVICE_DISPLAY_NAME, "brickletlcd128x64", BrickletLCD128x64.DEVICE_IDENTIFIER, BrickletLCD128x64Wrapper.class, BrickletLCD128x64Actions.class, "2.0.2", true);

    public BrickletLCD128x64Wrapper(String uid, IPConnection ipcon) {
        super(uid, ipcon);
    }

    private List<ScheduledFuture<?>> manualChannelUpdates = new ArrayList<>();
    private List<ListenerReg<?>> listenerRegs = new ArrayList<>();

    public void cancelManualUpdates() {
        manualChannelUpdates.forEach(f -> f.cancel(true));
    }

    public <T> T reg(T listener, Consumer<T> toRemove) {
        listenerRegs.add(new ListenerReg<T>(listener, toRemove));
        return listener;
    }

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

    @Override
    public void initialize(org.eclipse.smarthome.config.core.Configuration config, Function<String, org.eclipse.smarthome.config.core.Configuration> getChannelConfigFn, BiConsumer<String, org.eclipse.smarthome.core.types.State> updateStateFn, BiConsumer<String, String> triggerChannelFn, ScheduledExecutorService scheduler, BaseThingHandler handler) throws TinkerforgeException {
        this.setResponseExpectedAll(true);
        BrickletLCD128x64Config cfg = (BrickletLCD128x64Config) config.as(BrickletLCD128x64Config.class);
        this.addTouchPositionListener(this.reg((pressure, x, y, age) -> {if(true) {triggerChannelFn.accept("BrickletLCD128x64TouchPosition", transformBrickletLCD128x64TouchPositionCallback0(pressure, x, y, age, cfg));}}, this::removeTouchPositionListener));
		this.addTouchGestureListener(this.reg((gesture, duration, pressureMax, xStart, yStart, xEnd, yEnd, age) -> {if(true) {triggerChannelFn.accept("BrickletLCD128x64TouchGesture", transformBrickletLCD128x64TouchGestureCallback0(gesture, duration, pressureMax, xStart, yStart, xEnd, yEnd, age, cfg));}}, this::removeTouchGestureListener));
		this.addGUITabSelectedListener(this.reg((index) -> {if(true) {updateStateFn.accept("BrickletLCD128x64SelectedGUITab", transformBrickletLCD128x64SelectedGUITabCallback0(index, cfg));}}, this::removeGUITabSelectedListener));
		this.addGUIButtonPressedListener(this.reg((index, pressed) -> {if(index ==  0) {triggerChannelFn.accept("BrickletLCD128x64GUIButton0", transformBrickletLCD128x64GUIButton0Callback0(index, pressed, cfg));}}, this::removeGUIButtonPressedListener));
		this.addGUIButtonPressedListener(this.reg((index, pressed) -> {if(index ==  1) {triggerChannelFn.accept("BrickletLCD128x64GUIButton1", transformBrickletLCD128x64GUIButton1Callback0(index, pressed, cfg));}}, this::removeGUIButtonPressedListener));
		this.addGUIButtonPressedListener(this.reg((index, pressed) -> {if(index ==  2) {triggerChannelFn.accept("BrickletLCD128x64GUIButton2", transformBrickletLCD128x64GUIButton2Callback0(index, pressed, cfg));}}, this::removeGUIButtonPressedListener));
		this.addGUIButtonPressedListener(this.reg((index, pressed) -> {if(index ==  3) {triggerChannelFn.accept("BrickletLCD128x64GUIButton3", transformBrickletLCD128x64GUIButton3Callback0(index, pressed, cfg));}}, this::removeGUIButtonPressedListener));
		this.addGUIButtonPressedListener(this.reg((index, pressed) -> {if(index ==  4) {triggerChannelFn.accept("BrickletLCD128x64GUIButton4", transformBrickletLCD128x64GUIButton4Callback0(index, pressed, cfg));}}, this::removeGUIButtonPressedListener));
		this.addGUIButtonPressedListener(this.reg((index, pressed) -> {if(index ==  5) {triggerChannelFn.accept("BrickletLCD128x64GUIButton5", transformBrickletLCD128x64GUIButton5Callback0(index, pressed, cfg));}}, this::removeGUIButtonPressedListener));
		this.addGUIButtonPressedListener(this.reg((index, pressed) -> {if(index ==  6) {triggerChannelFn.accept("BrickletLCD128x64GUIButton6", transformBrickletLCD128x64GUIButton6Callback0(index, pressed, cfg));}}, this::removeGUIButtonPressedListener));
		this.addGUIButtonPressedListener(this.reg((index, pressed) -> {if(index ==  7) {triggerChannelFn.accept("BrickletLCD128x64GUIButton7", transformBrickletLCD128x64GUIButton7Callback0(index, pressed, cfg));}}, this::removeGUIButtonPressedListener));
		this.addGUIButtonPressedListener(this.reg((index, pressed) -> {if(index ==  8) {triggerChannelFn.accept("BrickletLCD128x64GUIButton8", transformBrickletLCD128x64GUIButton8Callback0(index, pressed, cfg));}}, this::removeGUIButtonPressedListener));
		this.addGUIButtonPressedListener(this.reg((index, pressed) -> {if(index ==  9) {triggerChannelFn.accept("BrickletLCD128x64GUIButton9", transformBrickletLCD128x64GUIButton9Callback0(index, pressed, cfg));}}, this::removeGUIButtonPressedListener));
		this.addGUIButtonPressedListener(this.reg((index, pressed) -> {if(index ==  10) {triggerChannelFn.accept("BrickletLCD128x64GUIButton10", transformBrickletLCD128x64GUIButton10Callback0(index, pressed, cfg));}}, this::removeGUIButtonPressedListener));
		this.addGUIButtonPressedListener(this.reg((index, pressed) -> {if(index ==  11) {triggerChannelFn.accept("BrickletLCD128x64GUIButton11", transformBrickletLCD128x64GUIButton11Callback0(index, pressed, cfg));}}, this::removeGUIButtonPressedListener));
		this.addGUISliderValueListener(this.reg((index, value) -> {if(index ==  0) {updateStateFn.accept("BrickletLCD128x64GUISlider0", transformBrickletLCD128x64GUISlider0Callback0(index, value, cfg));}}, this::removeGUISliderValueListener));
		this.addGUISliderValueListener(this.reg((index, value) -> {if(index ==  1) {updateStateFn.accept("BrickletLCD128x64GUISlider1", transformBrickletLCD128x64GUISlider1Callback0(index, value, cfg));}}, this::removeGUISliderValueListener));
		this.addGUISliderValueListener(this.reg((index, value) -> {if(index ==  2) {updateStateFn.accept("BrickletLCD128x64GUISlider2", transformBrickletLCD128x64GUISlider2Callback0(index, value, cfg));}}, this::removeGUISliderValueListener));
		this.addGUISliderValueListener(this.reg((index, value) -> {if(index ==  3) {updateStateFn.accept("BrickletLCD128x64GUISlider3", transformBrickletLCD128x64GUISlider3Callback0(index, value, cfg));}}, this::removeGUISliderValueListener));
		this.addGUISliderValueListener(this.reg((index, value) -> {if(index ==  4) {updateStateFn.accept("BrickletLCD128x64GUISlider4", transformBrickletLCD128x64GUISlider4Callback0(index, value, cfg));}}, this::removeGUISliderValueListener));
		this.addGUISliderValueListener(this.reg((index, value) -> {if(index ==  5) {updateStateFn.accept("BrickletLCD128x64GUISlider5", transformBrickletLCD128x64GUISlider5Callback0(index, value, cfg));}}, this::removeGUISliderValueListener));
        this.setDisplayConfiguration(cfg.contrast, cfg.defaultBacklightIntensity, cfg.invert, cfg.automaticDraw);
		    this.setTouchLEDConfig(cfg.touchLEDConfig);
		    this.setGUIButtonPressedCallbackConfiguration(cfg.guiButtonUpdateInterval.longValue(), true);
		    this.setGUISliderValueCallbackConfiguration(cfg.guiSliderUpdateInterval.longValue(), true);
		this.setStatusLEDConfig(cfg.statusLEDConfig);
		{
		this.setTouchPositionCallbackConfiguration(cfg.touchPositionUpdateInterval, true);
		}
		{
		this.setTouchGestureCallbackConfiguration(cfg.touchGestureUpdateInterval, true);
		}
		{
		BrickletLCD128x64GUITabSelectedConfig channelCfg = getChannelConfigFn.apply("BrickletLCD128x64SelectedGUITab").as(BrickletLCD128x64GUITabSelectedConfig.class);
		this.setGUITabSelectedCallbackConfiguration(channelCfg.updateInterval.longValue(), true);
		}
    }

    @Override
    public void dispose(org.eclipse.smarthome.config.core.Configuration config) throws TinkerforgeException {
        listenerRegs.forEach(ListenerReg::deregister);

        
        this.setTouchPositionCallbackConfiguration(0, true);
		this.setTouchGestureCallbackConfiguration(0, true);
		this.setGUITabSelectedCallbackConfiguration(0, true);
		
    }

    @Override
    public List<String> getEnabledChannels(org.eclipse.smarthome.config.core.Configuration config) throws TinkerforgeException{
        BrickletLCD128x64Config cfg = (BrickletLCD128x64Config) config.as(BrickletLCD128x64Config.class);
List<String> result = new ArrayList<String>();
        result.add("BrickletLCD128x64Text");
		result.add("BrickletLCD128x64ClearDisplay");
		if (cfg.automaticDraw) {
                result.add("BrickletLCD128x64DrawBufferedFrame");
            }
		result.add("BrickletLCD128x64Backlight");
		result.add("BrickletLCD128x64TouchPosition");
		result.add("BrickletLCD128x64TouchGesture");
		result.add("BrickletLCD128x64SelectedGUITab");
		result.add("BrickletLCD128x64GUIButton0");
		result.add("BrickletLCD128x64GUIButton1");
		result.add("BrickletLCD128x64GUIButton2");
		result.add("BrickletLCD128x64GUIButton3");
		result.add("BrickletLCD128x64GUIButton4");
		result.add("BrickletLCD128x64GUIButton5");
		result.add("BrickletLCD128x64GUIButton6");
		result.add("BrickletLCD128x64GUIButton7");
		result.add("BrickletLCD128x64GUIButton8");
		result.add("BrickletLCD128x64GUIButton9");
		result.add("BrickletLCD128x64GUIButton10");
		result.add("BrickletLCD128x64GUIButton11");
		result.add("BrickletLCD128x64GUISlider0");
		result.add("BrickletLCD128x64GUISlider1");
		result.add("BrickletLCD128x64GUISlider2");
		result.add("BrickletLCD128x64GUISlider3");
		result.add("BrickletLCD128x64GUISlider4");
		result.add("BrickletLCD128x64GUISlider5");
        return result;
    }

    public static @Nullable ChannelType getChannelType(ChannelTypeUID channelTypeUID) {
        switch(channelTypeUID.getId()) {
            case "BrickletLCD128x64Text":
                return ChannelTypeBuilder.state(new ChannelTypeUID("tinkerforge", "BrickletLCD128x64Text"), "Text", "String").withConfigDescriptionURI(URI.create("channel-type:tinkerforge:BrickletLCD128x64Text")).withDescription("Text to display on the LCD. Command format is [line],[position],[text].<br/><br/>Additional ',' are handled as part of the text. Unicode characters are converted to the LCD character set if possible. Additionally you can use \\x[two hex digits] to use a character of the LCD character set directly.<br/><br/>PaperUI truncates whitespace at the start and end of commands. So to clear (parts of) a line, you can not use f.e. 1,2,[spaces]. Instead you can use the empty character like this 1,2,\\xFE\\xFE\\xFE to delete three characters at Line 1, Column 2.").build();
            case "BrickletLCD128x64ClearDisplay":
                return ChannelTypeBuilder.state(new ChannelTypeUID("tinkerforge", "BrickletLCD128x64ClearDisplay"), "Clear Display", "String").withConfigDescriptionURI(URI.create("channel-type:tinkerforge:BrickletLCD128x64ClearDisplay")).withDescription("Deletes all characters from the display.")
.withCommandDescription(CommandDescriptionBuilder.create().withCommandOption(new CommandOption("CLEAR", "Clear")).build()).build();
            case "BrickletLCD128x64DrawBufferedFrame":
                return ChannelTypeBuilder.state(new ChannelTypeUID("tinkerforge", "BrickletLCD128x64DrawBufferedFrame"), "Draw Buffered Frame", "String").withConfigDescriptionURI(URI.create("channel-type:tinkerforge:BrickletLCD128x64DrawBufferedFrame")).withDescription("Draws the currently buffered frame.")
.withCommandDescription(CommandDescriptionBuilder.create().withCommandOption(new CommandOption("DRAW", "Draw")).build()).build();
            case "BrickletLCD128x64Backlight":
                return ChannelTypeBuilder.state(new ChannelTypeUID("tinkerforge", "BrickletLCD128x64Backlight"), "Backlight", "Number:Dimensionless").withConfigDescriptionURI(URI.create("channel-type:tinkerforge:BrickletLCD128x64Backlight")).withDescription("The backlight intensity value.")
.withStateDescription(StateDescriptionFragmentBuilder.create().withMinimum(BigDecimal.valueOf(0)).withMaximum(BigDecimal.valueOf(100)).withStep(BigDecimal.valueOf(1)).withPattern("%d").withReadOnly(false).build().toStateDescription()).build();
            case "BrickletLCD128x64GUITabSelected":
                return ChannelTypeBuilder.state(new ChannelTypeUID("tinkerforge", "BrickletLCD128x64GUITabSelected"), "Selected GUI Tab", "Number").withConfigDescriptionURI(URI.create("channel-type:tinkerforge:BrickletLCD128x64GUITabSelected")).withDescription("The index of the currently selected tab. If there are not tabs, the index is -1.")
.withStateDescription(StateDescriptionFragmentBuilder.create().withMinimum(BigDecimal.valueOf(-1)).withMaximum(BigDecimal.valueOf(9)).withStep(BigDecimal.valueOf(1)).withPattern("%d %unit%").withReadOnly(false).build().toStateDescription()).build();
            case "BrickletLCD128x64GUISlider":
                return ChannelTypeBuilder.state(new ChannelTypeUID("tinkerforge", "BrickletLCD128x64GUISlider"), "NOT USED", "Number:Dimensionless").withConfigDescriptionURI(URI.create("channel-type:tinkerforge:BrickletLCD128x64GUISlider")).withDescription("The current slider value.")
.withStateDescription(StateDescriptionFragmentBuilder.create().withMinimum(BigDecimal.valueOf(0)).withMaximum(BigDecimal.valueOf(120)).withStep(BigDecimal.valueOf(1)).withPattern("%d").withReadOnly(true).build().toStateDescription()).build();
default:
                break;
        }

        return null;
    }

    public static ThingType getThingType(ThingTypeUID thingTypeUID) {
             Map<String, String> thingTypeProperties = ThingTypeBuilder.instance(thingTypeUID, "unused").build().getProperties();
             Map<String, String> props = new HashMap<String, String>(thingTypeProperties);
             props.putIfAbsent(TinkerforgeBindingConstants.PROPERTY_MINIMUM_FIRMWARE_VERSION, DEVICE_INFO.minimumFWVersion);
        return ThingTypeBuilder.instance(thingTypeUID, "Tinkerforge LCD 128x64 Bricklet").isListed(false).withSupportedBridgeTypeUIDs(Arrays.asList(TinkerforgeBindingConstants.THING_TYPE_BRICK_DAEMON.toString())).withConfigDescriptionURI(URI.create("thing-type:tinkerforge:" + thingTypeUID.getId())).withDescription("7.1cm (2.8\") display with 128x64 pixel and touch screen").withChannelDefinitions(Arrays.asList(new ChannelDefinitionBuilder("BrickletLCD128x64Text", new ChannelTypeUID("tinkerforge", "BrickletLCD128x64Text")).withLabel("Text").build(), new ChannelDefinitionBuilder("BrickletLCD128x64ClearDisplay", new ChannelTypeUID("tinkerforge", "BrickletLCD128x64ClearDisplay")).withLabel("Clear Display").build(), new ChannelDefinitionBuilder("BrickletLCD128x64DrawBufferedFrame", new ChannelTypeUID("tinkerforge", "BrickletLCD128x64DrawBufferedFrame")).withLabel("Draw Buffered Frame").build(), new ChannelDefinitionBuilder("BrickletLCD128x64Backlight", new ChannelTypeUID("tinkerforge", "BrickletLCD128x64Backlight")).withLabel("Backlight").build(), new ChannelDefinitionBuilder("BrickletLCD128x64TouchPosition", new ChannelTypeUID("system", "trigger")).withLabel("Touch Position").withDescription("Triggers when a new touch position is available. You can then use the getTouchPosition action to query the touch position information.").build(), new ChannelDefinitionBuilder("BrickletLCD128x64TouchGesture", new ChannelTypeUID("system", "trigger")).withLabel("Touch Gesture").withDescription("Triggers when a new touch gesture is available. You can then use the getTouchGesture action to query the touch gesture information.").build(), new ChannelDefinitionBuilder("BrickletLCD128x64SelectedGUITab", new ChannelTypeUID("tinkerforge", "BrickletLCD128x64GUITabSelected")).withLabel("Selected GUI Tab").build(), new ChannelDefinitionBuilder("BrickletLCD128x64GUIButton0", new ChannelTypeUID("system", "rawbutton")).withLabel("GUI Button 0").withDescription("Triggers when GUI Button 0 is pressed or released.").build(), new ChannelDefinitionBuilder("BrickletLCD128x64GUIButton1", new ChannelTypeUID("system", "rawbutton")).withLabel("GUI Button 1").withDescription("Triggers when GUI Button 1 is pressed or released.").build(), new ChannelDefinitionBuilder("BrickletLCD128x64GUIButton2", new ChannelTypeUID("system", "rawbutton")).withLabel("GUI Button 2").withDescription("Triggers when GUI Button 2 is pressed or released.").build(), new ChannelDefinitionBuilder("BrickletLCD128x64GUIButton3", new ChannelTypeUID("system", "rawbutton")).withLabel("GUI Button 3").withDescription("Triggers when GUI Button 3 is pressed or released.").build(), new ChannelDefinitionBuilder("BrickletLCD128x64GUIButton4", new ChannelTypeUID("system", "rawbutton")).withLabel("GUI Button 4").withDescription("Triggers when GUI Button 4 is pressed or released.").build(), new ChannelDefinitionBuilder("BrickletLCD128x64GUIButton5", new ChannelTypeUID("system", "rawbutton")).withLabel("GUI Button 5").withDescription("Triggers when GUI Button 5 is pressed or released.").build(), new ChannelDefinitionBuilder("BrickletLCD128x64GUIButton6", new ChannelTypeUID("system", "rawbutton")).withLabel("GUI Button 6").withDescription("Triggers when GUI Button 6 is pressed or released.").build(), new ChannelDefinitionBuilder("BrickletLCD128x64GUIButton7", new ChannelTypeUID("system", "rawbutton")).withLabel("GUI Button 7").withDescription("Triggers when GUI Button 7 is pressed or released.").build(), new ChannelDefinitionBuilder("BrickletLCD128x64GUIButton8", new ChannelTypeUID("system", "rawbutton")).withLabel("GUI Button 8").withDescription("Triggers when GUI Button 8 is pressed or released.").build(), new ChannelDefinitionBuilder("BrickletLCD128x64GUIButton9", new ChannelTypeUID("system", "rawbutton")).withLabel("GUI Button 9").withDescription("Triggers when GUI Button 9 is pressed or released.").build(), new ChannelDefinitionBuilder("BrickletLCD128x64GUIButton10", new ChannelTypeUID("system", "rawbutton")).withLabel("GUI Button 10").withDescription("Triggers when GUI Button 10 is pressed or released.").build(), new ChannelDefinitionBuilder("BrickletLCD128x64GUIButton11", new ChannelTypeUID("system", "rawbutton")).withLabel("GUI Button 11").withDescription("Triggers when GUI Button 11 is pressed or released.").build(), new ChannelDefinitionBuilder("BrickletLCD128x64GUISlider0", new ChannelTypeUID("tinkerforge", "BrickletLCD128x64GUISlider")).withLabel("GUI Slider 0").build(), new ChannelDefinitionBuilder("BrickletLCD128x64GUISlider1", new ChannelTypeUID("tinkerforge", "BrickletLCD128x64GUISlider")).withLabel("GUI Slider 1").build(), new ChannelDefinitionBuilder("BrickletLCD128x64GUISlider2", new ChannelTypeUID("tinkerforge", "BrickletLCD128x64GUISlider")).withLabel("GUI Slider 2").build(), new ChannelDefinitionBuilder("BrickletLCD128x64GUISlider3", new ChannelTypeUID("tinkerforge", "BrickletLCD128x64GUISlider")).withLabel("GUI Slider 3").build(), new ChannelDefinitionBuilder("BrickletLCD128x64GUISlider4", new ChannelTypeUID("tinkerforge", "BrickletLCD128x64GUISlider")).withLabel("GUI Slider 4").build(), new ChannelDefinitionBuilder("BrickletLCD128x64GUISlider5", new ChannelTypeUID("tinkerforge", "BrickletLCD128x64GUISlider")).withLabel("GUI Slider 5").build())).withProperties(props).build();
    }

    public static @Nullable ConfigDescription getConfigDescription(URI uri) {
        switch(uri.toASCIIString()) {
            case "thing-type:tinkerforge:brickletlcd128x64":
                return ConfigDescriptionBuilder.create(uri).withParameters(Arrays.asList(ConfigDescriptionParameterBuilder.create("contrast", Type.INTEGER).withDefault("14").withDescription("Sets the contrast of the display.").withLabel("Contrast").withAdvanced(true).withMinimum(BigDecimal.valueOf(0)).withMaximum(BigDecimal.valueOf(63)).build(), ConfigDescriptionParameterBuilder.create("defaultBacklightIntensity", Type.INTEGER).withDefault("100").withDescription("Sets the default backlight intensity of the display.").withLabel("Default Backlight Intensity").withAdvanced(true).withMinimum(BigDecimal.valueOf(0)).withMaximum(BigDecimal.valueOf(100)).build(), ConfigDescriptionParameterBuilder.create("invert", Type.BOOLEAN).withDefault("false").withDescription("Inverts black and white pixels.").withLabel("Invert").withAdvanced(true).build(), ConfigDescriptionParameterBuilder.create("automaticDraw", Type.BOOLEAN).withDefault("true").withDescription("If automatic draw is enabled, the display is automatically updated when writing text or clearing the display. If it is disabled, the changes are written into an internal buffer and only shown on the display after triggering the Draw Buffered Frame channel.").withLabel("Automatic Draw").withAdvanced(true).build(), ConfigDescriptionParameterBuilder.create("touchLEDConfig", Type.INTEGER).withDefault("3").withDescription("The touch LED configuration. By default the LED is on if the LCD is touched.<br/>You can also turn the LED permanently on/off or show a heartbeat.<br/>If the Bricklet is in bootloader mode, the LED is off.").withLabel("Touch LED").withAdvanced(true).withLimitToOptions(true).withOptions(Arrays.asList(new ParameterOption("0", "Off"), new ParameterOption("1", "On"), new ParameterOption("2", "Show Heartbeat"), new ParameterOption("3", "Show Touch"))).build(), ConfigDescriptionParameterBuilder.create("guiButtonUpdateInterval", Type.INTEGER).withDefault("100").withDescription("Specifies the update interval for the GUI buttons in milliseconds. A value of 0 disables automatic updates.").withGroupName("update_intervals").withLabel("GUI Button Update Interval").withUnit("ms").withMinimum(BigDecimal.valueOf(0)).withMaximum(BigDecimal.valueOf(4294967295L)).build(), ConfigDescriptionParameterBuilder.create("guiSliderUpdateInterval", Type.INTEGER).withDefault("100").withDescription("Specifies the update interval for the GUI sliders in milliseconds. A value of 0 disables automatic updates.").withGroupName("update_intervals").withLabel("GUI Slider Update Interval").withUnit("ms").withMinimum(BigDecimal.valueOf(0)).withMaximum(BigDecimal.valueOf(4294967295L)).build(), ConfigDescriptionParameterBuilder.create("touchPositionUpdateInterval", Type.INTEGER).withDefault("100").withDescription("Specifies the update interval for touch positions in milliseconds. A value of 0 disables automatic updates.").withGroupName("update_intervals").withLabel("Touch Position Update Interval").withUnit("ms").withMinimum(BigDecimal.valueOf(0)).withMaximum(BigDecimal.valueOf(4294967295L)).build(), ConfigDescriptionParameterBuilder.create("touchGestureUpdateInterval", Type.INTEGER).withDefault("100").withDescription("Specifies the update interval for touch gestures in milliseconds. A value of 0 disables automatic updates.").withGroupName("update_intervals").withLabel("Touch Gesture Update Interval").withUnit("ms").withMinimum(BigDecimal.valueOf(0)).withMaximum(BigDecimal.valueOf(4294967295L)).build(), ConfigDescriptionParameterBuilder.create("statusLEDConfig", Type.INTEGER).withDefault("3").withDescription("The status LED configuration. By default the LED shows communication traffic between Brick and Bricklet, it flickers once for every 10 received data packets.<br/><br/>You can also turn the LED permanently on/off or show a heartbeat.<br/><br/>If the Bricklet is in bootloader mode, the LED is will show heartbeat by default.").withLabel("Status LED Configuration").withAdvanced(true).withLimitToOptions(true).withOptions(Arrays.asList(new ParameterOption("0", "Off"), new ParameterOption("1", "On"), new ParameterOption("2", "Show Heartbeat"), new ParameterOption("3", "Show Status"))).build())).withParameterGroups(Arrays.asList(new ConfigDescriptionParameterGroup("update_intervals", "null", true, "Update Intervals", "Update Intervals"))).build();
            case "channel-type:tinkerforge:BrickletLCD128x64Text":
                return ConfigDescriptionBuilder.create(uri).withParameters(Arrays.asList()).withParameterGroups(Arrays.asList()).build();
            case "channel-type:tinkerforge:BrickletLCD128x64ClearDisplay":
                return ConfigDescriptionBuilder.create(uri).withParameters(Arrays.asList()).withParameterGroups(Arrays.asList()).build();
            case "channel-type:tinkerforge:BrickletLCD128x64DrawBufferedFrame":
                return ConfigDescriptionBuilder.create(uri).withParameters(Arrays.asList()).withParameterGroups(Arrays.asList()).build();
            case "channel-type:tinkerforge:BrickletLCD128x64Backlight":
                return ConfigDescriptionBuilder.create(uri).withParameters(Arrays.asList()).withParameterGroups(Arrays.asList()).build();
            case "channel-type:tinkerforge:BrickletLCD128x64GUITabSelected":
                return ConfigDescriptionBuilder.create(uri).withParameters(Arrays.asList(ConfigDescriptionParameterBuilder.create("updateInterval", Type.INTEGER).withDefault("1000").withDescription("Specifies the update interval in milliseconds. A value of 0 disables automatic updates.").withGroupName("update_intervals").withLabel("Update Interval").withUnit("ms").withMinimum(BigDecimal.valueOf(0)).withMaximum(BigDecimal.valueOf(4294967295L)).build())).withParameterGroups(Arrays.asList()).build();
            case "channel-type:tinkerforge:BrickletLCD128x64GUISlider":
                return ConfigDescriptionBuilder.create(uri).withParameters(Arrays.asList()).withParameterGroups(Arrays.asList()).build();
            default:
                break;
        }
        return null;
    }

        @Override
    public void refreshValue(String channel, org.eclipse.smarthome.config.core.Configuration config, org.eclipse.smarthome.config.core.Configuration channelConfig, BiConsumer<String, org.eclipse.smarthome.core.types.State> updateStateFn, BiConsumer<String, String> triggerChannelFn) throws TinkerforgeException {
        BrickletLCD128x64Config cfg = (BrickletLCD128x64Config) config.as(BrickletLCD128x64Config.class);
switch(channel) {
            case "BrickletLCD128x64Text":
               return;
            case "BrickletLCD128x64ClearDisplay":
               return;
            case "BrickletLCD128x64DrawBufferedFrame":
               return;
            case "BrickletLCD128x64Backlight":
                   {
            BrickletLCD128x64.DisplayConfiguration value = this.getDisplayConfiguration();
            if(true)
                updateStateFn.accept(channel, transformBrickletLCD128x64BacklightGetter0(value, cfg));
        }
                   return;
            case "BrickletLCD128x64TouchPosition":
               return;
            case "BrickletLCD128x64TouchGesture":
               return;
            case "BrickletLCD128x64SelectedGUITab":
                   {
            int value = this.getGUITabSelected();
            if(true)
                updateStateFn.accept(channel, transformBrickletLCD128x64SelectedGUITabGetter0(value, cfg));
        }
                   return;
            case "BrickletLCD128x64GUIButton0":
                   {
            boolean value = this.getGUIButtonPressed(0);
            if(true)
                triggerChannelFn.accept(channel, transformBrickletLCD128x64GUIButton0Getter0(value, cfg));
        }
                   return;
            case "BrickletLCD128x64GUIButton1":
                   {
            boolean value = this.getGUIButtonPressed(1);
            if(true)
                triggerChannelFn.accept(channel, transformBrickletLCD128x64GUIButton1Getter0(value, cfg));
        }
                   return;
            case "BrickletLCD128x64GUIButton2":
                   {
            boolean value = this.getGUIButtonPressed(2);
            if(true)
                triggerChannelFn.accept(channel, transformBrickletLCD128x64GUIButton2Getter0(value, cfg));
        }
                   return;
            case "BrickletLCD128x64GUIButton3":
                   {
            boolean value = this.getGUIButtonPressed(3);
            if(true)
                triggerChannelFn.accept(channel, transformBrickletLCD128x64GUIButton3Getter0(value, cfg));
        }
                   return;
            case "BrickletLCD128x64GUIButton4":
                   {
            boolean value = this.getGUIButtonPressed(4);
            if(true)
                triggerChannelFn.accept(channel, transformBrickletLCD128x64GUIButton4Getter0(value, cfg));
        }
                   return;
            case "BrickletLCD128x64GUIButton5":
                   {
            boolean value = this.getGUIButtonPressed(5);
            if(true)
                triggerChannelFn.accept(channel, transformBrickletLCD128x64GUIButton5Getter0(value, cfg));
        }
                   return;
            case "BrickletLCD128x64GUIButton6":
                   {
            boolean value = this.getGUIButtonPressed(6);
            if(true)
                triggerChannelFn.accept(channel, transformBrickletLCD128x64GUIButton6Getter0(value, cfg));
        }
                   return;
            case "BrickletLCD128x64GUIButton7":
                   {
            boolean value = this.getGUIButtonPressed(7);
            if(true)
                triggerChannelFn.accept(channel, transformBrickletLCD128x64GUIButton7Getter0(value, cfg));
        }
                   return;
            case "BrickletLCD128x64GUIButton8":
                   {
            boolean value = this.getGUIButtonPressed(8);
            if(true)
                triggerChannelFn.accept(channel, transformBrickletLCD128x64GUIButton8Getter0(value, cfg));
        }
                   return;
            case "BrickletLCD128x64GUIButton9":
                   {
            boolean value = this.getGUIButtonPressed(9);
            if(true)
                triggerChannelFn.accept(channel, transformBrickletLCD128x64GUIButton9Getter0(value, cfg));
        }
                   return;
            case "BrickletLCD128x64GUIButton10":
                   {
            boolean value = this.getGUIButtonPressed(10);
            if(true)
                triggerChannelFn.accept(channel, transformBrickletLCD128x64GUIButton10Getter0(value, cfg));
        }
                   return;
            case "BrickletLCD128x64GUIButton11":
                   {
            boolean value = this.getGUIButtonPressed(11);
            if(true)
                triggerChannelFn.accept(channel, transformBrickletLCD128x64GUIButton11Getter0(value, cfg));
        }
                   return;
            case "BrickletLCD128x64GUISlider0":
                   {
            int value = this.getGUISliderValue(0);
            if(true)
                updateStateFn.accept(channel, transformBrickletLCD128x64GUISlider0Getter0(value, cfg));
        }
                   return;
            case "BrickletLCD128x64GUISlider1":
                   {
            int value = this.getGUISliderValue(1);
            if(true)
                updateStateFn.accept(channel, transformBrickletLCD128x64GUISlider1Getter0(value, cfg));
        }
                   return;
            case "BrickletLCD128x64GUISlider2":
                   {
            int value = this.getGUISliderValue(2);
            if(true)
                updateStateFn.accept(channel, transformBrickletLCD128x64GUISlider2Getter0(value, cfg));
        }
                   return;
            case "BrickletLCD128x64GUISlider3":
                   {
            int value = this.getGUISliderValue(3);
            if(true)
                updateStateFn.accept(channel, transformBrickletLCD128x64GUISlider3Getter0(value, cfg));
        }
                   return;
            case "BrickletLCD128x64GUISlider4":
                   {
            int value = this.getGUISliderValue(4);
            if(true)
                updateStateFn.accept(channel, transformBrickletLCD128x64GUISlider4Getter0(value, cfg));
        }
                   return;
            case "BrickletLCD128x64GUISlider5":
                   {
            int value = this.getGUISliderValue(5);
            if(true)
                updateStateFn.accept(channel, transformBrickletLCD128x64GUISlider5Getter0(value, cfg));
        }
                   return;
default:
                logger.warn("Refresh for unknown channel {}", channel);
                break;
        }
    }
    

        @Override
    public List<SetterRefresh> handleCommand(org.eclipse.smarthome.config.core.Configuration config, org.eclipse.smarthome.config.core.Configuration channelConfig, String channel, Command command) throws TinkerforgeException {
        List<SetterRefresh> result = Collections.emptyList();
        BrickletLCD128x64Config cfg = (BrickletLCD128x64Config) config.as(BrickletLCD128x64Config.class);
        switch(channel) {
            case "BrickletLCD128x64Text":
                if (command instanceof StringType) {
                    StringType cmd = (StringType) command;
this.writeLine(Helper.parseDisplayCommandLine(cmd.toString(), logger), Helper.parseDisplayCommandPosition(cmd.toString(), logger), Helper.parseDisplayCommandText(cmd.toString(), logger, false));
                }
        
                else {
                    logger.warn("Command type {} not supported for channel {}. Please use one of StringType.", command.getClass().getName(), channel);
                }
                
                break;
            case "BrickletLCD128x64ClearDisplay":
                if (command instanceof StringType) {
                    this.clearDisplay();
                }
        
                else {
                    logger.warn("Command type {} not supported for channel {}. Please use one of StringType.", command.getClass().getName(), channel);
                }
                
                break;
            case "BrickletLCD128x64DrawBufferedFrame":
                if (command instanceof StringType) {
                    this.drawBufferedFrame(true);
                }
        
                else {
                    logger.warn("Command type {} not supported for channel {}. Please use one of StringType.", command.getClass().getName(), channel);
                }
                
                break;
            case "BrickletLCD128x64Backlight":
                if (command instanceof Number) {
                    Number cmd = (Number) command;
this.setDisplayConfiguration(cfg.contrast, cmd.intValue(), cfg.invert, cfg.automaticDraw);
                }
        
                else {
                    logger.warn("Command type {} not supported for channel {}. Please use one of Number.", command.getClass().getName(), channel);
                }
                
                break;
            case "BrickletLCD128x64SelectedGUITab":
                if (command instanceof Number) {
                    Number cmd = (Number) command;
this.setGUITabSelected(cmd.intValue());
                }
        
                else {
                    logger.warn("Command type {} not supported for channel {}. Please use one of Number.", command.getClass().getName(), channel);
                }
                
                break;
default:
                logger.warn("Command for unknown channel {}", channel);
        }
        return result;
    }

        private String transformBrickletLCD128x64TouchPositionCallback0(int pressure, int x, int y, long age, BrickletLCD128x64Config cfg) {
        return "";
    }
	    private String transformBrickletLCD128x64TouchGestureCallback0(int gesture, long duration, int pressureMax, int xStart, int yStart, int xEnd, int yEnd, long age, BrickletLCD128x64Config cfg) {
        return "";
    }
	    private org.eclipse.smarthome.core.types.State transformBrickletLCD128x64SelectedGUITabCallback0(int index, BrickletLCD128x64Config cfg) {
        return new DecimalType(index);
    }
	    private String transformBrickletLCD128x64GUIButton0Callback0(int index, boolean pressed, BrickletLCD128x64Config cfg) {
        return pressed ? CommonTriggerEvents.PRESSED : CommonTriggerEvents.RELEASED;
    }
	    private String transformBrickletLCD128x64GUIButton1Callback0(int index, boolean pressed, BrickletLCD128x64Config cfg) {
        return pressed ? CommonTriggerEvents.PRESSED : CommonTriggerEvents.RELEASED;
    }
	    private String transformBrickletLCD128x64GUIButton2Callback0(int index, boolean pressed, BrickletLCD128x64Config cfg) {
        return pressed ? CommonTriggerEvents.PRESSED : CommonTriggerEvents.RELEASED;
    }
	    private String transformBrickletLCD128x64GUIButton3Callback0(int index, boolean pressed, BrickletLCD128x64Config cfg) {
        return pressed ? CommonTriggerEvents.PRESSED : CommonTriggerEvents.RELEASED;
    }
	    private String transformBrickletLCD128x64GUIButton4Callback0(int index, boolean pressed, BrickletLCD128x64Config cfg) {
        return pressed ? CommonTriggerEvents.PRESSED : CommonTriggerEvents.RELEASED;
    }
	    private String transformBrickletLCD128x64GUIButton5Callback0(int index, boolean pressed, BrickletLCD128x64Config cfg) {
        return pressed ? CommonTriggerEvents.PRESSED : CommonTriggerEvents.RELEASED;
    }
	    private String transformBrickletLCD128x64GUIButton6Callback0(int index, boolean pressed, BrickletLCD128x64Config cfg) {
        return pressed ? CommonTriggerEvents.PRESSED : CommonTriggerEvents.RELEASED;
    }
	    private String transformBrickletLCD128x64GUIButton7Callback0(int index, boolean pressed, BrickletLCD128x64Config cfg) {
        return pressed ? CommonTriggerEvents.PRESSED : CommonTriggerEvents.RELEASED;
    }
	    private String transformBrickletLCD128x64GUIButton8Callback0(int index, boolean pressed, BrickletLCD128x64Config cfg) {
        return pressed ? CommonTriggerEvents.PRESSED : CommonTriggerEvents.RELEASED;
    }
	    private String transformBrickletLCD128x64GUIButton9Callback0(int index, boolean pressed, BrickletLCD128x64Config cfg) {
        return pressed ? CommonTriggerEvents.PRESSED : CommonTriggerEvents.RELEASED;
    }
	    private String transformBrickletLCD128x64GUIButton10Callback0(int index, boolean pressed, BrickletLCD128x64Config cfg) {
        return pressed ? CommonTriggerEvents.PRESSED : CommonTriggerEvents.RELEASED;
    }
	    private String transformBrickletLCD128x64GUIButton11Callback0(int index, boolean pressed, BrickletLCD128x64Config cfg) {
        return pressed ? CommonTriggerEvents.PRESSED : CommonTriggerEvents.RELEASED;
    }
	    private org.eclipse.smarthome.core.types.State transformBrickletLCD128x64GUISlider0Callback0(int index, int value, BrickletLCD128x64Config cfg) {
        return new DecimalType(value);
    }
	    private org.eclipse.smarthome.core.types.State transformBrickletLCD128x64GUISlider1Callback0(int index, int value, BrickletLCD128x64Config cfg) {
        return new DecimalType(value);
    }
	    private org.eclipse.smarthome.core.types.State transformBrickletLCD128x64GUISlider2Callback0(int index, int value, BrickletLCD128x64Config cfg) {
        return new DecimalType(value);
    }
	    private org.eclipse.smarthome.core.types.State transformBrickletLCD128x64GUISlider3Callback0(int index, int value, BrickletLCD128x64Config cfg) {
        return new DecimalType(value);
    }
	    private org.eclipse.smarthome.core.types.State transformBrickletLCD128x64GUISlider4Callback0(int index, int value, BrickletLCD128x64Config cfg) {
        return new DecimalType(value);
    }
	    private org.eclipse.smarthome.core.types.State transformBrickletLCD128x64GUISlider5Callback0(int index, int value, BrickletLCD128x64Config cfg) {
        return new DecimalType(value);
    }
	    private org.eclipse.smarthome.core.types.State transformBrickletLCD128x64BacklightGetter0(BrickletLCD128x64.DisplayConfiguration value, BrickletLCD128x64Config cfg) {
        return new DecimalType(value.backlight);
    }
	    private org.eclipse.smarthome.core.types.State transformBrickletLCD128x64SelectedGUITabGetter0(int value, BrickletLCD128x64Config cfg) {
        return new DecimalType(value);
    }
	    private String transformBrickletLCD128x64GUIButton0Getter0(boolean value, BrickletLCD128x64Config cfg) {
        return value ? CommonTriggerEvents.PRESSED : CommonTriggerEvents.RELEASED;
    }
	    private String transformBrickletLCD128x64GUIButton1Getter0(boolean value, BrickletLCD128x64Config cfg) {
        return value ? CommonTriggerEvents.PRESSED : CommonTriggerEvents.RELEASED;
    }
	    private String transformBrickletLCD128x64GUIButton2Getter0(boolean value, BrickletLCD128x64Config cfg) {
        return value ? CommonTriggerEvents.PRESSED : CommonTriggerEvents.RELEASED;
    }
	    private String transformBrickletLCD128x64GUIButton3Getter0(boolean value, BrickletLCD128x64Config cfg) {
        return value ? CommonTriggerEvents.PRESSED : CommonTriggerEvents.RELEASED;
    }
	    private String transformBrickletLCD128x64GUIButton4Getter0(boolean value, BrickletLCD128x64Config cfg) {
        return value ? CommonTriggerEvents.PRESSED : CommonTriggerEvents.RELEASED;
    }
	    private String transformBrickletLCD128x64GUIButton5Getter0(boolean value, BrickletLCD128x64Config cfg) {
        return value ? CommonTriggerEvents.PRESSED : CommonTriggerEvents.RELEASED;
    }
	    private String transformBrickletLCD128x64GUIButton6Getter0(boolean value, BrickletLCD128x64Config cfg) {
        return value ? CommonTriggerEvents.PRESSED : CommonTriggerEvents.RELEASED;
    }
	    private String transformBrickletLCD128x64GUIButton7Getter0(boolean value, BrickletLCD128x64Config cfg) {
        return value ? CommonTriggerEvents.PRESSED : CommonTriggerEvents.RELEASED;
    }
	    private String transformBrickletLCD128x64GUIButton8Getter0(boolean value, BrickletLCD128x64Config cfg) {
        return value ? CommonTriggerEvents.PRESSED : CommonTriggerEvents.RELEASED;
    }
	    private String transformBrickletLCD128x64GUIButton9Getter0(boolean value, BrickletLCD128x64Config cfg) {
        return value ? CommonTriggerEvents.PRESSED : CommonTriggerEvents.RELEASED;
    }
	    private String transformBrickletLCD128x64GUIButton10Getter0(boolean value, BrickletLCD128x64Config cfg) {
        return value ? CommonTriggerEvents.PRESSED : CommonTriggerEvents.RELEASED;
    }
	    private String transformBrickletLCD128x64GUIButton11Getter0(boolean value, BrickletLCD128x64Config cfg) {
        return value ? CommonTriggerEvents.PRESSED : CommonTriggerEvents.RELEASED;
    }
	    private org.eclipse.smarthome.core.types.State transformBrickletLCD128x64GUISlider0Getter0(int value, BrickletLCD128x64Config cfg) {
        return new DecimalType(value);
    }
	    private org.eclipse.smarthome.core.types.State transformBrickletLCD128x64GUISlider1Getter0(int value, BrickletLCD128x64Config cfg) {
        return new DecimalType(value);
    }
	    private org.eclipse.smarthome.core.types.State transformBrickletLCD128x64GUISlider2Getter0(int value, BrickletLCD128x64Config cfg) {
        return new DecimalType(value);
    }
	    private org.eclipse.smarthome.core.types.State transformBrickletLCD128x64GUISlider3Getter0(int value, BrickletLCD128x64Config cfg) {
        return new DecimalType(value);
    }
	    private org.eclipse.smarthome.core.types.State transformBrickletLCD128x64GUISlider4Getter0(int value, BrickletLCD128x64Config cfg) {
        return new DecimalType(value);
    }
	    private org.eclipse.smarthome.core.types.State transformBrickletLCD128x64GUISlider5Getter0(int value, BrickletLCD128x64Config cfg) {
        return new DecimalType(value);
    }

}