/**
 *  Copyright © 2020-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.phone;

import java.awt.Color;
import java.awt.Dimension;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.GridLayout;
import java.awt.Insets;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeSupport;
import java.beans.PropertyVetoException;
import java.net.URL;
import java.util.Arrays;
import java.util.List;
import javax.sound.sampled.Mixer.Info;
import javax.swing.DefaultComboBoxModel;
import javax.swing.ImageIcon;
import javax.swing.JComboBox;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JSeparator;
import javax.swing.JSplitPane;
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 org.nexuswob.gui.swing.NimbusCellRenderer;
import net.javacomm.client.resource.Resource;
import net.javacomm.multilingual.MultilingualButton;
import net.javacomm.multilingual.MultilingualLabel;
import net.javacomm.multilingual.schema.ISO639;
import net.javacomm.multilingual.schema.KEY;
import net.javacomm.transfer.Sprachguete;
import net.javacomm.window.manager.Control;
import net.javacomm.window.manager.Frames;
import net.javacomm.window.manager.WM;
import net.javacomm.window.manager.WindowAnrufenEvent;
import net.javacomm.window.manager.WindowAnrufenListener;
import net.javacomm.window.manager.WindowManagerInternalFrame;



public class JTelefonEinrichtenFrame extends WindowManagerInternalFrame implements WindowAnrufenListener {

  private final static Logger log = LogManager.getLogger(JTelefonEinrichtenFrame.class);
  private static final long serialVersionUID = 1677728476280898765L;

  public final static int SCREEN_WIDTH = 792;
  public final static int SCREEN_HEIGHT = 402;

  private PropertyChangeSupport changes = new PropertyChangeSupport(this);
  private InternalAction internalAction = new InternalAction();
  private JSplitPane splitpane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT);
  private JPanel mainpanel = new JPanel();

  private GridBagLayout gridbag = new GridBagLayout();
  private GridBagConstraints con = new GridBagConstraints();

  private MultilingualLabel labelLautsprecher = new MultilingualLabel(KEY.LABEL_LAUTSPRECHER);
  private JComboBox<String> comboLautsprecher = new JComboBox<>();
  private MultilingualLabel labelSprachquality = new MultilingualLabel(KEY.LABEL_SPRACHQUALITAET);
  private DefaultComboBoxModel<Telefonformat> boxmodel = new DefaultComboBoxModel<>();
  private JComboBox<Telefonformat> comboboxTelefonformat = new JComboBox<>(boxmodel);
  private MultilingualLabel labelMikrofonaufnahme = new MultilingualLabel(KEY.LABEL_STEREO);
  private MultilingualLabel labelLautsprecherEmpfang = new MultilingualLabel(KEY.LABEL_LAUTSPRECHEREMPFANG);
  private MultilingualLabel labelRoboter = new MultilingualLabel(KEY.LABEL_ROBOTER);
  private MultilingualLabel labelMikrofon = new MultilingualLabel(KEY.LABEL_MIKROFONAUFNAHME);
  private JComboBox<String> comboMicro = new JComboBox<>();
  private JSeparator separator = new JSeparator();
  private TelefonButton telefonButton = new TelefonButton();
  private JScrollPane scrollpanel = new JScrollPane();

  public JTelefonEinrichtenFrame() {
    super();

    Class<? extends JTelefonEinrichtenFrame> resource = getClass();
    URL url = resource.getResource(Resource.TELEFONEINRICHTEN_42x26);
    setFrameIcon(new ImageIcon(url));
    setMaximizable(false);
    setResizable(true);
    setIconifiable(true);
    setClosable(true);
    setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
    setSize(SCREEN_WIDTH, SCREEN_HEIGHT); // +30
    addInternalFrameListener(internalAction);

  }



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



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



  /**
   * Das Telefonfenster wird geschlossen.
   */
  public void closing() {
    try {
      setClosed(true);
    }
    catch (PropertyVetoException e) {
      log.error(e.getMessage(), e.getCause());
    }
  }



  /**
   *
   * Gib den Lautsprecher zurück.
   *
   * @return Lautsprecher als Text oder {@code null}, falls kein Lautsprecher
   *         gefunden wurde
   */
  public String getLautsprecher() {
    String lautsprecher = (String) comboLautsprecher.getSelectedItem();
    return lautsprecher;
  }



  /**
   * Gib das Mikrofon zurück.
   *
   * @return Mikrofon als Text oder {@code null}, falls kein Mikrofon gefunden
   *         wurde
   */
  public String getMikrofon() {
    String mikro = (String) comboMicro.getSelectedItem();
    return mikro;
  }



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



  /**
   * Gib das Telefonformat zurück.
   *
   * @return Telefonformat als Text
   */
  public String getTelefonformat() {
    return getTelefonformatEnum().toString();
  }



  private Telefonformat getTelefonformatEnum() {
    return (Telefonformat) comboboxTelefonformat.getSelectedItem();
  }



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



  /**
   *
   *
   *
   * @param lautsprecher
   *                            die Lautsprecherbezeichnung aus der Datenbank
   * @param mikrofon
   *                            die Mikrofonbezeichnung aus der Datenbank
   * @param telefonpuffer
   * @param telefonLautsprecher
   * @param telefonMikrofon
   */
  public void init(Sprachguete telefonpuffer, String telefonLautsprecher, String telefonMikrofon) {

    setContentPane(splitpane);
    splitpane.setBorder(null);
    splitpane.setLeftComponent(scrollpanel);
    scrollpanel.getVerticalScrollBar().setUnitIncrement(12);
    scrollpanel.getHorizontalScrollBar().setUnitIncrement(12);
    scrollpanel.setBorder(null);

    splitpane.setDividerLocation(SCREEN_WIDTH - 220);

    scrollpanel.setViewportView(mainpanel);

    mainpanel.setMinimumSize(new Dimension(0, 0));
    mainpanel.setLayout(gridbag);

    // Lautsprecher
    con.gridx = 0;
    con.gridy = 0;
    con.gridwidth = 1;
    con.insets = new Insets(12, 0, 0, 0);
    con.fill = GridBagConstraints.NONE;
    con.anchor = GridBagConstraints.EAST;
    gridbag.setConstraints(labelLautsprecher, con);
    mainpanel.add(labelLautsprecher);

    // Lautsprecherauswahl
    con.gridx = 1;
    con.gridy = 0;
    con.gridwidth = 2;
    con.insets = new Insets(12, 6, 0, 0);
    con.fill = GridBagConstraints.HORIZONTAL;
    gridbag.setConstraints(comboLautsprecher, con);
    mainpanel.add(comboLautsprecher);
    comboLautsprecher.setRenderer(new NimbusCellRenderer<>());
    List<Info> speaker = TelefonUtil.speakerMixer(Telefonformat.MEDIUM_LOW);

    // finde alle Lautsprecher und selektiere den Trefferlautsprecher
    for (Info tmp : speaker) {
      comboLautsprecher.addItem(tmp.getName());
      if (tmp.getName().equals(telefonLautsprecher)) {
        comboLautsprecher.setSelectedItem(tmp.getName());
      }
    }

    // Sprachqualität

    con.gridx = 0;
    con.gridy = 1;
    con.gridwidth = 1;
    con.fill = GridBagConstraints.NONE;
    con.insets = new Insets(6, 0, 0, 0);
    con.anchor = GridBagConstraints.EAST;
    gridbag.setConstraints(labelSprachquality, con);
    mainpanel.add(labelSprachquality);

    // Telefonformat

    con.gridx = 1;
    con.gridy = 1;
    con.gridwidth = 1;
    con.insets = new Insets(6, 6, 0, 0);
    con.fill = GridBagConstraints.NONE;
    con.anchor = GridBagConstraints.WEST;
    gridbag.setConstraints(comboboxTelefonformat, con);
    mainpanel.add(comboboxTelefonformat);
    comboboxTelefonformat.setRenderer(new NimbusCellRenderer<>());

    boxmodel.addAll(Arrays.asList(Telefonformat.values()));
    for (int index = 0; index < comboboxTelefonformat.getItemCount(); index++) {
      if (comboboxTelefonformat.getItemAt(index).toString().equals(telefonpuffer.toString())) {
        comboboxTelefonformat.setSelectedIndex(index);
        break;
      }
    }
    comboboxTelefonformat.addActionListener((event) -> {
      labelLautsprecherEmpfang.setKey(KEY.LABEL_LAUTSPRECHEREMPFANG);
      String neuerText = labelLautsprecherEmpfang.getText()
          .replace("XXX", String.valueOf((int) getTelefonformatEnum().getFrequenz()));
      labelLautsprecherEmpfang.setText(neuerText);
    });

    // für die Mikrofonaufnahme

    con.gridx = 2;
    con.gridy = 1;
    con.gridwidth = 1;
    con.insets = new Insets(6, 6, 0, 0);
    con.fill = GridBagConstraints.NONE;
    con.anchor = GridBagConstraints.WEST;
    gridbag.setConstraints(labelMikrofonaufnahme, con);
    mainpanel.add(labelMikrofonaufnahme);

    // labelLautsprecherEmpfang

    con.gridx = 0;
    con.gridy++;
    con.gridwidth = 3;
    con.insets = new Insets(12, 0, 6, 0);
    con.anchor = GridBagConstraints.CENTER;
    con.fill = GridBagConstraints.NONE;
    gridbag.setConstraints(labelLautsprecherEmpfang, con);
    mainpanel.add(labelLautsprecherEmpfang);

    // Mein Mikrofon
    con.gridx = 0;
    con.gridy = 3;
    con.gridwidth = 1;
    con.insets = new Insets(6, 0, 0, 0);
    con.anchor = GridBagConstraints.EAST;
    con.fill = GridBagConstraints.NONE;
    gridbag.setConstraints(labelMikrofon, con);
    mainpanel.add(labelMikrofon);

    // comboMicro

    con.gridx = 1;
    con.gridy = 3;
    con.gridwidth = 2;
    con.anchor = GridBagConstraints.WEST;
    con.insets = new Insets(6, 6, 0, 0);
    con.fill = GridBagConstraints.HORIZONTAL;
    gridbag.setConstraints(comboMicro, con);
    mainpanel.add(comboMicro);
    comboMicro.setRenderer(new NimbusCellRenderer<>());

    List<Info> micro = TelefonUtil.microMixer(Telefonformat.MEDIUM_LOW);
    for (Info tmp : micro) {
      comboMicro.addItem(tmp.getName());
      if (tmp.getName().equals(telefonMikrofon)) {
        comboMicro.setSelectedItem(tmp.getName());
      }
    }

    // Roboter
    con.gridx = 0;
    con.gridy++;
    con.gridwidth = 3;
    con.insets = new Insets(18, 6, 12, 0);
    con.fill = GridBagConstraints.NONE;
    con.anchor = GridBagConstraints.WEST;
    gridbag.setConstraints(labelRoboter, con);
    mainpanel.add(labelRoboter);

    // separator
    con.gridx = 0;
    con.gridy++;
    con.gridwidth = 3;
    con.anchor = GridBagConstraints.CENTER;
    con.insets = new Insets(18, 6, 0, 0);
    con.fill = GridBagConstraints.HORIZONTAL;
    gridbag.setConstraints(separator, con);
    mainpanel.add(separator);

    // Telefonbutton

    con.gridx = 0;
    con.gridy++;
    con.gridwidth = 3;
    con.anchor = GridBagConstraints.NORTHEAST;
    con.insets = new Insets(18, 6, 12, 0);
    con.fill = GridBagConstraints.NONE;
    con.weighty = 1.0;
    gridbag.setConstraints(telefonButton, con);
    mainpanel.add(telefonButton);

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

      }
    });
    mainpanel.setBorder(null);
  }



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



  public synchronized void removeAllListener() {
    for (PropertyChangeListener listener : changes.getPropertyChangeListeners()) {
      changes.removePropertyChangeListener(listener);
    }
    windowManager.removeAllListener();
    removeInternalFrameListener(internalAction);
  }



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



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



  @Override
  public void setFrameTitleId(String value) {
    setTitle(value);
  }



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



  @Override
  public void setType(Frames value) {
    // TODO Auto-generated method stub

  }

  private class InternalAction extends InternalFrameAdapter {
    @Override
    public void internalFrameClosed(InternalFrameEvent event) {
      changes.firePropertyChange("JTelefon", Control.NULL, Control.CLOSE);
    }

  }

  private class TelefonButton extends JPanel {

    private static final long serialVersionUID = 2661535884663004195L;
    private MultilingualButton buttonSpeichern = new MultilingualButton(KEY.BUTTON_SPEICHERN_SCHLIESSEN);
    private MultilingualButton buttonSchliessen = new MultilingualButton(KEY.BUTTON_SCHLIESSEN);
    private GridLayout grid = new GridLayout(1, 2, 18, 0);

    private TelefonButton() {
      setLayout(grid);

      buttonSpeichern.addActionListener((event) -> {
        // closing();
        changes.firePropertyChange(
            JTelefonEinrichtenFrame.class.getName(), Control.NULL, Control.TELEFON_SPEICHERN
        );
      });
      add(buttonSpeichern);

      buttonSchliessen.addActionListener((event) -> {
        // closing();
        changes.firePropertyChange(JTelefonEinrichtenFrame.class.getName(), Control.NULL, Control.CLOSE);
      });
      add(buttonSchliessen);
    }

  }

  @Override
  public void setLanguage(ISO639 code) {
    telefonButton.buttonSchliessen.setLanguage(code);
    telefonButton.buttonSpeichern.setLanguage(code);
    labelLautsprecher.setLanguage(code);
    labelMikrofon.setLanguage(code);
    labelSprachquality.setLanguage(code);
    labelMikrofonaufnahme.setLanguage(code);
    labelRoboter.setLanguage(code);
    labelLautsprecherEmpfang.setLanguage(code);
    String neuerText = labelLautsprecherEmpfang.getText()
        .replace("XXX", String.valueOf((int) getTelefonformatEnum().getFrequenz()));
    labelLautsprecherEmpfang.setText(neuerText);

    // Si el discurso suena distorsionado para la otra persona, reduzca/reduce la
    // frecuencia de muestreo.
    setLanguage(KEY.FRAME_TELEFON_EINRICHTEN, code); // der neue Name wird gesetzt
    treeView(code);
  }



  @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);
  }



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

}
