/*
 * The MIT License
 * Copyright © 2025 Luis Andrés Lange <https://javacomm.net>
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */
package org.nexuswob.gui;

import java.awt.Component;
import java.awt.EventQueue;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.nio.file.Files;
import java.nio.file.InvalidPathException;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import javax.swing.AbstractAction;
import javax.swing.ActionMap;
import javax.swing.DefaultListSelectionModel;
import javax.swing.InputMap;
import javax.swing.JComponent;
import javax.swing.JTable;
import javax.swing.JTextField;
import javax.swing.KeyStroke;
import javax.swing.RowFilter;
import javax.swing.RowSorter;
import javax.swing.SortOrder;
import javax.swing.event.TableModelEvent;
import javax.swing.event.TableModelListener;
import javax.swing.table.TableModel;
import javax.swing.table.TableRowSorter;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.nexuswob.util.Util;



/**
 * Über den MediaFileChooser kann nur eine Datei ausgewählt werden. Dieser
 * FileChooser zeigt nach dem Aufruf eine sortierte Detailansicht nach Datum an.
 * Nach Dateien kann über das Eingabefeld Dateiname gesucht werden. Für das
 * Suchmuster sind keine Jokerzeichen notwendig. Bei einem leeren Eingabefeld
 * werden alle Dateien im Verzeichnis angezeigt.
 */
public class MediaFileChooser extends JavacommFileChooser {

  private static final long serialVersionUID = -1231989618871457796L;

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

  private JTable table = null;
  private JTextField textfield;
  private int row = 0;
  private TableRowSorter<? extends TableModel> sorter;

  public MediaFileChooser() {
    this(null);
  }



  /**
   * 
   * @param file
   *             a <code>String</code> giving the path to a file or directory
   */
  public MediaFileChooser(String file) {
    super(file);
    setNameWidth(700);
    setSizeWidth(100);
    setModifiedWidth(130);
    setTypeWidth(150);
  }



  /**
   * Markiere die ausgewählte Datei.
   */
  public void highligthRow() {
    table.setRowSelectionInterval(row, row);
  }



  /**
   * Das Texteingabefeld für Dateinamen. Der eingegebene Text ist gleich dem
   * Suchmuster. Jede Datei wird gefunden, die das Suchmuster enthält.
   */
  @SuppressWarnings("serial")
  public void inputfield() {
    List<Component> components = Util.getAllComponents(this);

    for (Component comp : components) {
      if (comp instanceof JTextField) {
        textfield = (JTextField) comp;

        InputMap inputmap = textfield.getInputMap(JComponent.WHEN_FOCUSED);
        ActionMap actionmap = textfield.getActionMap();
        inputmap.put(KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0), "ENTER");
        actionmap.put("ENTER", new AbstractAction() {

          @Override
          public void actionPerformed(ActionEvent event) {

            String text = textfield.getText();

            if (text.length() == 0) {

            }
            else {
              // * nicht erlaubt
              // ? nicht erlaubt
              // | nicht erlaubt
              try {
                Path path = Paths.get(text);
                if (Files.isDirectory(path)) {
                  setCurrentDirectory(path.toFile());
                  return;
                }
                else if (Files.isRegularFile(path)) {
                  setSelectedFile(path.toFile());
                  return;
                }
              }
              catch (InvalidPathException e) {
                log.warn(e.getMessage());
                return;
              }
            }

            String regex = text.length() == 0 ? ".+"
                : text.replace("[", "\\[").replace("{", "\\{").replace("+", "\\+");

            // Filtern
            RowFilter<TableModel, Object> filter = RowFilter.regexFilter(regex, 0);
            sorter.setRowFilter(filter);

            // Sortieren
            List<RowSorter.SortKey> sortkeys = new ArrayList<>();
            RowSorter.SortKey column_3 = new RowSorter.SortKey(3, SortOrder.DESCENDING);
            sortkeys.add(column_3);
            sorter.setSortKeys(sortkeys);

            table.setRowSorter(sorter);

          }
        });
        break;
      }
    }

  }



  @Override
  public void sort() {
    List<Component> components = Util.getAllComponents(this);

    for (Component comp : components) {
      if (comp instanceof JTable) {
        table = (JTable) comp;
        break;
      }
    }
    if (table == null) return;

    // Alle MouseListener entfernen, sonst gibt es 3 Listener
    // 3 Listener kommen aus dem JFIleChooser
    Arrays.stream(table.getMouseListeners()).forEach(listener -> table.removeMouseListener(listener));

    // Den Standard ListSelectionListener von JFileChooser entfernen
    // eiegenen ListeSelectionListener hinzufügen
    DefaultListSelectionModel listSelectionModel = (DefaultListSelectionModel) table.getSelectionModel();
    Arrays.stream(listSelectionModel.getListSelectionListeners())
        .forEach(listener -> listSelectionModel.removeListSelectionListener(listener));

    if (table.getMouseListeners().length == 0) {

      table.addMouseListener(new MouseAdapter() {

        @Override
        public void mousePressed(MouseEvent event) {
          row = table.rowAtPoint(event.getPoint());
          table.repaint();

        }



        @Override
        public void mouseReleased(MouseEvent event) {
          row = table.rowAtPoint(event.getPoint());
          int modelRow = table.convertRowIndexToModel(row);
          table.repaint();
          String text;
          if (event.getClickCount() >= 2) {
            text = table.getModel().getValueAt(modelRow, 0).toString();
            Path pathToFile = Paths.get(text);
            if (Files.isDirectory(pathToFile)) {
              setCurrentDirectory(pathToFile.toFile());
            }
            else {
              try {
                setSelectedFile(pathToFile.toFile());
              }
              catch (ArrayIndexOutOfBoundsException e) {}
              approveSelection();
            }
            return;
          }
          text = table.getModel().getValueAt(modelRow, 0).toString();
          try {
            setSelectedFile(Paths.get(text).toFile());
          }
          catch (ArrayIndexOutOfBoundsException e) {}
        }
      });
    }

    table.getModel().addTableModelListener(new TableModelListener() {

      @Override
      public void tableChanged(TableModelEvent event) {
        table.getModel().removeTableModelListener(this);
        EventQueue.invokeLater(() -> {
          sorter = (TableRowSorter<? extends TableModel>) table.getRowSorter();
          List<RowSorter.SortKey> sortkeys = new ArrayList<>();
          RowSorter.SortKey sortkey = new RowSorter.SortKey(3, SortOrder.DESCENDING);
          sortkeys.add(sortkey);
          sorter.setSortKeys(sortkeys);
        });
      }
    });

  }

}
