/**
 *  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.Dimension;
import java.awt.FontMetrics;
import java.awt.Toolkit;
import java.awt.datatransfer.Clipboard;
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.Transferable;
import java.awt.datatransfer.UnsupportedFlavorException;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.FocusAdapter;
import java.awt.event.FocusEvent;
import java.awt.event.FocusListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeSupport;
import java.io.IOException;
import javax.swing.AbstractAction;
import javax.swing.JPanel;
import javax.swing.JPopupMenu;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JToolTip;
import javax.swing.KeyStroke;
import javax.swing.border.MatteBorder;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.nexuswob.gui.ArrowTooltip;
import org.nexuswob.gui.InputDocument;
import org.nexuswob.gui.JToolTipBorder;
import net.javacomm.client.environment.GUI;
import net.javacomm.client.resource.Resource;
import net.javacomm.multilingual.Babelfish;
import net.javacomm.multilingual.MultilingualCheckBoxMenuItem;
import net.javacomm.multilingual.MultilingualMenuItem;
import net.javacomm.multilingual.MultilingualString;
import net.javacomm.multilingual.schema.ISO639;
import net.javacomm.multilingual.schema.KEY;
import net.javacomm.window.manager.Control;



class JInput extends JPanel implements Babelfish {

  private final static Logger log = LogManager.getLogger(JInput.class);
  private static final long serialVersionUID = -5494262362709859216L;
  private JScrollPane scrollText = new JScrollPane();
  private JTextArea textArea = new JTextArea() {
    private static final long serialVersionUID = 1628367315511920662L;

    @Override
    public JToolTip createToolTip() {
      ArrowTooltip arrow = new ArrowTooltip(Resource.JQUERY_BLAU);
      arrow.setComponent(textArea);
      arrow.setTextAttributes(GUI.regularFont13, Resource.JQUERY_HELLBLAU, Resource.JQUERY_BLAU);
      arrow.setBorder(new JToolTipBorder(7, Resource.JQUERY_YELLOW, Resource.JQUERY_BLAU));
      return arrow;
    }

  };
  private MatteBorder matte;
  private InputDocument doc = new InputDocument(255);
  private PropertyChangeSupport changes = new PropertyChangeSupport(this);
  private JPopupMenu popup = new JPopupMenu();
  private MultilingualMenuItem itemPaste = new MultilingualMenuItem(KEY.POPUP_PASTE);
  private MultilingualMenuItem itemZeilenumbruch = new MultilingualMenuItem(KEY.POPUP_ZEILENUMBRUCH);
  private MultilingualCheckBoxMenuItem itemTooltip = new MultilingualCheckBoxMenuItem(KEY.POPUP_TOOLTIP);
  private MultilingualString tooltip = new MultilingualString(KEY.TOOLTIP_INPUT);

  public JInput() {
    super(true);
    setLayout(new BorderLayout());
    itemPaste.addActionListener((event) -> {
      Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard();
      Transferable transferable = clipboard.getContents(this);
      if (transferable == null) return;
      try {
        String text = (String) transferable.getTransferData(DataFlavor.stringFlavor);
        textArea.setText(textArea.getText().concat(text));
      }
      catch (UnsupportedFlavorException | IOException e) {
        log.error(e.getMessage(), e);
      }
    });
    popup.add(itemPaste);
    itemZeilenumbruch.addActionListener((event) -> {
      shiftDownEnter();
    });
    popup.add(itemZeilenumbruch);
    scrollText.setViewportView(textArea);
    scrollText.setBorder(null);
    textArea.addFocusListener(new FocusAdapter() {
      @Override
      public void focusGained(FocusEvent event) {
        changes.firePropertyChange(JInput.class.getName(), Control.NULL, Control.INPUT_FOCUS);
      }

    });
    textArea.setLineWrap(true);
    textArea.setWrapStyleWord(true);
    textArea.setDocument(doc);
    textArea.getInputMap()
        .put(KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, KeyEvent.SHIFT_DOWN_MASK), "SHIFT_ENTER");
    textArea.getActionMap().put("SHIFT_ENTER", new AbstractAction() {

      private static final long serialVersionUID = -6909033642696710886L;

      @Override
      public void actionPerformed(ActionEvent event) {
        shiftDownEnter();
      }
    });

    textArea.getInputMap().put(KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0), "ENTER");
    textArea.getActionMap().put("ENTER", new AbstractAction() {
      private static final long serialVersionUID = 7348629681452971214L;
      @Override
      public void actionPerformed(ActionEvent event) {
        changes.firePropertyChange("JInput", Control.NULL, Control.MESSAGE);
      }
    });

    textArea.add(popup);
    textArea.addMouseListener(new MouseAdapter() {

      @Override
      public void mousePressed(MouseEvent event) {
        if (event.isPopupTrigger()) {
          pasteFromClipboard(event);
        }
      }



      @Override
      public void mouseReleased(MouseEvent event) {
        if (event.isPopupTrigger()) {
          pasteFromClipboard(event);
        }
      }

    });
    popup.addSeparator();
    popup.add(itemTooltip);
    itemTooltip.addActionListener((event) -> {
      tooltip();
      changes.firePropertyChange(JInput.class.getName(), itemTooltip.isSelected(), Control.CHATTOOLTIP);
    });
    add(BorderLayout.CENTER, scrollText);
  }



  private void shiftDownEnter() {
    StringBuffer text = new StringBuffer(textArea.getText());
    int caretPosition = textArea.getCaretPosition();
    text.insert(caretPosition, "\n");
    textArea.setText(text.toString());
    textArea.setCaretPosition(caretPosition + 1);
  }



  void chatTooltip(boolean chattooltip) {
    itemTooltip.setSelected(chattooltip);
    tooltip();
  }



  private void tooltip() {
    textArea.setToolTipText(itemTooltip.isSelected() ? null : "<html>" + tooltip.toString() + "</html>");
  }



  void pasteFromClipboard(MouseEvent event) {
    popup.show(textArea, event.getX(), event.getY());
  }



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



  public void clear() {
    textArea.setText(new String());
    setFocus();
  }



  public void disableInput() {
    textArea.setEditable(false);
  }



  public String getMessage() {
    return textArea.getText().replace('\n', Message.EOT.charAt(0));
  }



  @Override
  public Dimension getPreferredSize() {
    FontMetrics fm;
    int height;

    fm = textArea.getFontMetrics(getFont());
    height = fm.getAscent() + fm.getDescent() + fm.getLeading();
    return new Dimension(super.getPreferredSize().width, height * 4);
  }




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



  public void removeAllListener() {
    for (PropertyChangeListener listener : changes.getPropertyChangeListeners()) {
      removeInputListener(listener);
    }
    for (MouseListener ml : textArea.getMouseListeners()) {
      textArea.removeMouseListener(ml);
    }
    for (KeyListener kl : textArea.getKeyListeners()) {
      textArea.removeKeyListener(kl);
    }

    for (ActionListener al : itemPaste.getActionListeners()) {
      itemPaste.removeActionListener(al);
    }

    for (ActionListener al : itemZeilenumbruch.getActionListeners()) {
      itemZeilenumbruch.removeActionListener(al);
    }

    for (FocusListener fl : textArea.getFocusListeners()) {
      textArea.removeFocusListener(fl);
    }

    for (ActionListener al : itemTooltip.getActionListeners()) {
      itemTooltip.removeActionListener(al);
    }


  }



  public void setBg(Color c) {
    textArea.setBackground(c);
  }



  public void setFg(Color c) {
    textArea.setForeground(c);
    textArea.setCaretColor(c);
    matte = new MatteBorder(
        JChatPane.thickness, JChatPane.thickness, JChatPane.thickness,
        JChatPane.thickness, textArea.getForeground()
    );
    setBorder(matte);
  }



  void setFocus() {
    textArea.requestFocus();
  }



  @Override
  public void setLanguage(ISO639 code) {
    itemPaste.setLanguage(code);
    itemZeilenumbruch.setLanguage(code);
    itemTooltip.setLanguage(code);
    tooltip.setLanguage(code);
    tooltip();
  }

}
