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

import static net.javacomm.protocol.Roomtype.FORUM;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeSupport;
import java.beans.PropertyVetoException;
import java.io.IOException;
import java.io.InputStream;
import javax.imageio.ImageIO;
import javax.swing.ImageIcon;
import javax.swing.JLabel;
import javax.swing.JMenuBar;
import javax.swing.JSplitPane;
import javax.swing.WindowConstants;
import javax.swing.event.InternalFrameAdapter;
import javax.swing.event.InternalFrameEvent;
import org.nexuswob.gui.TableModel3;
import org.nexuswob.util.Cell;
import org.nexuswob.util.Util.Record;
import net.javacomm.client.resource.Resource;
import net.javacomm.multilingual.MultilingualCheckBoxMenuItem;
import net.javacomm.multilingual.MultilingualMenu;
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.protocol.ChatOnline;
import net.javacomm.protocol.Entry;
import net.javacomm.protocol.Lifetime;
import net.javacomm.protocol.Room;
import net.javacomm.protocol.Roomtype;
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.WindowManager;
import net.javacomm.window.manager.WindowManagerInternalFrame;



/**
 * Die Chatliste wird in einem Frame angezeigt.
 */
public class JLauncher extends WindowManagerInternalFrame implements WindowAnrufenListener {

  private static final long serialVersionUID = 4115791690979135651L;

  public final static int WIDTH = 771;
  public final static int HEIGHT = 432;
  private FrameAction frameAction = new FrameAction();
  private JLauncherSelectRoom selectRoom = new JLauncherSelectRoom();
  private JLeftComponent leftcomponent = new JLeftComponent(selectRoom);
  private PropertyChangeSupport changes = new PropertyChangeSupport(this);
  private JMenuBar menubar = new JMenuBar();
  private MultilingualMenu menuRoom = new MultilingualMenu(KEY.CHAT);
  private MultilingualMenuItem itemPausenraum = new MultilingualMenuItem(KEY.PAUSENRAEUME_VERWALTEN);
  private MultilingualMenuItem itemGruppenraum = new MultilingualMenuItem(KEY.GRUPPENRAUM_EINRICHTEN);
  private MultilingualMenuItem itemBesprechungsraum = new MultilingualMenuItem(
      KEY.BESPRECHUNGSRAEUME_VERWALTEN
  );
  private MultilingualMenuItem itemOne = new MultilingualMenuItem(KEY.PRIVATGESPRAECH);
  private boolean restrictionOn;
  private MultilingualCheckBoxMenuItem itemAnfragenAblehnen = new MultilingualCheckBoxMenuItem(
      KEY.CHATANFRAGEN_ABLEHNEN
  );
  private JSplitPane splitpane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT);
  private Room[] roomlist;
  private MultilingualString unbegrenzt = new MultilingualString(KEY.STRING_LEBENSDAUER_UNBEGRENZT);
  private MultilingualString begrenzt = new MultilingualString(KEY.STRING_LEBENSDAUER_BEGRENZT);
  private ComponentAdapter componentAdapter = new ComponentAdapter() {
    @Override
    public void componentResized(ComponentEvent e) {
      Rectangle rectangle = JLauncher.this.getBounds();
      int breite = (int) rectangle.getSize().getWidth() - WindowManagerInternalFrame.SPLITWIDTH;
      setHorizontalDivider(breite);
    }
  };
  private PropertyChangeListener changeListener;

  public JLauncher() {
    setContentPane(splitpane);
    setMaximizable(false);
    setResizable(true);
    setClosable(false);
    setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
    menubar.add(menuRoom);

    itemBesprechungsraum.setEnabled(true);

    try(InputStream stream = getClass().getResourceAsStream(Resource.BESPRECUNGSRAUM_35x26)) {
      itemBesprechungsraum.setIcon(new ImageIcon(ImageIO.read(stream)));
    }
    catch (IOException e) {}

    itemBesprechungsraum.addActionListener(new ActionListener() {

      @Override
      public void actionPerformed(ActionEvent event) {
        itemBesprechungsraum.setEnabled(false);
        changes.firePropertyChange(JLauncher.class.getName(), Control.NULL, Control.TOPIC);
      }
    });
    menuRoom.add(itemBesprechungsraum);

    try(InputStream stream = getClass().getResourceAsStream(Resource.PAUSENRAUM)) {
      itemPausenraum.setIcon(new ImageIcon(ImageIO.read(stream)));
    }
    catch (IOException e) {}
    itemPausenraum.addActionListener(new ActionListener() {

      @Override
      public void actionPerformed(ActionEvent event) {
        itemPausenraum.setEnabled(false);
        changes.firePropertyChange(JLauncher.class.getName(), Control.NULL, Control.ROOM);
      }

    });
    menuRoom.add(itemPausenraum);

    try(InputStream stream = getClass().getResourceAsStream(Resource.GRUPPENRAUM_25x26)) {
      itemGruppenraum.setIcon(new ImageIcon(ImageIO.read(stream)));
    }
    catch (IOException e) {}

    itemGruppenraum.addActionListener(new ActionListener() {

      @Override
      public void actionPerformed(ActionEvent event) {
        itemGruppenraum.setEnabled(false);
        changes.firePropertyChange(JLauncher.class.getName(), Control.NULL, Control.GROUPROOM);
      }

    });
    menuRoom.add(itemGruppenraum);

    menuRoom.addSeparator();

    itemOne.setEnabled(false);

    try(InputStream stream = getClass().getResourceAsStream(Resource.PRIVAT_26x26)) {
      itemOne.setIcon(new ImageIcon(ImageIO.read(stream)));
    }
    catch (IOException e) {}
    itemOne.addActionListener(new ActionListener() {

      @Override
      public void actionPerformed(ActionEvent event) {
        changes.firePropertyChange(JLauncher.class.getName(), Control.NULL, Control.PRIVATECHAT);
      }

    });

    menuRoom.add(itemOne);
    menuRoom.addSeparator();

    itemAnfragenAblehnen.setSelected(restrictionOn);
    itemAnfragenAblehnen.setEnabled(true);
    itemAnfragenAblehnen.addActionListener(new ActionListener() {
      @Override
      public void actionPerformed(ActionEvent event) {
        restrictionOn = itemAnfragenAblehnen.isSelected();
        changes.firePropertyChange(JLauncher.class.getName(), restrictionOn, Control.RESTRICTION);

      }
    });

    try(InputStream stream = getClass().getResourceAsStream(Resource.NO_CELL_PHONE_25X25)) {
      itemAnfragenAblehnen.setIcon(new ImageIcon(ImageIO.read(stream)));
    }
    catch (IOException e) {}
    menuRoom.add(itemAnfragenAblehnen);

    setJMenuBar(menubar);
    addInternalFrameListener(frameAction);

    selectRoom.setBorder(null);

    changeListener = new PropertyChangeListener() {

      @Override
      public void propertyChange(PropertyChangeEvent event) {
        Room room = (Room) event.getNewValue();
        changes.firePropertyChange(JLauncher.class.getName(), room, Control.REQUEST);
      }
    };

    selectRoom.addChatListener(changeListener);
    selectRoom.getVerticalScrollBar().setUnitIncrement(12);
    selectRoom.getHorizontalScrollBar().setUnitIncrement(12);
    selectRoom.setMinimumSize(new Dimension(0, 0));
    JLabel corner = new JLabel();
    corner.setBorder(null);
    corner.setBackground(Resource.JQUERY_HELLBLAU);
    corner.setOpaque(true);
    windowManager.addWMListener(propertyEvent -> {
      changes.firePropertyChange(propertyEvent);

    });
    windowManager.setMinimumSize(new Dimension(0, 0));

    splitpane.setRightComponent(windowManager);
//    splitpane.setLeftComponent(selectRoom);
    leftcomponent.addLeftComponentListener(event -> {
      doDefaultCloseAction();
    });
    leftcomponent.setMinimumSize(new Dimension(0, 0));

    splitpane.setLeftComponent(leftcomponent);
    splitpane.setDividerLocation(WIDTH - WindowManagerInternalFrame.SPLITWIDTH);
    splitpane.setOneTouchExpandable(true);

    addComponentListener(componentAdapter);

    setMinimumSize(new Dimension(480, 300));

    setSize(WIDTH, HEIGHT);
    setBorder(null);
  }

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



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



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



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



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



  public void removeAllListener() {
    windowManager.removeAllListener();
    removeComponentListener(componentAdapter);
    for (PropertyChangeListener pl : changes.getPropertyChangeListeners()) {
      changes.removePropertyChangeListener(pl);
    }
    selectRoom.removeChatListener(changeListener);
  }



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



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



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



  public void setEnabled1OneChat(boolean value) {
    itemOne.setEnabled(value);
  }



  public void setEnabledBesprechungsraum(boolean value) {
    itemBesprechungsraum.setEnabled(value);
  }



  /**
   * Das Menu Gruppenraum wird wieder aktiviert.
   * 
   * @param value
   *              {@code true}, Gruppenraum einrichten wird aktiv
   */
  public void setEnabledGruppenraum(boolean value) {
    itemGruppenraum.setEnabled(value);
  }



  public void setEnabledPausenraum(boolean value) {
    itemPausenraum.setEnabled(value);
  }



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



  /**
   * 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) {
    splitpane.setDividerLocation(pixel);
  }



  @Override
  public void setLanguage(ISO639 code) {
    unbegrenzt.setLanguage(code);
    begrenzt.setLanguage(code);
    TableModel3 model3 = selectRoom.getModel();
    if (roomlist != null) {
      for (int index = 0; index < roomlist.length; index++) {
        Cell<String> cellLifetime = new Cell<>();
        cellLifetime.setValue(
            roomlist[index].getLifetime() == Lifetime.PERMANENT ? unbegrenzt.toString() : begrenzt.toString()
        );
        // CellLifetime in die richtige Row legen
        model3.setValueAt(cellLifetime.getValue(), index * 2 + 1, JLauncherSelectRoom.LIFETIME);
      }
    }
    selectRoom.setLanguage(code);
    itemPausenraum.setLanguage(code);
    itemGruppenraum.setLanguage(code);
    itemBesprechungsraum.setLanguage(code);
    itemOne.setLanguage(code);
    itemAnfragenAblehnen.setLanguage(code);
    menuRoom.setLanguage(code);
    windowManager.setLanguage(KEY.FRAME_LAUNCHER, code);
    setLanguage(KEY.FRAME_LAUNCHER, code, extText);
    leftcomponent.setLanguage(code);
    treeView(code);
  }



  /**
   *
   * Es können neue User hinzugekommen sein, genauso wie welche gegangen sind;
   *
   * @param recList
   *
   */
  public void setRecordList(ChatOnline[] recList) {

    TableModel3 model = selectRoom.getModel();
    int rows = model.getRowCount();
    for (int index = 0; index < rows; index++) {
      Record record = model.getRecordAt(index);
      Cell<?> room = record.getCellAt(JLauncherSelectRoom.ROOM);
      boolean done = false;
      int count = recList.length;
      for (int m = 0; m < count; m++) {
        if (room.getValue().equals(recList[m].getRoom())) {
          model.setValueAt(recList[m].getOnline(), index, JLauncherSelectRoom.ONLINE);
          done = true;
          break;
        }
      }
      if (done) continue;
      if (index % 2 != 0) model.setValueAt(0, index, JLauncherSelectRoom.ONLINE);
    }

  }



  public void setRestriction(boolean value) {
    itemAnfragenAblehnen.setSelected(value);
  }



  /**
   * Alle Besprechungsräume, Pausennräume und Gruppenräume werden übergeben.
   *
   * @param roomlist
   *                 diese Raumliste
   *
   */
  public void setRoomlist(Room[] roomlist) {
    this.roomlist = roomlist;
    selectRoom.removeAll();
    TableModel3 model3 = selectRoom.getModel();
    for (Room room : roomlist) {

      // Pseudozeile einfügen

      Record pseudo = new Record();

      Cell<String> cellPseudoOnline = new Cell<>();
      cellPseudoOnline.setValue("");
      pseudo.add(cellPseudoOnline);

      Cell<String> cellPseudoRoom = new Cell<>();
      cellPseudoRoom.setValue("");
      pseudo.add(cellPseudoRoom);

      Cell<String> cellPseudoOrt = new Cell<>();
      cellPseudoOrt.setValue("");
      pseudo.add(cellPseudoOrt);

      Cell<String> cellPseudoInhabler = new Cell<>();
      cellPseudoInhabler.setValue("");
      pseudo.add(cellPseudoInhabler);

      Cell<String> cellPseudoZutritt = new Cell<>();
      cellPseudoZutritt.setValue("");
      pseudo.add(cellPseudoZutritt);

      Cell<String> cellPseudoLifetime = new Cell<>();
      cellPseudoLifetime.setValue("");
      pseudo.add(cellPseudoLifetime);

      model3.addRow(pseudo);

      // Räume einfügen
      Record record = new Record();

      Cell<Integer> cellOnline = new Cell<>();
      cellOnline.setValue(0);
      record.add(cellOnline);

      Cell<String> cellRoom = new Cell<>();
      cellRoom.setValue(room.getChatid());
      record.add(cellRoom);

      Cell<JRoomtypeLabel> cellOrt = new Cell<>();
      JRoomtypeLabel type = new JRoomtypeLabel();
      switch(room.getRoomtype()) {
        case FORUM:
          type.setRoomtype(FORUM);

          if (room.getChatid().equals(WindowManager.Welt)) {
            type.setIcon(new ImageIcon(getClass().getClassLoader().getResource(WMResource.DEVELOPER_26x26)));
            type.setIcon(new ImageIcon(getClass().getClassLoader().getResource(WMResource.EL_MUNDO)));
          }
          else {
            type.setIcon(new ImageIcon(getClass().getClassLoader().getResource(WMResource.FORUM_26x26)));
          }
          break;
        case PAUSENRAUM:
          type.setRoomtype(Roomtype.PAUSENRAUM);
          type.setIcon(new ImageIcon(getClass().getResource(Resource.PAUSENRAUM)));
          break;
        case GRUPPENRAUM:
          type.setRoomtype(Roomtype.GRUPPENRAUM);
          type.setIcon(new ImageIcon(getClass().getResource(Resource.GRUPPENRAUM_25x26)));
          break;
        case BESPRECHUNGSRAUM:
          type.setRoomtype(Roomtype.BESPRECHUNGSRAUM);

          if (room.getChatid().equals(WindowManager.Programmierer)) {
            type.setIcon(new ImageIcon(getClass().getClassLoader().getResource(WMResource.DEVELOPER_26x26)));
          }
          else if (room.getChatid().equals(WindowManager.Tester)) {
            type.setIcon(new ImageIcon(getClass().getClassLoader().getResource(WMResource.TESTER_26x26)));
          }
          else if (room.getChatid().equals(WindowManager.Schach)) {
            type.setIcon(new ImageIcon(getClass().getClassLoader().getResource(WMResource.KING_26x26)));
          }
          else if (room.getChatid().equals(WindowManager.ODX)) {
            type.setIcon(new ImageIcon(getClass().getClassLoader().getResource(WMResource.ODX_26x26)));
          }
          else {
            type.setIcon(new ImageIcon(getClass().getResource(Resource.BESPRECUNGSRAUM_35x26)));
          }

          break;
        default:
          break;
      }

      cellOrt.setValue(type);
      record.add(cellOrt);

      Cell<String> cellInhaber = new Cell<>();
      cellInhaber.setValue(room.getOwner());
      record.add(cellInhaber);

      Cell<JEntryLabel> cellZutritt = new Cell<>();
      JEntryLabel entry = new JEntryLabel();
      if (room.getEntry() == Entry.PUBLIC) {

        entry.setIcon(
            room.getRoomtype() == FORUM ? new ImageIcon(getClass().getResource(Resource.OPEN_26x26))
                : new ImageIcon(getClass().getResource(Resource.LOCK_OPEN))
        );

        entry.setEntry(Entry.PUBLIC);
      }
      else {
        entry.setIcon(new ImageIcon(getClass().getResource(Resource.PADLOCK)));
        entry.setEntry(Entry.PROTECTED);
      }
      cellZutritt.setValue(entry);
      record.add(cellZutritt);

      Cell<String> cellLifetime = new Cell<>();

      // value ist ein FlipFlop

      cellLifetime
          .setValue(room.getLifetime() == Lifetime.PERMANENT ? unbegrenzt.toString() : begrenzt.toString());
      record.add(cellLifetime);

      model3.addRow(record);

      selectRoom.setRowHeight(model3.getRowCount() - 1, 28);
    }

    // Pseudozeile am Ende einfügen

    Record pseudo = new Record();

    Cell<String> cellPseudoOnline = new Cell<>();
    cellPseudoOnline.setValue("");
    pseudo.add(cellPseudoOnline);

    Cell<String> cellPseudoRoom = new Cell<>();
    cellPseudoRoom.setValue("");
    pseudo.add(cellPseudoRoom);

    Cell<String> cellPseudoOrt = new Cell<>();
    cellPseudoOrt.setValue("");
    pseudo.add(cellPseudoOrt);

    Cell<String> cellPseudoInhabler = new Cell<>();
    cellPseudoInhabler.setValue("");
    pseudo.add(cellPseudoInhabler);

    Cell<String> cellPseudoZutritt = new Cell<>();
    cellPseudoZutritt.setValue("");
    pseudo.add(cellPseudoZutritt);

    Cell<String> cellPseudoLifetime = new Cell<>();
    cellPseudoLifetime.setValue("");
    pseudo.add(cellPseudoLifetime);

    model3.addRow(pseudo);

  }



  /**
   * Fenster schließen.
   */
  class FrameAction extends InternalFrameAdapter {

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

  }

}
