/**
 *  Copyright © 2021-2025, Luis Andrés Lange <https://javacomm.net>
 *
 *  This Source Code Form is subject to the terms of the Mozilla Public
 *  License, v. 2.0. If a copy of the MPL was not distributed with this
 *  file, You can obtain one at http://mozilla.org/MPL/2.0/.
 *
 *  ----------------------------------------------------------------------------
 *
 *  Exhibit B - "Incompatible With Secondary Licenses" Notice
 *
 *  This Source Code Form is "Incompatible With Secondary Licenses",
 *  as defined by the Mozilla Public License, v. 2.0.
 *
 *  In short:
 *  - This file may be used, modified, and distributed under MPL 2.0 only.
 *  - It may NOT be relicensed under GPL, LGPL, AGPL, or any other Secondary License.
 *
 *  Rationale:
 *  - Ensures that the code remains MPL-2.0.
 *  - Avoids legal conflicts with GPL-licensed libraries (e.g., VideoLAN).
 *  - Maximizes usability for commercial and security-critical applications.
 *
 */
package net.javacomm.client.iptv;

import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Cursor;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeSupport;
import java.beans.PropertyVetoException;
import java.net.URL;
import java.util.HashMap;
import java.util.List;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import javax.swing.ButtonGroup;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JCheckBoxMenuItem;
import javax.swing.JComponent;
import javax.swing.JPanel;
import javax.swing.JPopupMenu;
import javax.swing.JScrollPane;
import javax.swing.JSplitPane;
import javax.swing.ScrollPaneConstants;
import javax.swing.SwingConstants;
import javax.swing.UIManager;
import javax.swing.WindowConstants;
import javax.swing.event.InternalFrameAdapter;
import javax.swing.event.InternalFrameEvent;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import net.javacomm.client.gui.JSliderVolumePanel;
import net.javacomm.client.mediaplayer.VLCMediaPlayerAdapter;
import net.javacomm.client.resource.Resource;
import net.javacomm.multilingual.MultilingualLabel;
import net.javacomm.multilingual.MultilingualMenu;
import net.javacomm.multilingual.MultilingualMenuItem;
import net.javacomm.multilingual.schema.ISO639;
import net.javacomm.multilingual.schema.KEY;
import net.javacomm.window.manager.Control;
import net.javacomm.window.manager.Frames;
import net.javacomm.window.manager.WM;
import net.javacomm.window.manager.WMResource;
import net.javacomm.window.manager.WindowAnrufenEvent;
import net.javacomm.window.manager.WindowAnrufenListener;
import net.javacomm.window.manager.WindowManagerInternalFrame;
import uk.co.caprica.vlcj.media.Media;
import uk.co.caprica.vlcj.media.MediaEventAdapter;
import uk.co.caprica.vlcj.media.MediaParsedStatus;
import uk.co.caprica.vlcj.player.base.AudioApi;
import uk.co.caprica.vlcj.player.base.EventApi;
import uk.co.caprica.vlcj.player.base.MediaPlayer;
import uk.co.caprica.vlcj.player.base.VideoApi;
import uk.co.caprica.vlcj.player.component.CallbackMediaPlayerComponent;
import uk.co.caprica.vlcj.player.component.callback.FilledCallbackImagePainter;
import uk.co.caprica.vlcj.player.embedded.EmbeddedMediaPlayer;



public class IptvFrame extends WindowManagerInternalFrame implements WindowAnrufenListener {

  private final static Logger log = LogManager.getLogger(IptvFrame.class);
  public final static int TOP_BAR = 220;
  private static final long serialVersionUID = -4639298125644834299L;
  public final static int SCREEN_WIDTH = 900;
  public final static int SCREEN_HEIGHT = 656;
  private BorderLayout borderlayout = new BorderLayout();
  private CallbackMediaPlayerComponent mediaplayerComponent;
  private JComponent videosurface;
  private MultilingualLabel corner;
  private ButtonGroup programgroup = new ButtonGroup();
  private GsonBuilder gsonbuilder;

  // private ScaledCallbackImagePainter imagePainter;
  // private FixedCallbackImagePainter imagePainter;
  private FilledCallbackImagePainter imagePainter;
  private JPopupMenu popup = new JPopupMenu();
  private MouseAdapter videosurfaceListener;
  private MouseAdapter robotListener;
  private int firsttime = 0;

  private JPanel eispanel = new JPanel();
  private JButton buttonVollbild;
  private ActionListener fullscreenListener;
  private int iptvVolume;
  private AudioApi audioapi;

  private EmbeddedMediaPlayer embedded;
  private PropertyChangeSupport changes = new PropertyChangeSupport(this);
  private InternalFrameAdapter internalFrameAdapter = new InternalFrameAdapter() {

    @Override
    public void internalFrameActivated(InternalFrameEvent event) {
      changes.firePropertyChange(IptvFrame.class.getName(), Control.NULL, Control.IPTV_FRAME_ACTIVATED);
    }



    @Override
    public void internalFrameClosing(InternalFrameEvent e) {
      shutdown();
      changes.firePropertyChange(IptvFrame.class.getName(), Control.NULL, Control.CLOSE);
    }

  };

  private int bottom = 6;
  private EventApi eventsAPI;
  private VideoApi videoApi;
  private ImageIcon image;
  private ImageIcon fullscreen;
  private URL url;
  private CountDownLatch countdown;
  private DurationAdapter mediaEventAdapter = new DurationAdapter();
  private String record = "";
  private JSplitPane splitpaneHorizontal = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT);
  private JScrollPane scrollvideopane = new JScrollPane();
  private GridBagLayout gridbag = new GridBagLayout();
  private GridBagConstraints con = new GridBagConstraints();
  private JPanel buttonpanel = new JPanel(gridbag);
  private JScrollPane topPanel = new JScrollPane();
  private JSplitPane splitpaneVertical = new JSplitPane(JSplitPane.VERTICAL_SPLIT);
  private MultilingualLabel imageRobot = new MultilingualLabel();
  private Class<? extends IptvFrame> resource;
  private IptvButton button01TV = new IptvButton("01TV");
  private IptvButton buttonAguasCalientes = new IptvButton("Aguascalientes TV (México)");
  private IptvButton buttonArteDeutsch = new IptvButton("ARTE Deutsch");
  private IptvButton buttonArteFrance = new IptvButton("ARTE Français");
  private IptvButton buttonSportschau = new IptvButton("ARD Sportschau LIVE");
  private IptvButton buttonSAT1 = new IptvButton("SAT 1");
  private IptvButton buttonBloomberg = new IptvButton("Bloomberg");
  private IptvButton buttonSIXX = new IptvButton("SIXX");
  private IptvButton buttonRAI24 = new IptvButton("RAI News 24");
  private IptvButton buttonCanal24 = new IptvButton("Canal 24");
  private IptvButton buttonMDR = new IptvButton("MDR");
  private IptvButton buttonBlueTV = new IptvButton("Blue TV (Brasil)");
  private IptvButton buttonDanceTV = new IptvButton("Dance TV");
  private IptvButton buttonV2Beat = new IptvButton("V2Beat TV");
  private IptvButton buttonRTDE = new IptvButton("RT DE");
  private IptvButton buttonRTL2 = new IptvButton("RTL 2");
  private IptvButton buttonIndiaNews = new IptvButton("India News");
  private IptvButton buttonMir24 = new IptvButton("МИР 24");
  private IptvButton buttonNTW = new IptvButton("НТВ");
  private IptvButton buttonCGTN_EN = new IptvButton("CGTN English");
  private IptvButton buttonCGTN_FR = new IptvButton("CGTN Français");
  private IptvButton buttonCGTN_ES = new IptvButton("CGTN Español");
  private IptvButton buttonKABEL1 = new IptvButton("Kabel 1");
  private IptvButton buttonTeleSUR_ES = new IptvButton("teleSUR Español");
  private IptvButton buttonTeleSUR_EN = new IptvButton("teleSUR English");
  private IptvButton buttonRTL_NITRO = new IptvButton("RTL NITRO");
  private IptvButton buttonNTW_SERIAL = new IptvButton("НТВ Сериал");
  private IptvButton buttonPRO7 = new IptvButton("PRO7");
  private IptvButton buttonPro7MAXX = new IptvButton("7MAXX");
  private IptvButton buttonTele5 = new IptvButton("Tele5");
  private IptvButton buttonAXN = new IptvButton("AXN Portugal");
  private IptvButton buttonVOX = new IptvButton("VOX");
  private IptvButton buttonZDFinfo = new IptvButton("ZDFinfo");
  private MultilingualMenuItem itemVollbild = new MultilingualMenuItem(KEY.VOLLBILDMODUS);
  private MultilingualMenuItem itemLauter = new MultilingualMenuItem(KEY.STRING_LAUTER);
  private MultilingualMenuItem itemLeiser = new MultilingualMenuItem(KEY.STRING_LEISER);
  private MultilingualMenu menuProgramme = new MultilingualMenu(KEY.TV);
  private JCheckBoxMenuItem itemArteDeutsch = new JCheckBoxMenuItem(buttonArteDeutsch.getText());
  private JCheckBoxMenuItem itemArteFrance = new JCheckBoxMenuItem(buttonArteFrance.getText());
  private JCheckBoxMenuItem itemSAT1 = new JCheckBoxMenuItem(buttonSAT1.getText());
  private JCheckBoxMenuItem itemBloomberg = new JCheckBoxMenuItem(buttonBloomberg.getText());
  private JCheckBoxMenuItem itemCGTN_EN = new JCheckBoxMenuItem(buttonCGTN_EN.getText());
  private JCheckBoxMenuItem itemCGTN_ES = new JCheckBoxMenuItem(buttonCGTN_ES.getText());
  private JCheckBoxMenuItem itemCGTN_FR = new JCheckBoxMenuItem(buttonCGTN_FR.getText());
  private JCheckBoxMenuItem itemBlueTV = new JCheckBoxMenuItem(buttonBlueTV.getText());
  private JCheckBoxMenuItem itemKABEL1 = new JCheckBoxMenuItem(buttonKABEL1.getText());
  private JCheckBoxMenuItem itemDanceTV = new JCheckBoxMenuItem(buttonDanceTV.getText());
  private JCheckBoxMenuItem itemSportschau = new JCheckBoxMenuItem(buttonSportschau.getText());
  private JCheckBoxMenuItem itemSIXX = new JCheckBoxMenuItem(buttonSIXX.getText());
  private JCheckBoxMenuItem itemRai24 = new JCheckBoxMenuItem(buttonRAI24.getText());
  private JCheckBoxMenuItem itemCanal24 = new JCheckBoxMenuItem(buttonCanal24.getText());
  private JCheckBoxMenuItem itemAXN = new JCheckBoxMenuItem(buttonAXN.getText());
  private JCheckBoxMenuItem itemMDR = new JCheckBoxMenuItem(buttonMDR.getText());
  private JCheckBoxMenuItem itemZdfinfo = new JCheckBoxMenuItem(buttonZDFinfo.getText());
  private JCheckBoxMenuItem itemPRO7 = new JCheckBoxMenuItem(buttonPRO7.getText());
  private JCheckBoxMenuItem itemVOX = new JCheckBoxMenuItem(buttonVOX.getText());
  private JCheckBoxMenuItem itemV2Beat = new JCheckBoxMenuItem(buttonV2Beat.getText());
  private JCheckBoxMenuItem itemTele5 = new JCheckBoxMenuItem(buttonTele5.getText());
  private JCheckBoxMenuItem itemRTDE = new JCheckBoxMenuItem(buttonRTDE.getText());
  private JCheckBoxMenuItem itemRTL2 = new JCheckBoxMenuItem(buttonRTL2.getText());
  private JCheckBoxMenuItem itemIndiaNews = new JCheckBoxMenuItem(buttonIndiaNews.getText());
  private JCheckBoxMenuItem itemMir24 = new JCheckBoxMenuItem(buttonMir24.getText());
  private JCheckBoxMenuItem itemNTW = new JCheckBoxMenuItem(buttonNTW.getText());
  private JCheckBoxMenuItem item01TV = new JCheckBoxMenuItem(button01TV.getText());
  private JCheckBoxMenuItem itemTeleSUR_ES = new JCheckBoxMenuItem(buttonTeleSUR_ES.getText());
  private JCheckBoxMenuItem itemTeleSUR_EN = new JCheckBoxMenuItem(buttonTeleSUR_EN.getText());
  private JCheckBoxMenuItem itemAguasCalientes = new JCheckBoxMenuItem(buttonAguasCalientes.getText());
  private JCheckBoxMenuItem itemRTL_NITRO = new JCheckBoxMenuItem(buttonRTL_NITRO.getText());
  private JCheckBoxMenuItem itemNTW_SERIAL = new JCheckBoxMenuItem(buttonNTW_SERIAL.getText());
  private JCheckBoxMenuItem itemPro7MAXX = new JCheckBoxMenuItem(buttonPro7MAXX.getText());
  private JSliderVolumePanel volumePanel = new JSliderVolumePanel();
  private PropertyChangeListener volumelistener = new PropertyChangeListener() {

    @Override
    public void propertyChange(PropertyChangeEvent event) {
      Integer value = (Integer) event.getNewValue();
      iptvVolume = value;
      synchronized (this) {
        if (audioapi != null) {
          audioapi.setVolume(iptvVolume);
        }
      }
      changes.firePropertyChange(IptvFrame.class.getName(), Control.NULL, Control.IPTV_VOLUME);
    }

  };
  private ActionListener lauterListener = new ActionListener() {

    @Override
    public void actionPerformed(ActionEvent event) {
      // Lautstärke erhöhen um 15 Punkte
      iptvVolume = volumePanel.getLoudness() + 15;
      volumePanel.setLoudness(iptvVolume);
      synchronized (this) {
        try {
          if (audioapi != null) audioapi.setVolume(iptvVolume);
        }
        catch (Error error) {
          log.error(error.getMessage());
        }
      }

    }

  };
  private ActionListener leiserListener = new ActionListener() {

    @Override
    public void actionPerformed(ActionEvent e) {
      // Lautstärke runter um 15 Punkte
      iptvVolume = volumePanel.getLoudness() - 15;
      volumePanel.setLoudness(iptvVolume);
      synchronized (this) {
        try {
          if (audioapi != null) audioapi.setVolume(iptvVolume);
        }
        catch (Error error) {
          log.error(error.getMessage());
        }
      }

    }

  };

  private JButton buttonPower = new JButton();
  private TVSender sender;
  private ComponentAdapter componentAdapter = new ComponentAdapter() {

    @Override
    public void componentResized(ComponentEvent event) {
      if (IptvFrame.this.isMaximum()) {
        setHorizontalDivider(1.0);
        setVerticalDivider(firsttime >= 2 ? 0 : TOP_BAR);
        firsttime++;
        // setVerticalDivider(0.0);
      }
      else {
        setHorizontalDivider(SCREEN_WIDTH - WindowManagerInternalFrame.SPLITWIDTH);
        setVerticalDivider(TOP_BAR);
        Rectangle rectangle = IptvFrame.this.getParent().getBounds();
        setLocation(
            (rectangle.width - IptvFrame.SCREEN_WIDTH) / 2, (rectangle.height - IptvFrame.SCREEN_HEIGHT) / 2
        );

      }
    }

  };

  private VLCMediaPlayerAdapter playerAdapter = new VLCMediaPlayerAdapter() {

    @Override
    public void stopped(MediaPlayer mediaPlayer) {

    }



    @Override
    public void videoOutput(MediaPlayer mediaPlayer, int newCount) {

      EventQueue.invokeLater(() -> {
        videoApi = mediaPlayer.video();
        // videoApi könnte null sein
        videosurface.requestFocusInWindow();
        try {
          videosurface.setSize(videoApi.videoDimension());
        }
        catch (Exception e) {}
        catch (Error error) {
          log.info(error.getMessage());
        }
        audioapi = mediaPlayer.audio();
        iptvVolume = volumePanel.getLoudness();
        audioapi.setVolume(iptvVolume);
      });

    }
  };
  private Cursor dukeCursor;
  private ImageIcon remoteImage;
  private String oldname;
  private String oldnameTelefonEinrichten;

  public IptvFrame() {
    gsonbuilder = new GsonBuilder().disableHtmlEscaping();
    resource = getClass();
    setMaximizable(true);
    setResizable(true);
    setIconifiable(true);
    setClosable(true);
    setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
    setFrameTitleId("IPTV");
    setSize(SCREEN_WIDTH, SCREEN_HEIGHT);
    url = getClass().getResource(Resource.TVTEST_41x26);
    image = new ImageIcon(url);
    setFrameIcon(image);
    setLayout(borderlayout);
    addInternalFrameListener(internalFrameAdapter);
    init();
  }



  @Override
  public void activated() {
    try {
      setSelected(true);
      windowManager.setActivNode(record);
    }
    catch (PropertyVetoException e) {}
  }



  public synchronized void addIptvListener(PropertyChangeListener listener) {
    changes.addPropertyChangeListener(listener);
  }



  /**
   * Baue eine Verbindung zum Server auf.
   *
   * @param adresse
   *                die Serveradresse
   */
  private void connect(String adresse) {
    // TODO der alte muss beendet sein

    embedded = createEmbeddedPlayer();
    countdown = new CountDownLatch(1);
    embedded.media().prepare(adresse);
    eventsAPI = embedded.events();
    eventsAPI.addMediaEventListener(mediaEventAdapter);
    eventsAPI.addMediaPlayerEventListener(playerAdapter);
    embedded.media().parsing().parse(); // asynchron
    try {
      // Warte, bis er mit dem Parsen fertig ist
      countdown.await(7, TimeUnit.SECONDS);
      MediaParsedStatus status = mediaEventAdapter.getStatus();
      if (status == MediaParsedStatus.FAILED) {
        log.warn("Die Adresse ist ungültig -> " + adresse);
        return;
      }
      embedded.media().play(adresse, "network-caching=8960"); // löst Status done aus
    }
    catch (InterruptedException e) {
      log.error(e.getMessage(), e.getCause());
      return;
    }
  }



  /**
   * Eine Hilfsmehode, welche die rechte untere Ecke in der Videoansicht einfärbt.
   * Nach einem L&F-Wechsel wurde die Farbe nicht geändert.
   *
   * @param color
   *              eine Farbe
   */
  public void corner(Color color) {
    corner.setBackground(color);
    eispanel.setBackground(color);

  }



  private EmbeddedMediaPlayer createEmbeddedPlayer() {
    mediaplayerComponent = new CallbackMediaPlayerComponent(null, null, null, true, null, null, null, null);

    if (videosurface != null) {
      // MouseAdapter entfernen
      videosurface.removeMouseListener(videosurfaceListener);
    }

    videosurface = mediaplayerComponent.videoSurfaceComponent();
    videosurfaceListener = new MouseAdapter() {

      @Override
      public void mousePressed(MouseEvent event) {
        if (event.isPopupTrigger()) {
          popup.show(videosurface, event.getX(), event.getY());
        }
      }



      @Override
      public void mouseReleased(MouseEvent event) {
        if (event.isPopupTrigger()) {
          popup.show(videosurface, event.getX(), event.getY());
        }
      }

    };
    videosurface.addMouseListener(videosurfaceListener);
    scrollvideopane.getViewport().add(videosurface);
    scrollvideopane.setCursor(dukeCursor);
    imagePainter = new FilledCallbackImagePainter();
    mediaplayerComponent.setImagePainter(imagePainter);
    EmbeddedMediaPlayer player = mediaplayerComponent.mediaPlayer();
    return player;
  }



  @Override
  public String getFrameTitleId() {
    return record;
  }



  @Override
  public Dimension getMinimumSize() {
    return new Dimension(SCREEN_WIDTH, SCREEN_HEIGHT);
  }



  @Override
  public Frames getType() {
    return Frames.TV;
  }



  /**
   * Die Lautsprecherstärke wird vom Slider abgelesen.
   *
   *
   * @return die Lautstärke
   */
  public int getVolume() {
    return volumePanel.getLoudness();
  }



  /**
   * Die Knöpfe werden ausgelegt.
   */
  private void init() {
    remoteImage = new ImageIcon(resource.getResource(Resource.REMOTECURSOR));
    Toolkit toolkit = Toolkit.getDefaultToolkit();
    dukeCursor = toolkit.createCustomCursor(remoteImage.getImage(), new Point(0, 0), "fernbedienung");

    popup.setCursor(dukeCursor);
    popup.add(menuProgramme);
    menuProgramme.setIcon(new ImageIcon(resource.getResource(Resource.ROBOT_TV_30x26)));

    menuProgramme.add(item01TV);
    menuProgramme.add(itemAguasCalientes);
    menuProgramme.add(itemSportschau);
    menuProgramme.add(itemArteDeutsch);
    menuProgramme.add(itemArteFrance);
    menuProgramme.add(itemAXN);
    menuProgramme.add(itemBloomberg);
    menuProgramme.add(itemBlueTV);
    menuProgramme.add(itemCanal24);
    menuProgramme.add(itemCGTN_EN);
    menuProgramme.add(itemCGTN_ES);
    menuProgramme.add(itemCGTN_FR);
    menuProgramme.add(itemDanceTV);
    menuProgramme.add(itemIndiaNews);
    menuProgramme.add(itemKABEL1);
    menuProgramme.add(itemMDR);
    menuProgramme.add(itemMir24);
    menuProgramme.add(itemNTW);
    menuProgramme.add(itemNTW_SERIAL);
    menuProgramme.add(itemPRO7);
    menuProgramme.add(itemPro7MAXX);
    menuProgramme.add(itemRai24);
    menuProgramme.add(itemRTL2);
    menuProgramme.add(itemRTL_NITRO);
    menuProgramme.add(itemRTDE);
    menuProgramme.add(itemSAT1);
    menuProgramme.add(itemSIXX);
    menuProgramme.add(itemTele5);
    menuProgramme.add(itemTeleSUR_EN);
    menuProgramme.add(itemTeleSUR_ES);
    menuProgramme.add(itemV2Beat);
    menuProgramme.add(itemVOX);
    menuProgramme.add(itemZdfinfo);

    programgroup.add(item01TV);
    programgroup.add(itemSportschau);
    programgroup.add(itemArteDeutsch);
    programgroup.add(itemArteFrance);
    programgroup.add(itemBloomberg);
    programgroup.add(itemBlueTV);
    programgroup.add(itemCanal24);
    programgroup.add(itemAguasCalientes);
    programgroup.add(itemRTL_NITRO);
    programgroup.add(itemCGTN_EN);
    programgroup.add(itemCGTN_ES);
    programgroup.add(itemCGTN_FR);
    programgroup.add(itemDanceTV);
    programgroup.add(itemIndiaNews);
    programgroup.add(itemKABEL1);
    programgroup.add(itemMDR);
    programgroup.add(itemMir24);
    programgroup.add(itemNTW);
    programgroup.add(itemNTW_SERIAL);
    programgroup.add(itemPRO7);
    programgroup.add(itemPro7MAXX);
    programgroup.add(itemRai24);
    programgroup.add(itemRTDE);
    programgroup.add(itemRTL2);
    programgroup.add(itemSAT1);
    programgroup.add(itemSIXX);
    programgroup.add(itemTele5);
    programgroup.add(itemTeleSUR_EN);
    programgroup.add(itemTeleSUR_ES);
    programgroup.add(itemAXN);
    programgroup.add(itemV2Beat);
    programgroup.add(itemVOX);
    programgroup.add(itemZdfinfo);

    item01TV.addActionListener((event) -> {
      button01TV.doClick();
    });
    itemAguasCalientes.addActionListener((event) -> {
      buttonAguasCalientes.doClick();
    });
    itemSportschau.addActionListener((event) -> {
      buttonSportschau.doClick();
    });
    itemArteDeutsch.addActionListener((event) -> {
      buttonArteDeutsch.doClick();
    });
    itemArteFrance.addActionListener((event) -> {
      buttonArteFrance.doClick();
    });
    itemBloomberg.addActionListener((event) -> {
      buttonBloomberg.doClick();
    });
    itemBlueTV.addActionListener((event) -> {
      buttonBlueTV.doClick();
    });
    itemCanal24.addActionListener((event) -> {
      buttonCanal24.doClick();
    });
    itemCGTN_EN.addActionListener((event) -> {
      buttonCGTN_EN.doClick();
    });
    itemCGTN_ES.addActionListener((event) -> {
      buttonCGTN_ES.doClick();
    });
    itemCGTN_FR.addActionListener((event) -> {
      buttonCGTN_FR.doClick();
    });
    itemKABEL1.addActionListener((event) -> {
      buttonKABEL1.doClick();
    });
    itemDanceTV.addActionListener((event) -> {
      buttonDanceTV.doClick();
    });
    itemRTL_NITRO.addActionListener((event) -> {
      buttonRTL_NITRO.doClick();
    });
    itemSAT1.addActionListener((event) -> {
      buttonSAT1.doClick();
    });
    itemMDR.addActionListener((event) -> {
      buttonMDR.doClick();
    });
    itemIndiaNews.addActionListener((event) -> {
      buttonIndiaNews.doClick();
    });
    itemMir24.addActionListener((event) -> {
      buttonMir24.doClick();
    });
    itemTele5.addActionListener((event) -> {
      buttonTele5.doClick();
    });
    itemNTW.addActionListener((event) -> {
      buttonNTW.doClick();
    });
    itemNTW_SERIAL.addActionListener((event) -> {
      buttonNTW_SERIAL.doClick();
    });
    itemTeleSUR_EN.addActionListener((event) -> {
      buttonTeleSUR_EN.doClick();
    });
    itemTeleSUR_ES.addActionListener((event) -> {
      buttonTeleSUR_ES.doClick();
    });
    itemPRO7.addActionListener((event) -> {
      buttonPRO7.doClick();
    });
    itemRTL2.addActionListener((event) -> {
      buttonRTL2.doClick();
    });
    itemRTDE.addActionListener((event) -> {
      buttonRTDE.doClick();
    });
    itemSIXX.addActionListener((event) -> {
      buttonSIXX.doClick();
    });
    itemAXN.addActionListener((event) -> {
      buttonAXN.doClick();
    });
    itemV2Beat.addActionListener((event) -> {
      buttonV2Beat.doClick();
    });
    itemRai24.addActionListener((event) -> {
      buttonRAI24.doClick();
    });
    itemVOX.addActionListener((event) -> {
      buttonVOX.doClick();
    });
    itemZdfinfo.addActionListener((event) -> {
      buttonZDFinfo.doClick();
    });
    itemPro7MAXX.addActionListener((event) -> {
      buttonPro7MAXX.doClick();
    });

    popup.addSeparator();
    popup.add(itemVollbild);
    itemVollbild.setIcon(new ImageIcon(resource.getResource(Resource.FULLSCREEN_29x26)));
    itemVollbild.addActionListener((event) -> {
      buttonVollbild.doClick();
    });
    popup.addSeparator();
    popup.add(itemLauter);
    itemLauter.setIcon(new ImageIcon(resource.getResource(Resource.LAUTER_32x26)));
    itemLauter.addActionListener(lauterListener);

    popup.add(itemLeiser);
    itemLeiser.setIcon(new ImageIcon(resource.getResource(Resource.LEISER_32x26)));
    itemLeiser.addActionListener(leiserListener);

    setContentPane(splitpaneHorizontal);
    URL url = resource.getResource(Resource.ROBOT_TV_299x264);

    scrollvideopane.setMinimumSize(new Dimension(0, 0));
    scrollvideopane.getVerticalScrollBar().setUnitIncrement(24);
    scrollvideopane.getHorizontalScrollBar().setUnitIncrement(24);

    imageRobot.setIcon(new ImageIcon(url));
    imageRobot.setOpaque(true);
    imageRobot.setHorizontalAlignment(SwingConstants.CENTER);

    // ROBOT Area
    robotListener = new MouseAdapter() {
      @Override
      public void mousePressed(MouseEvent event) {
        if (event.isPopupTrigger()) {
          popup.show(imageRobot, event.getX(), event.getY());
        }
      }



      @Override
      public void mouseReleased(MouseEvent event) {
        if (event.isPopupTrigger()) {
          popup.show(imageRobot, event.getX(), event.getY());
        }
      }

    };
    imageRobot.addMouseListener(robotListener);
    imageRobot.setCursor(dukeCursor);

    scrollvideopane.setViewportView(imageRobot);
    // scrollvideopane.setBorder(null);
    corner = new MultilingualLabel();
    // die richtige Frabe einblenden
    corner.setBackground(UIManager.getColor("nimbusSelectionBackground"));
    corner.setOpaque(true);
    eispanel.setBackground(UIManager.getColor("nimbusSelectionBackground"));
    scrollvideopane.setCorner(ScrollPaneConstants.LOWER_RIGHT_CORNER, eispanel); // ok!

    topPanel.setViewportView(buttonpanel);
    topPanel.setBorder(null);
    topPanel.getVerticalScrollBar().setUnitIncrement(12);
    topPanel.getHorizontalScrollBar().setUnitIncrement(12);
    topPanel.setMinimumSize(new Dimension(0, 0));
    topPanel.setCorner(ScrollPaneConstants.LOWER_RIGHT_CORNER, corner); // ok!
    this.setVerticalDivider(TOP_BAR);

    splitpaneVertical.setTopComponent(topPanel);
    splitpaneVertical.setBottomComponent(scrollvideopane);
    splitpaneVertical.setOneTouchExpandable(true);
    splitpaneVertical.setContinuousLayout(true);
    splitpaneVertical.setMinimumSize(new Dimension(0, 0));

    splitpaneHorizontal.setLeftComponent(splitpaneVertical);
    splitpaneHorizontal.setRightComponent(windowManager);
    splitpaneHorizontal.setDividerLocation(SCREEN_WIDTH - WindowManagerInternalFrame.SPLITWIDTH);
    splitpaneHorizontal.setOneTouchExpandable(true);
    splitpaneHorizontal.setContinuousLayout(true);

    addComponentListener(componentAdapter);

    windowManager.setMinimumSize(new Dimension(0, 0));
    windowManager.addWMListener(new PropertyChangeListener() {
      @Override
      public void propertyChange(PropertyChangeEvent event) {
        changes.firePropertyChange(event);
      }
    });

    fullscreen = new ImageIcon(resource.getResource(Resource.FULLSCREEN_58x52));
    buttonVollbild = new JButton(fullscreen);
    con.insets = new Insets(12, 6, bottom, 0);
    con.gridx = 0;
    con.gridy = 0;
    con.gridwidth = 1;
    con.gridheight = 2;
    con.fill = GridBagConstraints.NONE;
    con.weightx = 0.0;
    con.weighty = 0.0;
    con.anchor = GridBagConstraints.WEST;
    gridbag.setConstraints(buttonVollbild, con);
    buttonpanel.add(buttonVollbild);

    fullscreenListener = new ActionListener() {

      @Override
      public void actionPerformed(ActionEvent e) {
        changes.firePropertyChange(IptvFrame.class.getName(), Control.NULL, Control.FULLSIZE);
      }

    };
    buttonVollbild.addActionListener(fullscreenListener);

    con.insets = new Insets(12, 6, bottom, 0);
    con.gridx++;
    con.gridy = 0;
    con.gridwidth = 1;
    con.gridheight = 2;
    con.fill = GridBagConstraints.NONE;
    con.weightx = 0.0;
    con.weighty = 0.0;
    con.anchor = GridBagConstraints.WEST;
    gridbag.setConstraints(buttonPower, con);
    buttonpanel.add(buttonPower);
    buttonPower.setIcon(new ImageIcon(resource.getResource(Resource.POWERBUTTON_52x52)));
    buttonPower.addActionListener((event) -> {
      try {
        setClosed(true);
      }
      catch (PropertyVetoException e) {
        log.error(e.getMessage(), e.getCause());
      }
    });

    con.insets = new Insets(12, 6, 0, 0);
    con.gridx++;
    con.gridy = 0;
    con.gridwidth = 1;
    con.gridheight = 1;
    con.fill = GridBagConstraints.HORIZONTAL;
    con.weightx = 0.0;
    con.weighty = 0.0;
    con.anchor = GridBagConstraints.WEST;
    gridbag.setConstraints(button01TV, con);
    buttonpanel.add(button01TV);

    con.insets = new Insets(12, 6, 0, 0);
    con.gridx++;
    con.gridy = 0;
    con.gridwidth = 1;
    con.gridheight = 1;
    con.fill = GridBagConstraints.HORIZONTAL;
    con.weightx = 0.0;
    con.weighty = 0.0;
    con.anchor = GridBagConstraints.WEST;
    gridbag.setConstraints(buttonAguasCalientes, con);
    buttonpanel.add(buttonAguasCalientes);

    con.insets = new Insets(12, 6, 0, 0);
    con.gridx++;
    con.gridy = 0;
    con.gridwidth = 1;
    con.gridheight = 1;
    con.fill = GridBagConstraints.HORIZONTAL;
    con.weightx = 0.0;
    con.weighty = 0.0;
    con.anchor = GridBagConstraints.WEST;
    gridbag.setConstraints(buttonSportschau, con);
    buttonpanel.add(buttonSportschau);

    con.insets = new Insets(12, 6, 0, 0);
    con.gridx++;
    con.gridy = 0;
    con.gridwidth = 1;
    con.gridheight = 1;
    con.fill = GridBagConstraints.HORIZONTAL;
    con.weightx = 0.0;
    con.weighty = 0.0;
    con.anchor = GridBagConstraints.WEST;
    gridbag.setConstraints(buttonArteDeutsch, con);
    buttonpanel.add(buttonArteDeutsch);

    con.insets = new Insets(12, 6, 0, 0);
    con.gridx++;
    con.gridy = 0;
    con.gridwidth = 1;
    con.gridheight = 1;
    con.fill = GridBagConstraints.HORIZONTAL;
    con.weightx = 0.0;
    con.weighty = 0.0;
    con.anchor = GridBagConstraints.WEST;
    gridbag.setConstraints(buttonArteFrance, con);
    buttonpanel.add(buttonArteFrance);

    con.insets = new Insets(12, 6, 0, 0);
    con.gridx++;
    con.gridy = 0;
    con.gridwidth = 1;
    con.gridheight = 1;
    con.fill = GridBagConstraints.HORIZONTAL;
    con.weightx = 0.0;
    con.weighty = 0.0;
    con.anchor = GridBagConstraints.WEST;
    gridbag.setConstraints(buttonAXN, con);
    buttonpanel.add(buttonAXN);

    con.insets = new Insets(12, 6, 0, 0);
    con.gridx++;
    con.gridy = 0;
    con.gridwidth = 1;
    con.gridheight = 1;
    con.fill = GridBagConstraints.HORIZONTAL;
    con.weightx = 0.0;
    con.weighty = 0.0;
    con.anchor = GridBagConstraints.WEST;
    gridbag.setConstraints(buttonBloomberg, con);
    buttonpanel.add(buttonBloomberg);

    con.insets = new Insets(12, 6, 0, 0);
    con.gridx++;
    con.gridy = 0;
    con.gridwidth = 1;
    con.gridheight = 1;
    con.fill = GridBagConstraints.HORIZONTAL;
    con.weightx = 0.0;
    con.weighty = 0.0;
    con.anchor = GridBagConstraints.WEST;
    gridbag.setConstraints(buttonBlueTV, con);
    buttonpanel.add(buttonBlueTV);

    con.insets = new Insets(12, 6, 0, 0);
    con.gridx++;
    con.gridy = 0;
    con.gridwidth = 1;
    con.gridheight = 1;
    con.fill = GridBagConstraints.HORIZONTAL;
    con.weightx = 0.0;
    con.weighty = 0.0;
    con.anchor = GridBagConstraints.WEST;
    gridbag.setConstraints(buttonCanal24, con);
    buttonpanel.add(buttonCanal24);

    con.insets = new Insets(12, 6, 0, 0);
    con.gridx++;
    con.gridy = 0;
    con.gridwidth = 1;
    con.gridheight = 1;
    con.fill = GridBagConstraints.HORIZONTAL;
    con.weightx = 0.0;
    con.weighty = 0.0;
    con.anchor = GridBagConstraints.WEST;
    gridbag.setConstraints(buttonCGTN_EN, con);
    buttonpanel.add(buttonCGTN_EN);

    con.insets = new Insets(12, 6, 0, 0);
    con.gridx++;
    con.gridy = 0;
    con.gridwidth = 1;
    con.gridheight = 1;
    con.fill = GridBagConstraints.HORIZONTAL;
    con.weightx = 0.0;
    con.weighty = 0.0;
    con.anchor = GridBagConstraints.WEST;
    gridbag.setConstraints(buttonCGTN_FR, con);
    buttonpanel.add(buttonCGTN_FR);

    con.insets = new Insets(6, 6, bottom, 0);
    con.gridx = 2;
    con.gridy = 1;
    con.gridwidth = 1;
    con.gridheight = 1;
    con.fill = GridBagConstraints.HORIZONTAL;
    con.weightx = 0.0;
    con.weighty = 0.0;
    con.anchor = GridBagConstraints.WEST;
    gridbag.setConstraints(buttonCGTN_ES, con);
    buttonpanel.add(buttonCGTN_ES);

    con.insets = new Insets(6, 6, bottom, 0);
    con.gridx++;
    con.gridy = 1;
    con.gridwidth = 1;
    con.gridheight = 1;
    con.fill = GridBagConstraints.HORIZONTAL;
    con.weightx = 0.0;
    con.weighty = 0.0;
    con.anchor = GridBagConstraints.WEST;
    gridbag.setConstraints(buttonDanceTV, con);
    buttonpanel.add(buttonDanceTV);

    con.insets = new Insets(6, 6, bottom, 0);
    con.gridx++;
    con.gridy = 1;
    con.gridwidth = 1;
    con.gridheight = 1;
    con.fill = GridBagConstraints.HORIZONTAL;
    con.weightx = 0.0;
    con.weighty = 0.0;
    con.anchor = GridBagConstraints.WEST;
    gridbag.setConstraints(buttonIndiaNews, con);
    buttonpanel.add(buttonIndiaNews);

    con.insets = new Insets(6, 6, bottom, 0);
    con.gridx++;
    con.gridy = 1;
    con.gridwidth = 1;
    con.gridheight = 1;
    con.fill = GridBagConstraints.HORIZONTAL;
    con.weightx = 0.0;
    con.weighty = 0.0;
    con.anchor = GridBagConstraints.WEST;
    gridbag.setConstraints(buttonKABEL1, con);
    buttonpanel.add(buttonKABEL1);

    con.insets = new Insets(6, 6, bottom, 0);
    con.gridx++;
    con.gridy = 1;
    con.gridwidth = 1;
    con.gridheight = 1;
    con.fill = GridBagConstraints.HORIZONTAL;
    con.weightx = 0.0;
    con.weighty = 0.0;
    con.anchor = GridBagConstraints.WEST;
    gridbag.setConstraints(buttonMDR, con);
    buttonpanel.add(buttonMDR);

    con.insets = new Insets(6, 6, bottom, 0);
    con.gridx++;
    con.gridy = 1;
    con.gridwidth = 1;
    con.gridheight = 1;
    con.fill = GridBagConstraints.HORIZONTAL;
    con.weightx = 0.0;
    con.weighty = 0.0;
    con.anchor = GridBagConstraints.WEST;
    gridbag.setConstraints(buttonMir24, con);
    buttonpanel.add(buttonMir24);

    con.insets = new Insets(6, 6, bottom, 0);
    con.gridx++;
    con.gridy = 1;
    con.gridwidth = 1;
    con.gridheight = 1;
    con.fill = GridBagConstraints.HORIZONTAL;
    con.weightx = 0.0;
    con.weighty = 0.0;
    con.anchor = GridBagConstraints.WEST;
    gridbag.setConstraints(buttonNTW, con);
    buttonpanel.add(buttonNTW);

    con.insets = new Insets(6, 6, bottom, 0);
    con.gridx++;
    con.gridy = 1;
    con.gridwidth = 1;
    con.gridheight = 1;
    con.fill = GridBagConstraints.HORIZONTAL;
    con.weightx = 0.0;
    con.weighty = 0.0;
    con.anchor = GridBagConstraints.WEST;
    gridbag.setConstraints(buttonNTW_SERIAL, con);
    buttonpanel.add(buttonNTW_SERIAL);

    con.insets = new Insets(6, 6, bottom, 0);
    con.gridx++;
    con.gridy = 1;
    con.gridwidth = 1;
    con.gridheight = 1;
    con.fill = GridBagConstraints.HORIZONTAL;
    con.weightx = 0.0;
    con.weighty = 0.0;
    con.anchor = GridBagConstraints.WEST;
    gridbag.setConstraints(buttonPRO7, con);
    buttonpanel.add(buttonPRO7);

    con.insets = new Insets(6, 6, bottom, 0);
    con.gridx++;
    con.gridy = 1;
    con.gridwidth = 1;
    con.gridheight = 1;
    con.fill = GridBagConstraints.HORIZONTAL;
    con.weightx = 0.0;
    con.weighty = 0.0;
    con.anchor = GridBagConstraints.WEST;
    gridbag.setConstraints(buttonPro7MAXX, con);
    buttonpanel.add(buttonPro7MAXX);

    con.insets = new Insets(6, 6, bottom, 0);
    con.gridx++;
    con.gridy = 1;
    con.gridwidth = 1;
    con.gridheight = 1;
    con.fill = GridBagConstraints.HORIZONTAL;
    con.weightx = 0.0;
    con.weighty = 0.0;
    con.anchor = GridBagConstraints.WEST;
    gridbag.setConstraints(buttonRAI24, con);
    buttonpanel.add(buttonRAI24);

    con.insets = new Insets(0, 6, bottom, 0);
    con.gridx = 2;
    con.gridy = 2;
    con.gridwidth = 1;
    con.gridheight = 1;
    con.fill = GridBagConstraints.HORIZONTAL;
    con.weightx = 0.0;
    con.weighty = 0.0;
    con.anchor = GridBagConstraints.WEST;
    gridbag.setConstraints(buttonRTDE, con);
    buttonpanel.add(buttonRTDE);

    con.insets = new Insets(0, 6, bottom, 0);
    con.gridx++;
    con.gridy = 2;
    con.gridwidth = 1;
    con.gridheight = 1;
    con.fill = GridBagConstraints.HORIZONTAL;
    con.weightx = 0.0;
    con.weighty = 0.0;
    con.anchor = GridBagConstraints.WEST;
    gridbag.setConstraints(buttonRTL2, con);
    buttonpanel.add(buttonRTL2);

    con.insets = new Insets(0, 6, bottom, 0);
    con.gridx++;
    con.gridy = 2;
    con.gridwidth = 1;
    con.gridheight = 1;
    con.fill = GridBagConstraints.HORIZONTAL;
    con.weightx = 0.0;
    con.weighty = 0.0;
    con.anchor = GridBagConstraints.WEST;
    gridbag.setConstraints(buttonRTL_NITRO, con);
    buttonpanel.add(buttonRTL_NITRO);

    con.insets = new Insets(0, 6, bottom, 0);
    con.gridx++;
    con.gridy = 2;
    con.gridwidth = 1;
    con.gridheight = 1;
    con.fill = GridBagConstraints.HORIZONTAL;
    con.weightx = 0.0;
    con.weighty = 0.0;
    con.anchor = GridBagConstraints.WEST;
    gridbag.setConstraints(buttonSAT1, con);
    buttonpanel.add(buttonSAT1);

    con.insets = new Insets(0, 6, bottom, 0);
    con.gridx++;
    con.gridy = 2;
    con.gridwidth = 1;
    con.gridheight = 1;
    con.fill = GridBagConstraints.HORIZONTAL;
    con.weightx = 0.0;
    con.weighty = 0.0;
    con.anchor = GridBagConstraints.WEST;
    gridbag.setConstraints(buttonSIXX, con);
    buttonpanel.add(buttonSIXX);

    con.insets = new Insets(0, 6, bottom, 0);
    con.gridx++;
    con.gridy = 2;
    con.gridwidth = 1;
    con.gridheight = 1;
    con.fill = GridBagConstraints.HORIZONTAL;
    con.weightx = 0.0;
    con.weighty = 0.0;
    con.anchor = GridBagConstraints.WEST;
    gridbag.setConstraints(buttonTele5, con);
    buttonpanel.add(buttonTele5);

    con.insets = new Insets(0, 6, bottom, 0);
    con.gridx++;
    con.gridy = 2;
    con.gridwidth = 1;
    con.gridheight = 1;
    con.fill = GridBagConstraints.HORIZONTAL;
    con.weightx = 0.0;
    con.weighty = 0.0;
    con.anchor = GridBagConstraints.WEST;
    gridbag.setConstraints(buttonTeleSUR_EN, con);
    buttonpanel.add(buttonTeleSUR_EN);

    con.insets = new Insets(0, 6, bottom, 0);
    con.gridx++;
    con.gridy = 2;
    con.gridwidth = 1;
    con.gridheight = 1;
    con.fill = GridBagConstraints.HORIZONTAL;
    con.weightx = 0.0;
    con.weighty = 0.0;
    con.anchor = GridBagConstraints.WEST;
    gridbag.setConstraints(buttonTeleSUR_ES, con);
    buttonpanel.add(buttonTeleSUR_ES);

    con.insets = new Insets(0, 6, bottom, 0);
    con.gridx++;
    con.gridy = 2;
    con.gridwidth = 1;
    con.gridheight = 1;
    con.fill = GridBagConstraints.HORIZONTAL;
    con.weightx = 0.0;
    con.weighty = 0.0;
    con.anchor = GridBagConstraints.WEST;
    gridbag.setConstraints(buttonV2Beat, con);
    buttonpanel.add(buttonV2Beat);

    con.insets = new Insets(0, 6, bottom, 0);
    con.gridx++;
    con.gridy = 2;
    con.gridwidth = 1;
    con.gridheight = 1;
    con.fill = GridBagConstraints.HORIZONTAL;
    con.weightx = 0.0;
    con.weighty = 0.0;
    con.anchor = GridBagConstraints.WEST;
    gridbag.setConstraints(buttonVOX, con);
    buttonpanel.add(buttonVOX);

    con.insets = new Insets(0, 6, bottom, 0);
    con.gridx++;
    con.gridy = 2;
    con.gridwidth = 1;
    con.gridheight = 1;
    con.fill = GridBagConstraints.HORIZONTAL;
    con.weightx = 0.0;
    con.weighty = 0.0;
    con.anchor = GridBagConstraints.WEST;
    gridbag.setConstraints(buttonZDFinfo, con);
    buttonpanel.add(buttonZDFinfo);

    con.insets = new Insets(12, 6, bottom, 0);
    con.gridx = 5;
    con.gridy = 3;
    con.gridwidth = 6;
    con.gridheight = 1;
    con.fill = GridBagConstraints.HORIZONTAL;
    con.weightx = 0.0;
    con.weighty = 0.0;
    con.anchor = GridBagConstraints.WEST;
    gridbag.setConstraints(volumePanel, con);
    buttonpanel.add(volumePanel);
    volumePanel.addVolumeListener(volumelistener);

    buttonMDR.addActionListener((event) -> {
      shutdown();
      setDisabled();
      if (sender == TVSender.MDR) {
        sender = null;
        return;
      }
      buttonMDR.setBackground(Resource.JQUERY_GREEN);
      buttonMDR.setForeground(Color.WHITE);
      itemMDR.setSelected(true);
      sender = TVSender.MDR;
      connect(buttonMDR.getUrl());
    });

    buttonArteDeutsch.addActionListener((event) -> {
      shutdown();
      setDisabled();
      if (sender == TVSender.ARTE_DEUTSCH) {
        sender = null;
        return;
      }
      buttonArteDeutsch.setBackground(Resource.JQUERY_GREEN);
      buttonArteDeutsch.setForeground(Color.WHITE);
      itemArteDeutsch.setSelected(true);
      connect(buttonArteDeutsch.getUrl());
      sender = TVSender.ARTE_DEUTSCH;
    });
    buttonArteFrance.addActionListener((event) -> {
      shutdown();
      setDisabled();
      if (sender == TVSender.ARTE_FRANKREICH) {
        sender = null;
        return;
      }
      buttonArteFrance.setBackground(Resource.JQUERY_GREEN);
      buttonArteFrance.setForeground(Color.WHITE);
      itemArteFrance.setSelected(true);
      sender = TVSender.ARTE_FRANKREICH;
      connect(buttonArteFrance.getUrl());
    });
    buttonSportschau.addActionListener((event) -> {
      shutdown();
      setDisabled();
      if (sender == TVSender.ARD_SPORTSCHAU_LIVE) {
        sender = null;
        return;
      }
      buttonSportschau.setBackground(Resource.JQUERY_GREEN);
      buttonSportschau.setForeground(Color.WHITE);
      itemSportschau.setSelected(true);
      sender = TVSender.ARD_SPORTSCHAU_LIVE;
      connect(buttonSportschau.getUrl());

    });

    buttonBloomberg.addActionListener((event) -> {
      shutdown();
      setDisabled();
      if (sender == TVSender.BLOOMBERG) {
        sender = null;
        return;
      }
      buttonBloomberg.setBackground(Resource.JQUERY_GREEN);
      buttonBloomberg.setForeground(Color.WHITE);
      itemBloomberg.setSelected(true);
      sender = TVSender.BLOOMBERG;
      connect(buttonBloomberg.getUrl());
    });

    buttonSIXX.addActionListener((event) -> {
      shutdown();
      setDisabled();
      if (sender == TVSender.SIXX) {
        sender = null;
        return;
      }
      buttonSIXX.setBackground(Resource.JQUERY_GREEN);
      buttonSIXX.setForeground(Color.WHITE);
      itemSIXX.setSelected(true);
      sender = TVSender.SIXX;
      connect(buttonSIXX.getUrl());
    });

    buttonBlueTV.addActionListener((event) -> {
      shutdown();
      setDisabled();
      if (sender == TVSender.BLUETV) {
        sender = null;
        return;
      }
      buttonBlueTV.setBackground(Resource.JQUERY_GREEN);
      buttonBlueTV.setForeground(Color.WHITE);
      itemBlueTV.setSelected(true);
      sender = TVSender.BLUETV;
      connect(buttonBlueTV.getUrl());
    });

    buttonCanal24.addActionListener((event) -> {
      shutdown();
      setDisabled();
      if (sender == TVSender.CANAL_24) {
        sender = null;
        return;
      }
      buttonCanal24.setBackground(Resource.JQUERY_GREEN);
      buttonCanal24.setForeground(Color.WHITE);
      itemCanal24.setSelected(true);
      sender = TVSender.CANAL_24;
      connect(buttonCanal24.getUrl());
    });

    buttonPRO7.addActionListener((event) -> {
      shutdown();
      setDisabled();
      if (sender == TVSender.PRO7) {
        sender = null;
        return;
      }
      buttonPRO7.setBackground(Resource.JQUERY_GREEN);
      buttonPRO7.setForeground(Color.WHITE);
      itemPRO7.setSelected(true);
      sender = TVSender.PRO7;
      connect(buttonPRO7.getUrl());
    });

    buttonAXN.addActionListener((event) -> {
      shutdown();
      setDisabled();
      if (sender == TVSender.AXN) {
        sender = null;
        return;
      }
      buttonAXN.setBackground(Resource.JQUERY_GREEN);
      buttonAXN.setForeground(Color.WHITE);
      itemAXN.setSelected(true);
      sender = TVSender.AXN;
      connect(buttonAXN.getUrl());
    });

    buttonRAI24.addActionListener((event) -> {
      shutdown();
      setDisabled();
      if (sender == TVSender.RAI24) {
        sender = null;
        return;
      }
      buttonRAI24.setBackground(Resource.JQUERY_GREEN);
      buttonRAI24.setForeground(Color.WHITE);
      itemRai24.setSelected(true);
      sender = TVSender.RAI24;
      connect(buttonRAI24.getUrl());
    });

    buttonZDFinfo.addActionListener((event) -> {
      shutdown();
      setDisabled();
      if (sender == TVSender.ZDFinfo) {
        sender = null;
        return;
      }
      buttonZDFinfo.setBackground(Resource.JQUERY_GREEN);
      buttonZDFinfo.setForeground(Color.WHITE);
      itemZdfinfo.setSelected(true);
      sender = TVSender.ZDFinfo;
      connect(buttonZDFinfo.getUrl());
    });

    buttonVOX.addActionListener((event) -> {
      shutdown();
      setDisabled();
      if (sender == TVSender.VOX) {
        sender = null;
        return;
      }
      buttonVOX.setBackground(Resource.JQUERY_GREEN);
      buttonVOX.setForeground(Color.WHITE);
      itemVOX.setSelected(true);
      sender = TVSender.VOX;
      connect(buttonVOX.getUrl());
    });

    buttonDanceTV.addActionListener((event) -> {
      shutdown();
      setDisabled();
      if (sender == TVSender.DANCE_TV) {
        sender = null;
        return;
      }
      buttonDanceTV.setBackground(Resource.JQUERY_GREEN);
      buttonDanceTV.setForeground(Color.WHITE);
      itemDanceTV.setSelected(true);
      sender = TVSender.DANCE_TV;
      connect(buttonDanceTV.getUrl());
    });

    buttonSAT1.addActionListener((event) -> {
      shutdown();
      setDisabled();
      if (sender == TVSender.SAT1) {
        sender = null;
        return;
      }
      buttonSAT1.setBackground(Resource.JQUERY_GREEN);
      buttonSAT1.setForeground(Color.WHITE);
      itemSAT1.setSelected(true);
      sender = TVSender.SAT1;
      connect(buttonSAT1.getUrl());
    });

    buttonV2Beat.addActionListener((event) -> {
      shutdown();
      setDisabled();
      if (sender == TVSender.V2BeatTV) {
        sender = null;
        return;
      }
      buttonV2Beat.setBackground(Resource.JQUERY_GREEN);
      buttonV2Beat.setForeground(Color.WHITE);
      itemV2Beat.setSelected(true);
      sender = TVSender.V2BeatTV;
      connect(buttonV2Beat.getUrl());
    });

    buttonTele5.addActionListener((event) -> {
      shutdown();
      setDisabled();
      if (sender == TVSender.TELE5) {
        sender = null;
        return;
      }
      buttonTele5.setBackground(Resource.JQUERY_GREEN);
      buttonTele5.setForeground(Color.WHITE);
      itemTele5.setSelected(true);
      sender = TVSender.TELE5;
      connect(buttonTele5.getUrl());
    });

    buttonRTDE.addActionListener((event) -> {
      shutdown();
      setDisabled();
      if (sender == TVSender.RTDE) {
        sender = null;
        return;
      }
      buttonRTDE.setBackground(Resource.JQUERY_GREEN);
      buttonRTDE.setForeground(Color.WHITE);
      itemRTDE.setSelected(true);
      sender = TVSender.RTDE;
      connect(buttonRTDE.getUrl());
    });

    buttonRTL2.addActionListener((event) -> {
      shutdown();
      setDisabled();
      if (sender == TVSender.RTL_2) {
        sender = null;
        return;
      }
      buttonRTL2.setBackground(Resource.JQUERY_GREEN);
      buttonRTL2.setForeground(Color.WHITE);
      itemRTL2.setSelected(true);
      sender = TVSender.RTL_2;
      connect(buttonRTL2.getUrl());
    });

    buttonIndiaNews.addActionListener((event) -> {
      shutdown();
      setDisabled();
      if (sender == TVSender.INDIA_NEWS) {
        sender = null;
        return;
      }
      buttonIndiaNews.setBackground(Resource.JQUERY_GREEN);
      buttonIndiaNews.setForeground(Color.WHITE);
      itemIndiaNews.setSelected(true);
      sender = TVSender.INDIA_NEWS;
      connect(buttonIndiaNews.getUrl());
    });

    buttonMir24.addActionListener((event) -> {
      shutdown();
      setDisabled();
      if (sender == TVSender.MIR24) {
        sender = null;
        return;
      }
      buttonMir24.setBackground(Resource.JQUERY_GREEN);
      buttonMir24.setForeground(Color.WHITE);
      itemMir24.setSelected(true);
      sender = TVSender.MIR24;
      connect(buttonMir24.getUrl());
    });

    buttonNTW.addActionListener((event) -> {
      shutdown();
      setDisabled();
      if (sender == TVSender.NTW) {
        sender = null;
        return;
      }
      buttonNTW.setBackground(Resource.JQUERY_GREEN);
      buttonNTW.setForeground(Color.WHITE);
      itemNTW.setSelected(true);
      sender = TVSender.NTW;
      connect(buttonNTW.getUrl());
    });

    buttonCGTN_EN.addActionListener((event) -> {
      shutdown();
      setDisabled();
      if (sender == TVSender.CGTN_EN) {
        sender = null;
        return;
      }
      buttonCGTN_EN.setBackground(Resource.JQUERY_GREEN);
      buttonCGTN_EN.setForeground(Color.WHITE);
      itemCGTN_EN.setSelected(true);
      sender = TVSender.CGTN_EN;
      connect(buttonCGTN_EN.getUrl());
    });

    buttonCGTN_ES.addActionListener((event) -> {
      shutdown();
      setDisabled();
      if (sender == TVSender.CGTN_ES) {
        sender = null;
        return;
      }
      buttonCGTN_ES.setBackground(Resource.JQUERY_GREEN);
      buttonCGTN_ES.setForeground(Color.WHITE);
      itemCGTN_ES.setSelected(true);
      sender = TVSender.CGTN_ES;
      connect(buttonCGTN_ES.getUrl());
    });

    buttonCGTN_FR.addActionListener((event) -> {
      shutdown();
      setDisabled();
      if (sender == TVSender.CGTN_FR) {
        sender = null;
        return;
      }
      buttonCGTN_FR.setBackground(Resource.JQUERY_GREEN);
      buttonCGTN_FR.setForeground(Color.WHITE);
      itemCGTN_FR.setSelected(true);
      sender = TVSender.CGTN_FR;
      connect(buttonCGTN_FR.getUrl());
    });

    buttonKABEL1.addActionListener((event) -> {
      shutdown();
      setDisabled();
      if (sender == TVSender.KABEL1) {
        sender = null;
        return;
      }
      buttonKABEL1.setBackground(Resource.JQUERY_GREEN);
      buttonKABEL1.setForeground(Color.WHITE);
      itemKABEL1.setSelected(true);
      sender = TVSender.KABEL1;
      connect(buttonKABEL1.getUrl());
    });

    button01TV.addActionListener((event) -> {
      shutdown();
      setDisabled();
      if (sender == TVSender.O1TV) {
        sender = null;
        return;
      }
      button01TV.setBackground(Resource.JQUERY_GREEN);
      button01TV.setForeground(Color.WHITE);
      item01TV.setSelected(true);
      sender = TVSender.O1TV;
      connect(button01TV.getUrl());
    });

    buttonTeleSUR_ES.addActionListener((event) -> {
      shutdown();
      setDisabled();
      if (sender == TVSender.teleSUR_ES) {
        sender = null;
        return;
      }
      buttonTeleSUR_ES.setBackground(Resource.JQUERY_GREEN);
      buttonTeleSUR_ES.setForeground(Color.WHITE);
      itemTeleSUR_ES.setSelected(true);
      sender = TVSender.teleSUR_ES;
      connect(buttonTeleSUR_ES.getUrl());
    });

    buttonTeleSUR_EN.addActionListener((event) -> {
      shutdown();
      setDisabled();
      if (sender == TVSender.teleSUR_EN) {
        sender = null;
        return;
      }
      buttonTeleSUR_EN.setBackground(Resource.JQUERY_GREEN);
      buttonTeleSUR_EN.setForeground(Color.WHITE);
      itemTeleSUR_EN.setSelected(true);
      sender = TVSender.teleSUR_EN;
      connect(buttonTeleSUR_EN.getUrl());
    });

    buttonAguasCalientes.addActionListener((event) -> {
      shutdown();
      setDisabled();
      if (sender == TVSender.AGUASCALIENTES) {
        sender = null;
        return;
      }
      buttonAguasCalientes.setBackground(Resource.JQUERY_GREEN);
      buttonAguasCalientes.setForeground(Color.WHITE);
      itemAguasCalientes.setSelected(true);
      sender = TVSender.AGUASCALIENTES;
      connect(buttonAguasCalientes.getUrl());
    });

    buttonRTL_NITRO.addActionListener((event) -> {
      shutdown();
      setDisabled();
      if (sender == TVSender.RTL_NITRO) {
        sender = null;
        return;
      }
      buttonRTL_NITRO.setBackground(Resource.JQUERY_GREEN);
      buttonRTL_NITRO.setForeground(Color.WHITE);
      itemRTL_NITRO.setSelected(true);
      sender = TVSender.RTL_NITRO;
      connect(buttonRTL_NITRO.getUrl());
    });

    buttonNTW_SERIAL.addActionListener((event) -> {
      shutdown();
      setDisabled();
      if (sender == TVSender.NTW_SERIAL) {
        sender = null;
        return;
      }
      buttonNTW_SERIAL.setBackground(Resource.JQUERY_GREEN);
      buttonNTW_SERIAL.setForeground(Color.WHITE);
      itemNTW_SERIAL.setSelected(true);
      sender = TVSender.NTW_SERIAL;
      connect(buttonNTW_SERIAL.getUrl());
    });

    buttonPro7MAXX.addActionListener((event) -> {
      shutdown();
      setDisabled();
      if (sender == TVSender.PRO7MAXX) {
        sender = null;
        return;
      }
      buttonPro7MAXX.setBackground(Resource.JQUERY_GREEN);
      buttonPro7MAXX.setForeground(Color.WHITE);
      itemPro7MAXX.setSelected(true);
      sender = TVSender.PRO7MAXX;
      connect(buttonPro7MAXX.getUrl());
    });

    // TODO weitere Sender

  }

  // public void start() {
  // start("udp://localhost@:29478");
  // }



  @Override
  public void insertWM(WM value) {
    windowManager.addWindow(value);
  }



  public void registerComponentAdapter() {
    addComponentListener(componentAdapter);
  }



  public synchronized void removeAllListener() {
    for (PropertyChangeListener tmp : changes.getPropertyChangeListeners()) {
      removeIptvListener(tmp);
    }
    windowManager.removeAllListener();
    for (Component comp : buttonpanel.getComponents()) {
      if (comp instanceof JButton button) {
        try {
          button.removeActionListener(button.getActionListeners()[0]);
        }
        catch (ArrayIndexOutOfBoundsException e) {}
      }
    }
    removeComponentListener(componentAdapter);
    buttonVollbild.removeActionListener(fullscreenListener);
    volumePanel.removePropertyChangeListener(volumelistener);
    if (videosurface != null) {
      // MouseAdapter entfernen
      videosurface.removeMouseListener(videosurfaceListener);
    }
    itemLauter.removeActionListener(lauterListener);
    itemLeiser.removeActionListener(leiserListener);
    imageRobot.removeMouseListener(robotListener);

  }



  public synchronized void removeIptvListener(PropertyChangeListener listener) {
    changes.removePropertyChangeListener(listener);
  }



  @Override
  public void removeWM(WM frame) {
    windowManager.removeWM(frame);
  }



  @Override
  public void ringRing(WindowAnrufenEvent event) {
    extText = event.getNickname();
    getMultiAbnehmen().setLanguage(KEY.FRAME_ABNEHMEN, event.getCode(), extText);
    getMultiAnrufen().setLanguage(KEY.TELEFON_ANRUFEN, event.getCode(), extText);
  }



  void setDisabled() {
    for (Component comp : buttonpanel.getComponents()) {
      if (comp instanceof JButton button) {
        button.setForeground(WMResource.ENABLED_BUTTON_FOREGROUND);
        button.setBackground(WMResource.ENABLED_BUTTON_BACKGROUND);
      }
    }
  }



  @Override
  public void setFrameTitleId(String id) {
    record = id;
    setTitle(record);
  }



  /**
   * Die Trennleiste wird in horizontaler Richtung positioniert. Die Angabe
   * erfolgt in Prozent. 0-Prozent ist ganz links und 100-Prozent ist ganz rechts.
   *
   * @param prozent
   *                liegt im Intervall [0..1]
   */
  public void setHorizontalDivider(double prozent) {
    if (0 > prozent || prozent > 1) {
      log.warn(prozent + " - die Prozentangabe liegt nicht im Intervall [0..1]");
    }
    splitpaneHorizontal.setDividerLocation(prozent);
  }



  /**
   * Die Trennleiste wird in horizontaler Richtung positioniert. Die Angabe
   * erfolgt in Pixel. 0 ist ganz links und {@code SCREEN_WIDTH} ist ganz rechts.
   *
   *
   * @param pixel
   *              die X-Position
   */
  public void setHorizontalDivider(int pixel) {
    splitpaneHorizontal.setDividerLocation(pixel);
  }



  public void setIptvvolume(int volume) {
    volumePanel.setLoudness(volume);
  }



  @Override
  public void setLanguage(ISO639 code) {
    volumePanel.setLanguage(code);
    itemLauter.setLanguage(code);
    itemLeiser.setLanguage(code);
    menuProgramme.setLanguage(code);
    itemVollbild.setLanguage(code);
    treeView(code);
  }



  /**
   * Alle TV Sender werden übergeben. Die Sender liegen im JSON-Format vor. Das
   * Format ist {@code code|programmname|url} mit den Typen
   * {@code int:String:String}. Das Attribut {@code programmname} muss gleich dem
   * Knopfnamen sein.
   *
   *
   * @param senderliste
   *                    alle Sender
   */
  public void setSenderliste(List<String> senderliste) {

    // über eine HashMap
    HashMap<String, String> name_url = new HashMap<>(senderliste.size());
    name_url.put(buttonArteDeutsch.getText(), "");
    name_url.put(buttonArteFrance.getText(), "");
    name_url.put(buttonSportschau.getText(), "");
    name_url.put(buttonSIXX.getText(), "");
    name_url.put(buttonRAI24.getText(), "");
    name_url.put(buttonVOX.getText(), "");
    name_url.put(buttonCanal24.getText(), "");
    name_url.put(buttonAXN.getText(), "");
    name_url.put(buttonMDR.getText(), "");
    name_url.put(buttonZDFinfo.getText(), "");
    name_url.put(buttonPRO7.getText(), "");
    name_url.put(buttonBlueTV.getText(), "");
    name_url.put(buttonDanceTV.getText(), "");
    name_url.put(buttonBloomberg.getText(), "");
    name_url.put(buttonSAT1.getText(), "");
    name_url.put(buttonV2Beat.getText(), "");
    name_url.put(buttonTele5.getText(), "");
    name_url.put(buttonRTDE.getText(), "");
    name_url.put(buttonRTL2.getText(), "");
    name_url.put(buttonIndiaNews.getText(), "");
    name_url.put(buttonMir24.getText(), "");
    name_url.put(buttonNTW.getText(), "");
    name_url.put(buttonCGTN_EN.getText(), "");
    name_url.put(buttonCGTN_ES.getText(), "");
    name_url.put(buttonCGTN_FR.getText(), "");
    name_url.put(buttonKABEL1.getText(), "");
    name_url.put(button01TV.getText(), "");
    name_url.put(buttonTeleSUR_ES.getText(), "");
    name_url.put(buttonTeleSUR_EN.getText(), "");
    name_url.put(buttonAguasCalientes.getText(), "");
    name_url.put(buttonRTL_NITRO.getText(), "");
    name_url.put(buttonNTW_SERIAL.getText(), "");
    name_url.put(buttonPro7MAXX.getText(), "");
    Gson gson = gsonbuilder.create();
    senderliste.forEach((item) -> {
      Sender result = gson.fromJson(item, Sender.class); // Reflection
      name_url.put(result.getProgrammname(), result.getUrl());
    });

    buttonArteDeutsch.setUrl(name_url.get(buttonArteDeutsch.getText()));
    buttonArteFrance.setUrl(name_url.get(buttonArteFrance.getText()));
    buttonSportschau.setUrl(name_url.get(buttonSportschau.getText()));
    buttonSIXX.setUrl(name_url.get(buttonSIXX.getText()));
    buttonRAI24.setUrl(name_url.get(buttonRAI24.getText()));
    buttonVOX.setUrl(name_url.get(buttonVOX.getText()));
    buttonCanal24.setUrl(name_url.get(buttonCanal24.getText()));
    buttonAXN.setUrl(name_url.get(buttonAXN.getText()));
    buttonMDR.setUrl(name_url.get(buttonMDR.getText()));
    buttonZDFinfo.setUrl(name_url.get(buttonZDFinfo.getText()));
    buttonPRO7.setUrl(name_url.get(buttonPRO7.getText()));
    buttonBlueTV.setUrl(name_url.get(buttonBlueTV.getText()));
    buttonDanceTV.setUrl(name_url.get(buttonDanceTV.getText()));
    buttonBloomberg.setUrl(name_url.get(buttonBloomberg.getText()));
    buttonSAT1.setUrl(name_url.get(buttonSAT1.getText()));
    buttonV2Beat.setUrl(name_url.get(buttonV2Beat.getText()));
    buttonTele5.setUrl(name_url.get(buttonTele5.getText()));
    buttonRTDE.setUrl(name_url.get(buttonRTDE.getText()));
    buttonRTL2.setUrl(name_url.get(buttonRTL2.getText()));
    buttonIndiaNews.setUrl(name_url.get(buttonIndiaNews.getText()));
    buttonMir24.setUrl(name_url.get(buttonMir24.getText()));
    buttonNTW.setUrl(name_url.get(buttonNTW.getText()));
    buttonCGTN_EN.setUrl(name_url.get(buttonCGTN_EN.getText()));
    buttonCGTN_ES.setUrl(name_url.get(buttonCGTN_ES.getText()));
    buttonCGTN_FR.setUrl(name_url.get(buttonCGTN_FR.getText()));
    buttonKABEL1.setUrl(name_url.get(buttonKABEL1.getText()));
    button01TV.setUrl(name_url.get(button01TV.getText()));
    buttonTeleSUR_ES.setUrl(name_url.get(buttonTeleSUR_ES.getText()));
    buttonTeleSUR_EN.setUrl(name_url.get(buttonTeleSUR_EN.getText()));
    buttonAguasCalientes.setUrl(name_url.get(buttonAguasCalientes.getText()));
    buttonRTL_NITRO.setUrl(name_url.get(buttonRTL_NITRO.getText()));
    buttonNTW_SERIAL.setUrl(name_url.get(buttonNTW_SERIAL.getText()));
    buttonPro7MAXX.setUrl(name_url.get(buttonPro7MAXX.getText()));

  }



  @Override
  public void setType(Frames value) {
    log.warn("Der Typ wurde mit Frames.TV statisch vorgegeben.");
  }



  /**
   * Die Trennleiste wird in vertikaler Richtung positioniert. Die Angabe erfolgt
   * in Prozent. 0-Prozent ist ganz oben und 100-Prozent ist ganz unten.
   *
   * @param prozent
   *                liegt im Intervall [0..1]
   */
  public void setVerticalDivider(double prozent) {
    if (0 > prozent || prozent > 1) {
      log.warn(prozent + " - die Prozentangabe liegt nicht im Intervall [0..1]");
    }
    splitpaneVertical.setDividerLocation(prozent);
  }



  /**
   * Die Trennleiste wird in vertikaler Richtung positioniert. Die Angabe erfolgt
   * in Pixel. 0 ist ganz oben.
   *
   * @param pixel
   */
  public void setVerticalDivider(int pixel) {
    splitpaneVertical.setDividerLocation(pixel);
  }



  /**
   * Alle Resourcen vom VLC Player werden freigegeben.
   *
   */
  public void shutdown() {
    if (eventsAPI != null) {
      eventsAPI.removeMediaEventListener(mediaEventAdapter);
      eventsAPI.removeMediaPlayerEventListener(playerAdapter);
    }
    try {
      if (embedded != null) embedded.release();
    }
    catch (Exception | Error error) {
      log.info("alles ok, " + error.getMessage());
    }
  }



  public void unregisterComponentAdapter() {
    removeComponentListener(componentAdapter);
  }

  /**
   *
   * @author llange
   *
   */
  private class DurationAdapter extends MediaEventAdapter {
    private MediaParsedStatus status;

    MediaParsedStatus getStatus() {
      return status;
    }



    @Override
    public void mediaParsedChanged(Media media, MediaParsedStatus newStatus) {
      status = newStatus;
      countdown.countDown();
    }

  }

  /**
   * Gson setzt die Variablen über Reflection!
   *
   * @author llange
   *
   */
  private static class Sender {

    private int code;
    private String programmname;
    private String url;

    @SuppressWarnings("unused")
    int getCode() {
      return code;
    }



    String getProgrammname() {
      return programmname;
    }



    String getUrl() {
      return url;
    }

  }

  @Override
  public void setBackgroundGradient(Color top, Color bottom) {
    windowManager.setBackgroundGradient(top, bottom);
  }

}
