/**
 *  Copyright © 2022-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.screencaster;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Rectangle;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.image.BufferedImage;
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.JComponent;
import javax.swing.JLabel;
import javax.swing.JScrollBar;
import javax.swing.JScrollPane;
import javax.swing.JSplitPane;
import javax.swing.ScrollPaneConstants;
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.resource.Resource;
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.WindowAnrufenEvent;
import net.javacomm.window.manager.WindowAnrufenListener;
import net.javacomm.window.manager.WindowManagerInternalFrame;



/**
 * Dieser Projektor wird für eine 1:1 Bildschirmübertragung verwendet.
 */
public class ProjektorInternalFrame extends WindowManagerInternalFrame implements WindowAnrufenListener {

  /**
   * 
   */
  private static final long serialVersionUID = -783434136934302532L;

  private final static Logger log = LogManager.getLogger(ProjektorInternalFrame.class);
  public final static int SCREEN_WIDTH = 871; // 640 + 271
  public final static int SCREEN_HEIGHT = 384; // 360+24
  private ImageIcon image;
  protected PropertyChangeSupport changes = new PropertyChangeSupport(this);
  protected InternalFrameAdapter internalFrameAdapter = new InternalFrameAdapter() {

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

  };

  private Videopanel videopanel;

  private BorderLayout borderlayout = new BorderLayout();
  private JScrollPane scrollvideopane = new JScrollPane();
  private JLabel corner;
  private JSplitPane splitpaneHorizontal = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT);
  private ComponentAdapter componentAdapter;
  private MouseAdapter mouseAdapter;
  private JScrollBar yScrollbar;
  private JScrollBar xScrollbar;

  public ProjektorInternalFrame() {
    setMaximizable(true);
    setResizable(true);
    setIconifiable(false);
    setClosable(true);
    setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
    URL url = getClass().getResource(Resource.PROJEKTOR_34x26);
    image = new ImageIcon(url);
    setFrameIcon(image);
    setSize(ProjektorInternalFrame.SCREEN_WIDTH, ProjektorInternalFrame.SCREEN_HEIGHT);
    addInternalFrameListener(internalFrameAdapter);
    componentAdapter = new ComponentAdapter() {

      @Override
      public void componentResized(ComponentEvent event) {
        if (ProjektorInternalFrame.this.isMaximum()) {
          Rectangle rectangle = ProjektorInternalFrame.this.getBounds();
//          int breite = (int) rectangle.getSize().getWidth() - WindowManagerInternalFrame.SPLITWIDTH
//              - WindowManagerInternalFrame.MALUS;
          int breite = (int) rectangle.getSize().getWidth() - WindowManagerInternalFrame.SPLITWIDTH;
          setHorizontalDivider(breite);
        }
        else {}
      }

    };
    addComponentListener(componentAdapter);
    init();
  }

  /**
   * 
   * In diesem Panel wird das Video angezeigt.
   * 
   * @author llange
   *
   */
  private static class Videopanel extends JComponent {

    /**
     * 
     */
    private static final long serialVersionUID = 7454789357550113183L;
    BufferedImage fullscreen;

    public Videopanel() {
      setLayout(new BorderLayout());
    }



    @Override
    public Dimension getPreferredSize() {

      if (fullscreen == null) return new Dimension(640, 360);
      return new Dimension(fullscreen.getWidth(), fullscreen.getHeight());

    }



    @Override
    public void paintComponent(Graphics g) {
      super.paintComponent(g);
      g.drawImage(fullscreen, 0, 0, this);
    }

  }

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



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



  /**
   * Das Fenster wird geschlossen.
   * 
   */
  public void closeWindow() {
    try {
      setClosed(true);
    }
    catch (PropertyVetoException e) {}
  }



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



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



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



  private void init() {
    setLayout(borderlayout);
    add(splitpaneHorizontal, BorderLayout.CENTER);
    splitpaneHorizontal.setLeftComponent(scrollvideopane);
    splitpaneHorizontal.setRightComponent(windowManager);
    splitpaneHorizontal.setDividerLocation(SCREEN_WIDTH - WindowManagerInternalFrame.SPLITWIDTH);
    splitpaneHorizontal.setOneTouchExpandable(true);
    this.setHorizontalDivider(1.0);
    windowManager.setMinimumSize(new Dimension(0, 0));
    windowManager.addWMListener(new PropertyChangeListener() {
      @Override
      public void propertyChange(PropertyChangeEvent event) {
        changes.firePropertyChange(event.getPropertyName(), Control.NULL, Control.SELECTED);
      }
    });

    mouseAdapter = new MouseAdapter() {
      @Override
      public void mouseEntered(MouseEvent event) {
        if (event.getSource().equals(videopanel)) {
          setHorizontalDivider(1.0);
        }
      }



      @Override
      public void mouseExited(MouseEvent event) {
        if (event.getSource().equals(videopanel)) {
          setHorizontalDivider(
              ProjektorInternalFrame.this.getWidth() - WindowManagerInternalFrame.SPLITWIDTH
          );
        }
      }

    };

    videopanel = new Videopanel();

    xScrollbar = scrollvideopane.getHorizontalScrollBar();
    xScrollbar.setUnitIncrement(12);

    yScrollbar = scrollvideopane.getVerticalScrollBar();
    yScrollbar.setUnitIncrement(12);

    corner = new JLabel();
    corner.setBackground(UIManager.getColor("nimbusSelectionBackground"));
    corner.setOpaque(true);
    scrollvideopane.setCorner(ScrollPaneConstants.LOWER_RIGHT_CORNER, corner); // ok!
    scrollvideopane.setViewportView(videopanel);
  }



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



  public void removeAllListener() {
    for (PropertyChangeListener listener : changes.getPropertyChangeListeners()) {
      removedProjektorListener(listener);
    }
    windowManager.removeAllListener();
    removeComponentListener(componentAdapter);
    videopanel.removeMouseListener(mouseAdapter);
  }



  public void removedProjektorListener(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);
  }



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



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



  /**
   * 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);
  }



  // TODO
  public void setImage(BufferedImage image) {
    videopanel.fullscreen = image;
    videopanel.repaint();
  }



  @Override
  public void setLanguage(ISO639 code) {
    setLanguage(KEY.FRAME_PROJEKTOR, code); // der neue Name wird gesetzt
    treeView(code);
  }



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

}
