/*
 * jNPad v0.3 - jNPad's an Simple Text Editor written in Java
 *
 * Copyright (C) 2014-2017  rgs
 *
 * Require JDK 1.6 (or later)
 *
 * This program is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License as published by the Free
 * Software Foundation; either version 2 of the License, or (at your option)
 * any later version.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
 * more details.
 *
 * You should have received a copy of the GNU General Public License along
 * with this program; if not, write to the Free Software Foundation, Inc.,
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 *
 *
 * Info, Questions, Suggestions & Bugs Report to rgsevero@gmail.com
 */

package jnpad.filebrowser;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.io.File;
import java.io.FileFilter;

import javax.swing.JLabel;
import javax.swing.JScrollPane;
import javax.swing.ScrollPaneConstants;
import javax.swing.SwingConstants;

import jnpad.GUIUtilities;
import jnpad.JNPadFrame;
import jnpad.config.Config;
import jnpad.config.Configurable;
import jnpad.ui.ColorUtilities;
import jnpad.ui.EscapableDialog;
import jnpad.ui.ReporterUtilities;
import jnpad.ui.SideBorder;
import jnpad.ui.plaf.LAFUtils;

/**
 * The Class FileBrowser.
 *
 * @version 0.3
 * @since   jNPad v0.1
 */
public class FileBrowser extends EscapableDialog implements Configurable {
  JScrollPane                 scrollPane       = new JScrollPane();
  FileList                    fileList;
  DirectoryFilter             directoryFilter  = new DirectoryFilter();
  FileBrowserFilter           fileFilter       = new FileBrowserFilter();
  JLabel                      info             = new JLabel();

  private JNPadFrame          jNPad;

  /** The Constant ENABLED. */
  private static final String ENABLED          = FileBrowserBundle.getString("FileBrowser.enabled"); //$NON-NLS-1$
  
  /** The Constant DISABLED. */
  private static final String DISABLED         = FileBrowserBundle.getString("FileBrowser.disabled"); //$NON-NLS-1$

  /** UID */
  private static final long   serialVersionUID = -9096054333515066973L;

  /**
   * 
   * @param jNPad JNPadFrame
   */
  public FileBrowser(JNPadFrame jNPad) {
    super(jNPad, true);

    this.jNPad = jNPad;

    setUndecorated(true);

    fileList = new FileList(this);

    goToHomeDir();

    scrollPane.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_NEVER);
    scrollPane.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
    scrollPane.getViewport().add(fileList, null);
    
    info.setText(FileBrowserBundle.getString("FileBrowser.info")); //$NON-NLS-1$
    info.setHorizontalAlignment(SwingConstants.CENTER);
    info.setOpaque(true);
    Font f = Config.BROWSER_NORMAL_FONT.getValue();
    info.setFont(new Font(f.getName(), Font.PLAIN, f.getSize() - 1));
    if (LAFUtils.isNimbusLAF()) {
      info.setBackground(new Color(242, 242, 189));
      info.setForeground(ColorUtilities.createPureColor(LAFUtils.getToolTipForeground()));
    }
    else {
      info.setBackground(LAFUtils.getToolTipBackground());
      info.setForeground(LAFUtils.getToolTipForeground());
    }
    Color c = info.getBackground().darker();
    info.setBorder(new SideBorder(null, c, c, c, 1));

    getContentPane().add(scrollPane, BorderLayout.CENTER);
    getContentPane().add(info, BorderLayout.SOUTH);

    // size
    int width = info.getPreferredSize().width + 10;
    if(width < 600) width = 600;
    int max = GUIUtilities.getScreenDimension().width - 40;
    if(width > max) width = max;
    setSize(new Dimension(width, 400));
    
    // location
    final double h = Config.BROWSER_LOCATION_HORIZONTAL.getValue();
    final double v = Config.BROWSER_LOCATION_VERTICAL.getValue();
    if ((Math.abs(h - 0.5) < .0000001 && Math.abs(v - 0.5) < .0000001) || h < 0 || v < 0) // Keep FindBugs happy if ((h == 0.5 && v == 0.5) || h < 0 || v < 0)
      setLocationRelativeTo(jNPad);
    else if (h >= 0 && h <= 1 && v >= 0 && v <= 1)
      GUIUtilities.setPositionFrameOnScreen(this, h, v);
    else
      setLocation((int) h, (int) v);
    
    // info visible
    info.setVisible(Config.BROWSER_INFO_VISIBLE.getValue());

    // transparency
    final float transparency = Config.BROWSER_TRANSPARENCY.getValue();
    if(transparency >= 0 && transparency < 1) {
      GUIUtilities.setWindowTransparency(this, transparency);
    }
  }

  /**
   * Configure.
   *
   * @param cfg int
   * @see jnpad.config.Configurable#configure(int)
   */
  @Override
  public void configure(final int cfg) {
    fileList.configure(cfg);
    refresh();
  }
  
  /**
   * Sets the position frame on screen.
   *
   * @param horizontalPercent the horizontal percent
   * @param verticalPercent the vertical percent
   */
  void setPositionFrameOnScreen(final double horizontalPercent, final double verticalPercent) {
    GUIUtilities.setPositionFrameOnScreen(this, horizontalPercent, verticalPercent);
    Config.BROWSER_LOCATION_HORIZONTAL.setValue(horizontalPercent);
    Config.BROWSER_LOCATION_VERTICAL.setValue(verticalPercent);
  }

  /**
   * Toggle info visible.
   */
  void toggleInfoVisible() {
    boolean b = Config.BROWSER_INFO_VISIBLE.getValue();
    Config.BROWSER_INFO_VISIBLE.setValue(!b);
    info.setVisible(!b);
    setStatus(FileBrowserBundle.getString("FileBrowser.status.info", !b ? ENABLED : DISABLED)); //$NON-NLS-1$
  }
  
  /**
   * Toggle color.
   */
  void toggleColor() {
    boolean b = Config.BROWSER_COLORS_ENABLED.getValue();
    Config.BROWSER_COLORS_ENABLED.setValue(!b);
    FileBrowserObject.updateDirColors();
    refresh();
    setStatus(FileBrowserBundle.getString("FileBrowser.status.color", !b ? ENABLED : DISABLED)); //$NON-NLS-1$
  }

  /**
   * Toggle human readable.
   */
  void toggleHumanReadable() {
    boolean b = Config.BROWSER_HUMAN_READABLE.getValue();
    Config.BROWSER_HUMAN_READABLE.setValue(!b);
    refresh();
    setStatus(FileBrowserBundle.getString("FileBrowser.status.humanReadable", !b ? ENABLED : DISABLED)); //$NON-NLS-1$
  }

  /**
   * Toggle classify.
   */
  void toggleClassify() {
    boolean b = Config.BROWSER_CLASSIFY.getValue();
    Config.BROWSER_CLASSIFY.setValue(!b);
    FileBrowserObject.updateDirColors();
    refresh();
    setStatus(FileBrowserBundle.getString("FileBrowser.status.classify", !b ? ENABLED : DISABLED)); //$NON-NLS-1$
  }

  /**
   *  
   * @see javax.swing.JComponent#requestFocus()
   */
  @Override
  public void requestFocus() {
    fileList.requestFocus();
  }

  /**
   * @return boolean
   * @see javax.swing.JComponent#requestFocusInWindow()
   */
  @Override
  public boolean requestFocusInWindow() {
    return fileList.requestFocusInWindow();
  }

  /**
   * Gets the file.
   *
   * @return File
   */
  public File getFile() {
    return fileList.getFile();
  }

  /**
   * Refresh.
   *
   * @param s String
   */
  public void refresh(String s) {
    fileList.refresh(s);
  }

  /**
   * Refresh.
   */
  public void refresh() {
    fileList.refresh();
  }

  /**
   * List file.
   *
   * @param file File
   * @return boolean
   */
  public boolean listFile(File file) {
    return fileList.listFile(file);
  }

  /**
   * Ir al directorio de trabajo
   */
  void goToHomeDir() {
    File file = new File(Config.CHOOSER_FILE_DIRECTORY.getValue());
    if (!file.exists())
      file = new File(System.getProperties().getProperty("user.dir", "/")); //$NON-NLS-1$ //$NON-NLS-2$
    if (!file.exists())
      file = new File(FileList.FILE_SYSTEM_ROOTS[FileList.FILE_SYSTEM_ROOTS.length - 1].getPath());
    listFile(file);
  }

  /**
   * 
   * @param s String
   */
  public void setHomeDir(String s) {
    setHomeDir(new File(s));
  }

  /**
   * 
   * @param file File
   */
  public void setHomeDir(File file) {
    if (file.exists() && file.isDirectory()) {
      Config.CHOOSER_FILE_DIRECTORY.setValue(file.getPath());
      setStatus(FileBrowserBundle.getString("FileBrowser.setHomeDir", file.getPath())); //$NON-NLS-1$
    }
  }

  /**
   * Open file.
   */
  public void openFile() {
    File file = new File(fileList.getPath());
    if (file.exists() && file.isFile()) {
      jNPad.openFile(file.getAbsolutePath());
      fileList.requestFocus();
    }
    else
    if (!file.exists()) {
      setStatus(FileBrowserBundle.getString("FileBrowser.openFile.error.status", file.getAbsolutePath())); //$NON-NLS-1$
      ReporterUtilities.reportError(jNPad,
                                    FileBrowserBundle.getString("FileBrowser.openFile.error.message", file.getAbsolutePath()), //$NON-NLS-1$
                                    FileBrowserBundle.getString("FileBrowser.openFile.error.title")); //$NON-NLS-1$
    }
  }
  
  /**
   * Sets the status.
   *
   * @param status the new status
   */
  void setStatus(String status) {
    jNPad.setStatus(status);
  }
}

///////////////////////////////////////////////////////////////////////////////
class DirectoryFilter implements FileFilter {
  /**
   * Implementa accept(File ) para aceptar todos los directorios
   *
   * @param file El archivo a aplicarle el filtro
   * @return <code>true</code> si acepta el archivo y <code>false</code> si no
   *         lo acepta
   */
  public boolean accept(File file) {
    return file.isDirectory();
  }
}
///////////////////////////////////////////////////////////////////////////////

///////////////////////////////////////////////////////////////////////////////
class FileBrowserFilter implements FileFilter {
  /**
   * Acepta todos los directorios y archivos(*.*).
   *
   * @param file archivo a aplicarle el filtro.
   * @return <code>true</code> si acepta el archivo y <code>false</code> si no
   *         lo acepta
   */
  public boolean accept(File file) {
    return file.isFile();
  }
}
///////////////////////////////////////////////////////////////////////////////
