/**
 *  Copyright © 2023-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.administer;

import java.awt.event.ActionListener;
import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeSupport;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.time.format.FormatStyle;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import javax.swing.DefaultCellEditor;
import javax.swing.JCheckBox;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.ListSelectionModel;
import javax.swing.SwingConstants;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.JTableHeader;
import javax.swing.table.TableColumnModel;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.nexuswob.gui.TableModel3;
import org.nexuswob.util.Cell;
import org.nexuswob.util.Util.Record;
import net.javacomm.multilingual.Babelfish;
import net.javacomm.multilingual.MultilingualString;
import net.javacomm.multilingual.schema.ISO639;
import net.javacomm.multilingual.schema.KEY;
import net.javacomm.transfer.TransferBenutzerkonto;
import net.javacomm.window.manager.Control;



@SuppressWarnings("serial")
public class JScrollAnwender extends JScrollPane implements Babelfish {

  private final static Logger log = LogManager.getLogger(JScrollAnwender.class);

  public final static int NICKNAME = 0;
  public final static int MAIL = 1;
  public final static int DELETED = 2;
  public final static int ABLAUFDATUM = 3;
  private JTable table = new JTable();
  private TableModel3 model3 = new TableModel3() {

    @Override
    public boolean isCellEditable(int rowIndex, int columnIndex) {
      return columnIndex == DELETED;
    }

  };
  private Map<String, String> map = new HashMap<>();
  private TableColumnModel columnModel;
  private JTableHeader header;
  private MultilingualString deleted = new MultilingualString(KEY.STRING_LOGISCH_GELOESCHT);
  private MultilingualString correo = new MultilingualString(KEY.STRING_MAIL);
  private MultilingualString apodo = new MultilingualString(KEY.LABEL_SPITZNAME);
  private MultilingualString ablaufdatum = new MultilingualString(KEY.STRING_ABLAUFDATUM);
  private DefaultTableCellRenderer headerRenderer;
  private DefaultCellEditor odxEditor;
  private JCheckBox checkbox = new JCheckBox();
  private PropertyChangeSupport changes = new PropertyChangeSupport(this);

  public JScrollAnwender() {

    model3.setHeader(apodo.toString(), correo.toString(), deleted.toString(), ablaufdatum.toString());
    table.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
    table.setModel(model3);
    table.setRowHeight(26);
    table.setFillsViewportHeight(true);
    table.setAutoResizeMode(JTable.AUTO_RESIZE_SUBSEQUENT_COLUMNS);

    centerHeader();

    columnModel = table.getColumnModel();
    columnModel.getColumn(MAIL).setPreferredWidth(250);
    columnModel.getColumn(NICKNAME).setPreferredWidth(150);
    columnModel.getColumn(DELETED).setPreferredWidth(180);
    columnModel.getColumn(ABLAUFDATUM).setPreferredWidth(250);

    odxEditor = new DefaultCellEditor(checkbox);
    columnModel.getColumn(DELETED).setCellEditor(odxEditor);
    checkbox.setHorizontalAlignment(SwingConstants.CENTER);
    checkbox.addActionListener((event) -> {
      boolean value = !(Boolean) table.getValueAt(table.getSelectedRow(), table.getSelectedColumn());
      String mail = (String) model3.getValueAt(table.getSelectedRow(), MAIL);
      // update senden

      Update update = new Update();
      update.setDeleted(value);
      update.setUserid(map.get(mail));

      changes.firePropertyChange(JScrollModule.class.getName(), update, Control.UPDATE);

    });



    getViewport().setOpaque(true);
    setViewportView(table);
    setOpaque(true);
    setBorder(null);

  }



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



  public void removeUpdateListener(PropertyChangeListener listener) {
    changes.removePropertyChangeListener(listener);
  }



  public void removeAllListener() {
    for (PropertyChangeListener pl : changes.getPropertyChangeListeners()) {
      removeUpdateListener(pl);
    }
    for (ActionListener al : checkbox.getActionListeners()) {
      checkbox.removeActionListener(al);
    }
  }



  /**
   * Die Spaltenüberschriften werden zentriert.
   *
   */
  public void centerHeader() {
    header = table.getTableHeader();
    headerRenderer = (DefaultTableCellRenderer) header.getDefaultRenderer();
    headerRenderer.setHorizontalAlignment(SwingConstants.CENTER);
  }



  /**
   * Zeige das Benutzerkonto an.
   *
   * @param transferuser
   *                     alle Anwender
   */
  public void setBenutzerkonto(List<TransferBenutzerkonto> transferuser) {
    model3.removeAll();
    map.clear();

    transferuser.forEach(user -> {

      // 1. Zelle
      Record record = new Record();
      map.put(user.getMail(), user.getUid());

      // 2. Zelle
      Cell<String> nickname = new Cell<>();
      nickname.setValue(user.getNickname());
      record.add(nickname);

      // 3. Zelle
      Cell<String> mail = new Cell<>();
      mail.setValue(user.getMail());
      record.add(mail);

      // 4. Zelle
      Cell<Boolean> permission = new Cell<>();
      permission.setValue(user.isLdelete());
      record.add(permission);

      // 5. Zelle
      ZonedDateTime berechneterWert = user.getTime().plusDays(180);
      DateTimeFormatter formatter = DateTimeFormatter.ofLocalizedDateTime(FormatStyle.LONG)
          .withLocale(Locale.getDefault());
      ZonedDateTime zdt = berechneterWert.withZoneSameInstant(ZoneId.systemDefault());
      String datum = zdt.format(formatter);
      Cell<String> date = new Cell<>();
      date.setValue(datum);
      record.add(date);

      model3.addRow(record);

    });

  }



  @Override
  public void setLanguage(ISO639 code) {
    deleted.setLanguage(code);
    correo.setLanguage(code);
    apodo.setLanguage(code);
    ablaufdatum.setLanguage(code);
    columnModel.getColumn(DELETED).setHeaderValue(deleted.toString());
    columnModel.getColumn(MAIL).setHeaderValue(correo.toString());
    columnModel.getColumn(NICKNAME).setHeaderValue(apodo.toString());
    columnModel.getColumn(ABLAUFDATUM).setHeaderValue(ablaufdatum.toString());

  }

  /**
   * In Update sind die Änderungen gespeichert.
   *
   *
   * @author llange
   *
   */
  static class Update {

    private String userid;
    private boolean isDeleted;

    Update() {}



    String getUserid() {
      return userid;
    }



    void setUserid(String userid) {
      this.userid = userid;
    }



    boolean isDeleted() {
      return isDeleted;
    }



    void setDeleted(boolean isDeleted) {
      this.isDeleted = isDeleted;
    }

  }

  /**
   * Die Methode wird nur aufgerufen, wenn es einen Übertragungsfehler zum Server
   * gab. Der alte Zustand vor der Übetragung wird wieder angezeigt.
   */
  public void flipLogicallyDelete() {
    checkbox.setSelected(!(Boolean) table.getValueAt(table.getSelectedRow(), table.getSelectedColumn()));
  }

}
