/**
 *  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.EventQueue;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.GridLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeSupport;
import java.beans.PropertyVetoException;
import java.net.URL;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JInternalFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JSeparator;
import javax.swing.JSplitPane;
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.resource.Resource;
import net.javacomm.multilingual.MultilingualButton;
import net.javacomm.multilingual.MultilingualString;
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;



public class JAbnehmenFrame extends WindowManagerInternalFrame implements WindowAnrufenListener {

  private final static Logger log = LogManager.getLogger(JAbnehmenFrame.class);
  private static final long serialVersionUID = -6089899074113375144L;
  public final static int SCREEN_WIDTH = 690;
  public final static int SCREEN_HEIGHT = 330;
  private PropertyChangeSupport changes = new PropertyChangeSupport(this);
  private JSplitPane splitpane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT);
  private JScrollPane scrollpane = new JScrollPane();
  private JPanel mainpanel = new JPanel();
  private GridBagLayout gridbag = new GridBagLayout();
  private GridBagConstraints con = new GridBagConstraints();
  private Knopfleiste knopfleiste = new Knopfleiste();
  private ActionListener buttonHoererAbnehmenListener;
  private ActionListener buttonHoererAuflegenListener;
  private JSeparator separator = new JSeparator();
  private MultilingualButton buttonSchliessen = new MultilingualButton(KEY.BUTTON_SCHLIESSEN);
  private JLabel labelPicture = new JLabel();
  private JSliderVolumePanel volumepanel = new JSliderVolumePanel();
  private PropertyChangeListener abnehmenListener;
  private MultilingualString mikrofonFehlt = new MultilingualString(KEY.STRING_EIN_MIKROFON_FEHLT);
  private MultilingualString telefonieren = new MultilingualString(KEY.STRING_TELEFONIEREN);
  private ActionListener buttonCloseListener;

  public JAbnehmenFrame() {
    Class<? extends JAbnehmenFrame> resource = getClass();
    URL url = resource.getResource(Resource.PHONE_RING);
    setFrameIcon(new ImageIcon(url));
    setMaximizable(false);
    setResizable(true);
    setIconifiable(true);
    setClosable(false);
    setDefaultCloseOperation(JInternalFrame.DISPOSE_ON_CLOSE);
    setSize(SCREEN_WIDTH, SCREEN_HEIGHT); // +30

    addInternalFrameListener(new InternalFrameAdapter() {
      @Override
      public void internalFrameClosed(InternalFrameEvent event) {
        changes.firePropertyChange(JAbnehmenFrame.class.getName(), Control.NULL, Control.TELEFON_AUFLEGEN);
      }
    });

    splitpane.setRightComponent(windowManager);
    splitpane.setLeftComponent(scrollpane);
    splitpane.setDividerLocation(SCREEN_WIDTH - 201);
    splitpane.setOneTouchExpandable(true);

    scrollpane.setViewportView(mainpanel);
    scrollpane.setBorder(null);
    scrollpane.getHorizontalScrollBar().setUnitIncrement(12);
    scrollpane.getVerticalScrollBar().setUnitIncrement(12);

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

    final int margin_left = 6;
    final int margin_right = 6;
    final int margin_top = 12;
    final int margin_bottom = 12;

    con.gridx = 0;
    con.gridy = 0;
    con.gridwidth = 1;
    con.fill = GridBagConstraints.HORIZONTAL;
    con.weightx = 0.0;
    con.weighty = 0.0;
    con.insets = new Insets(margin_top, margin_left, 12, margin_right);
    con.anchor = GridBagConstraints.CENTER;
    gridbag.setConstraints(volumepanel, con);
    mainpanel.add(volumepanel);
    abnehmenListener = new PropertyChangeListener() {

      @Override
      public void propertyChange(PropertyChangeEvent event) {
        changes.firePropertyChange(JAbnehmenFrame.class.getName(), Control.NULL, Control.TELEFON_VOLUME);
      }

    };
    volumepanel.addVolumeListener(abnehmenListener);

    labelPicture.setIcon(new ImageIcon(resource.getResource(Resource.TELEFON_PICTURE)));
    con.gridx = 0;
    con.gridy = 1;
    con.gridwidth = 1;
    con.fill = GridBagConstraints.NONE;
    con.weightx = 0.0;
    con.weighty = 0.0;
    con.insets = new Insets(margin_top, margin_left, 12, margin_right);
    con.anchor = GridBagConstraints.CENTER;
    gridbag.setConstraints(labelPicture, con);
    mainpanel.add(labelPicture);

    con.gridx = 0;
    con.gridy = 2;
    con.gridwidth = 1;
    con.fill = GridBagConstraints.NONE;
    con.weightx = 0.0;
    con.weighty = 0.0;
    con.insets = new Insets(0, margin_left, 0, margin_right);
    con.anchor = GridBagConstraints.CENTER;
    gridbag.setConstraints(knopfleiste, con);
    mainpanel.add(knopfleiste);

    con.gridx = 0;
    con.gridy = 3;
    con.gridwidth = 1;
    con.fill = GridBagConstraints.HORIZONTAL;
    con.weightx = 0.0;
    con.weighty = 0.0;
    con.anchor = GridBagConstraints.CENTER;
    con.insets = new Insets(24, margin_left, 0, margin_right);
    gridbag.setConstraints(separator, con);
    mainpanel.add(separator);

    con.gridx = 0;
    con.gridy = 4;
    con.gridwidth = 1;
    con.fill = GridBagConstraints.NONE;
    con.weightx = 0.0;
    con.weighty = 0.0;
    con.anchor = GridBagConstraints.EAST;
    con.insets = new Insets(12, margin_left, margin_bottom, margin_right);
    gridbag.setConstraints(buttonSchliessen, con);
    mainpanel.add(buttonSchliessen);
    buttonCloseListener = (event) -> {
      try {
        setClosed(true);
      }
      catch (PropertyVetoException e1) {
        log.error(e1.getMessage(), e1.getCause());
      }
    };
    buttonSchliessen.addActionListener(buttonCloseListener);

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

    buttonHoererAbnehmenListener = new ActionListener() {

      @Override
      public void actionPerformed(ActionEvent e) {
        if (!TelefonUtil.isMicro()) {
          Runnable runnable = () -> {
            JOptionPane.showMessageDialog(
                JAbnehmenFrame.this, "<html>" + mikrofonFehlt.toString() + "</html>", telefonieren.toString(),
                JOptionPane.ERROR_MESSAGE
            );
          };
          EventQueue.invokeLater(runnable);
          return;
        }
        // AbnehmenListener deaktivieren und AuflegenListener aktivieren

        hoererAbnehmen();
        changes.firePropertyChange(JAbnehmenFrame.class.getName(), Control.NULL, Control.TELEFON_ABNEHMEN);
      }
    };

    buttonHoererAuflegenListener = new ActionListener() {
      @Override
      public void actionPerformed(ActionEvent event) {
        hoererAuflegen();
        try {
          setClosed(true);
        }
        catch (PropertyVetoException e) {
          log.error(e.getMessage(), e);
        }
      }
    };

    setContentPane(splitpane);
  }



  /**
   * Die Lautsprecherstärke wird in der GUI eingestellt und nicht am realen
   * Lautsprecher.
   * 
   * @param volume
   */
  public void setVolumeGui(int volume) {
    volumepanel.setLoudness(volume);
  }



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



  public synchronized void addAbnehmenListener(PropertyChangeListener l) {
    changes.addPropertyChangeListener(l);
  }



  void buttonDisabled(JButton button) {
    button.setForeground(WMResource.DISABLED_BUTTON_FOREGROUND);
    button.setBackground(WMResource.DISABLED_BUTTON_BACKGROUND);
  }



  void buttonEnabled(JButton button) {
    button.setForeground(WMResource.ENABLED_BUTTON_FOREGROUND);
    button.setBackground(WMResource.ENABLED_BUTTON_BACKGROUND);
  }



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



  /**
   * Der Anwender hat auf Hörer abnehmen geklickt. Der Abnehmenknopf wird rot und
   * sein zugehöriger Listener deaktiviert. Der Auflegenknopf wird aktiviert.
   * 
   */
  private void hoererAbnehmen() {
    knopfleiste.buttonHoererAbnehmen.removeActionListener(buttonHoererAbnehmenListener);
    knopfleiste.buttonHoererAuflegen.addActionListener(buttonHoererAuflegenListener);

    for (ActionListener listener : buttonSchliessen.getActionListeners()) {
      buttonSchliessen.removeActionListener(listener);
    }

    buttonDisabled(buttonSchliessen);
    buttonDisabled(knopfleiste.buttonHoererAbnehmen);
    buttonEnabled(knopfleiste.buttonHoererAuflegen);

  }



  /**
   * Der Anwender legt den Telefonhörer auf. Alle Listener werden entfernt, weil
   * das Fenster geschlossen wird. Die Knöpfe werden obligatorisch auf
   * abgeschaltet umgestellt.
   * 
   */
  public void hoererAuflegen() {
    for (ActionListener listener : knopfleiste.buttonHoererAbnehmen.getActionListeners()) {
      knopfleiste.buttonHoererAbnehmen.removeActionListener(listener);
    }
    for (ActionListener listener : knopfleiste.buttonHoererAuflegen.getActionListeners()) {
      knopfleiste.buttonHoererAuflegen.removeActionListener(listener);
    }
    buttonDisabled(knopfleiste.buttonHoererAbnehmen);
    buttonDisabled(knopfleiste.buttonHoererAuflegen);
  }



  public synchronized void removeAbnehmenListener(PropertyChangeListener l) {
    changes.removePropertyChangeListener(l);
  }



  public synchronized void removeAllListener() {
    for (PropertyChangeListener tmp : changes.getPropertyChangeListeners()) {
      removeAbnehmenListener(tmp);
    }
    windowManager.removeAllListener();
    volumepanel.removeVolumeListener(abnehmenListener);
  }



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



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



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



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



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



  /**
   * Das Fenster wurde gerade geöffnet und die Knopfleiste wird in ihrer
   * Ausgangsposition angezeigt. Abnehmen ist aktiv und Auflegen ist rot.
   * 
   */
  public void startenKnopfleiste() {

    buttonEnabled(knopfleiste.buttonHoererAbnehmen);
    buttonDisabled(knopfleiste.buttonHoererAuflegen);

    knopfleiste.buttonHoererAbnehmen.addActionListener(buttonHoererAbnehmenListener);
    knopfleiste.buttonHoererAuflegen.removeActionListener(buttonHoererAuflegenListener);

  }

  private class Knopfleiste extends JPanel {

    private static final long serialVersionUID = 7506748079964000121L;
    private GridLayout grid = new GridLayout(1, 2, 9, 24);
    private MultilingualButton buttonHoererAbnehmen = new MultilingualButton(KEY.BUTTON_HOERER_ABNEHMEN);
    private MultilingualButton buttonHoererAuflegen = new MultilingualButton(KEY.BUTTON_HOERER_AUFLEGEN);
    private Class<? extends Knopfleiste> resource2;

    private Knopfleiste() {
      resource2 = getClass();
      setLayout(grid);
      add(buttonHoererAbnehmen);
      buttonHoererAbnehmen.setIcon(new ImageIcon(resource2.getResource(Resource.ABNEHMEN)));
      add(buttonHoererAuflegen);
      buttonHoererAuflegen.setIcon(new ImageIcon(resource2.getResource(Resource.AUFLEGEN)));
    }

  }

  @Override
  public void setLanguage(ISO639 code) {
    buttonSchliessen.setLanguage(code);
    knopfleiste.buttonHoererAbnehmen.setLanguage(code);
    knopfleiste.buttonHoererAuflegen.setLanguage(code);
    volumepanel.setLanguage(code);
    mikrofonFehlt.setLanguage(code);
    telefonieren.setLanguage(code);
    setLanguage(KEY.FRAME_ABNEHMEN, code, extText);
    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);
  }

}
