/**
 *  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.chat;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Cursor;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.KeyboardFocusManager;
import java.awt.event.ActionEvent;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeSupport;
import java.beans.PropertyVetoException;
import java.util.Collections;
import java.util.List;
import javax.swing.AbstractAction;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JSeparator;
import javax.swing.JTextField;
import javax.swing.KeyStroke;
import javax.swing.UIManager;
import javax.swing.event.InternalFrameAdapter;
import javax.swing.event.InternalFrameEvent;
import net.javacomm.client.resource.Resource;
import net.javacomm.multilingual.MultilingualButton;
import net.javacomm.multilingual.MultilingualLabel;
import net.javacomm.multilingual.MultilingualString;
import net.javacomm.multilingual.MultilingualTextField;
import net.javacomm.multilingual.schema.ISO639;
import net.javacomm.multilingual.schema.KEY;
import net.javacomm.protocol.UserOnline;
import net.javacomm.window.manager.Control;
import net.javacomm.window.manager.WindowAnrufenEvent;
import net.javacomm.window.manager.WindowAnrufenListener;
import net.javacomm.window.manager.WindowManagerInternalFrame;



public class JPrivateChat extends WindowManagerInternalFrame implements WindowAnrufenListener {

  private static final long serialVersionUID = 1791664713483858966L;

  public final static int WIDTH = 590;
  public final static int HEIGHT = 420;
  private JPanel mainPanel = new JPanel(new BorderLayout());
  private FrameAction frameAction = new FrameAction();
  private PropertyChangeSupport changes = new PropertyChangeSupport(this);
  private OneChatPanel onePanel = new OneChatPanel();

  public JPrivateChat() {
    addInternalFrameListener(frameAction);
    setContentPane(mainPanel);
    mainPanel.add(BorderLayout.CENTER, onePanel);
  }



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



  public void closingWindow() {
    try {
      setClosed(true);
    }
    catch (PropertyVetoException e) {}
  }



  public void removeAllListener() {
    for (PropertyChangeListener l : changes.getPropertyChangeListeners()) {
      removePersonListener(l);
    }
  }



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



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



  /**
   * Ein Grund, warum der Chat nicht beginnen kann.
   * 
   * @param txt
   *            eine Fehlerbeschreibung
   */
  public void setErrorMessage(String txt) {
    onePanel.textFieldStatus.setForeground(Color.WHITE);
    onePanel.textFieldStatus.setBackground(Resource.JQUERY_RED);
    onePanel.textFieldStatus.setText(txt);
  }



  public void setFocus() {
    onePanel.textFieldNickname.requestFocus();
    onePanel.onlinelist.revalidate();
  }



  @Override
  public void setLanguage(ISO639 code) {
    onePanel.buttonClose.setLanguage(code);
    onePanel.labelStatus.setLanguage(code);
    onePanel.onlinelist.setLanguage(code);
    setLanguage(KEY.PRIVATGESPRAECH, code);
    onePanel.multistatus.setLanguage(code);
    if (onePanel.textFieldStatus.getText().length() > 0) {
      onePanel.textFieldStatus.setText(onePanel.multistatus.toString());
    }
    onePanel.gespraechBeginnen.setLanguage(code);
    onePanel.buttonGespraech.setToolTipText(onePanel.gespraechBeginnen.toString());
    treeView(code);
  }



  public void setUserOnlinelist(List<UserOnline> list) {
    onePanel.setUserList(list);
  }

  /*****************************************************************************/
  /*                                                                           */
  /* Innerclass FrameAction */
  /*                                                                           */
  /*****************************************************************************/

  class FrameAction extends InternalFrameAdapter {

    @Override
    public void internalFrameClosing(InternalFrameEvent event) {
      changes.firePropertyChange("JPersonChat", Control.NULL, Control.QUIT);
    }

  }

  /*****************************************************************************/
  /*                                                                           */
  /* Innerclass OneChatPanel */
  /*                                                                           */
  /*****************************************************************************/
  class OneChatPanel extends JPanel {

    private static final long serialVersionUID = -571082746691193469L;
    private GridBagLayout gridbag = new GridBagLayout();
    private GridBagConstraints con = new GridBagConstraints();
    private JLabel lablabelNicknameNickname = new JLabel();
    private JTextField textFieldNickname = new JTextField(10);
    private JButton buttonGespraech = new JButton();
    private MultilingualLabel labelStatus = new MultilingualLabel(KEY.LABEL_STATUS);
    private MultilingualTextField textFieldStatus = new MultilingualTextField();
    private MultilingualString multistatus = new MultilingualString(KEY.STRING_FIELD_STATUS);
    private Class<? extends OneChatPanel> resource;
    private MultilingualButton buttonClose = new MultilingualButton(KEY.BUTTON_SCHLIESSEN);
    private JOnlineliste onlinelist = new JOnlineliste();
    private JSeparator separator = new JSeparator();
    private MultilingualString gespraechBeginnen = new MultilingualString(KEY.STRING_GESPRAECH_BEGINNEN);

    @SuppressWarnings("serial")
    public OneChatPanel() {
      super(true);
      resource = getClass();
      setLayout(gridbag);
      setBorder(null);

      final int top = 12;
      final int left = 12;
      final int bottom = 12;
      final int right = 12;

      con.gridx = 0;
      con.gridy = 0;
      con.gridwidth = 2;
      con.insets = new Insets(top, left, 0, 0);
      gridbag.setConstraints(lablabelNicknameNickname, con);
      add(lablabelNicknameNickname);
      lablabelNicknameNickname.setIcon(new ImageIcon(resource.getResource(Resource.NICKNAME)));

      con.gridx = 2;
      con.gridy = 0;
      con.gridwidth = 1;
      con.insets = new Insets(top, 0, 0, 0);
      gridbag.setConstraints(textFieldNickname, con);
      add(textFieldNickname);
      textFieldNickname
          .setFocusTraversalKeys(KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS, Collections.emptySet());

      textFieldNickname.getInputMap(JComponent.WHEN_FOCUSED)
          .put(KeyStroke.getKeyStroke(KeyEvent.VK_TAB, 0), "Tabulator");
      textFieldNickname.getActionMap().put("Tabulator", new AbstractAction() {
        @Override
        public void actionPerformed(ActionEvent e) {
          if (onlinelist.focusList()) {
            textFieldNickname.setText(onlinelist.getBenutzer());
            textFieldStatus.setBackground(Color.WHITE);
            textFieldStatus.setForeground((Color) UIManager.get("TextField.textForeground"));
            textFieldStatus.setText("Ein Gesprächspartner wurde gewählt.");
          }
        }
      });

      textFieldNickname.addKeyListener(new KeyAdapter() {
        @Override
        public void keyPressed(KeyEvent event) {
          if (event.getKeyCode() == KeyEvent.VK_ENTER) {
            go();
            return;
          }
          if (event.getKeyCode() == KeyEvent.VK_TAB) return;
          if (event.getKeyCode() == KeyEvent.VK_HOME) return;
          if (event.getKeyCode() == KeyEvent.VK_END) return;
          if (event.getKeyCode() == KeyEvent.VK_LEFT) return;
          if (event.getKeyCode() == KeyEvent.VK_RIGHT) return;
          if (event.getKeyCode() == KeyEvent.VK_UP) return;
          if (event.getKeyCode() == KeyEvent.VK_DOWN) return;
          textFieldStatus.setBackground(Color.WHITE);
          textFieldStatus.setForeground((Color) UIManager.get("TextField.textForeground"));
        }
      });

      con.gridx = 3;
      con.gridy = 0;
      con.gridwidth = 1;
      con.insets = new Insets(top, 6, 0, 6);
      gridbag.setConstraints(onlinelist, con);
      add(onlinelist);

      onlinelist.addOnlinelistListener((event) -> {
        textFieldNickname.setText(onlinelist.getBenutzer());
        textFieldStatus.setBackground(Color.WHITE);
        textFieldStatus.setForeground((Color) UIManager.get("TextField.textForeground"));
        textFieldStatus.setText("Ein Gesprächspartner wurde gewählt.");
        Control control = (Control) event.getNewValue();
        switch(control) {
          case PRIVATECHAT:
            buttonGespraech.doClick();
            break;
          case SELECTED:
            break;
          default:
            break;
        }
      });

      con.insets = new Insets(top, 0, 0, right);
      con.gridx = 4;
      con.gridy = 0;
      con.gridwidth = 1;

      gridbag.setConstraints(buttonGespraech, con);
      add(buttonGespraech);
      buttonGespraech.addActionListener((event) -> {
        go();
      });
      buttonGespraech.setFocusPainted(true);
      buttonGespraech.setIcon(new ImageIcon(resource.getResource(Resource.PRIVAT)));
      buttonGespraech.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
      buttonGespraech.setToolTipText(gespraechBeginnen.toString());

      con.gridx = 0;
      con.gridy = 1;
      con.gridwidth = 1;
      con.insets = new Insets(12, left, 0, 0);

      gridbag.setConstraints(labelStatus, con);
      labelStatus.setIconTextGap(9);
      add(labelStatus);
      labelStatus.setIcon(new ImageIcon(resource.getResource(Resource.STATUS)));

      con.gridx = 2;
      con.gridy = 1;
      con.gridwidth = 3;
      con.fill = GridBagConstraints.HORIZONTAL;
      con.insets = new Insets(12, 6, 0, right);
      con.weightx = 1.0;
      gridbag.setConstraints(textFieldStatus, con);
      add(textFieldStatus);
      textFieldStatus.setOpaque(false);
      textFieldStatus.setFocusable(false);

      con.gridx = 0;
      con.gridy = 2;
      con.gridwidth = 5;
      con.fill = GridBagConstraints.HORIZONTAL;
      con.insets = new Insets(24, left, 0, right);
      con.weightx = 1.0;
      gridbag.setConstraints(separator, con);
      add(separator);

      con.gridx = 4;
      con.gridy = 3;
      con.gridwidth = 1;
      con.fill = GridBagConstraints.HORIZONTAL;
      con.anchor = GridBagConstraints.EAST;
      con.insets = new Insets(12, left, bottom, right);
      con.weightx = 0.0;

      gridbag.setConstraints(buttonClose, con);
      add(buttonClose);
      buttonClose.addActionListener((event) -> {
        try {
          setClosed(true);
        }
        catch (PropertyVetoException e) {}
      });
      buttonClose.setIcon(new ImageIcon(resource.getResource(Resource.CLOSE_BLUE)));
      buttonClose.setIconTextGap(9);
    }



    private void go() {
      if (textFieldNickname.getText().length() > 0) {
        textFieldStatus.setBackground(Color.WHITE);
        textFieldStatus.setForeground((Color) UIManager.get("TextField.textForeground"));
        textFieldStatus.setText("Eine Verbindung wird aufgebaut...");
        changes.firePropertyChange(textFieldNickname.getText(), Control.NULL, Control.HIT);
      }
      else {
//        textFieldStatus.setText("Du hast keinen Gesprächspartner gewählt.");
        // Sie haben keine Person zum Chatten ausgewählt.
//        ou have not selected any person to chat.
//        No ha seleccionado ningún usuario.
//        No ha seleccionado a ninguna persona para chatear.
//        You have not selected anyone to chat with.
        textFieldStatus.setText(multistatus.toString());
        textFieldStatus.setCaretPosition(0);
        textFieldStatus.setBackground(Resource.JQUERY_RED);
        textFieldStatus.setForeground(Color.WHITE);
      }
    }



    public void setUserList(List<UserOnline> list) {
      onlinelist.setUserList(list);
    }

  }

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

}
