/*
    Copyright (C) 2013-2020 Nicola L.C. Talbot
    www.dickimaw-books.com

    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 3 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
*/
package com.dickimawbooks.makeglossariesgui;

import java.io.*;
import java.util.*;
import java.awt.Font;

import java.awt.event.ActionListener;
import javax.swing.JMenu;
import javax.swing.JMenuItem;
import javax.swing.JToolBar;
import javax.swing.UIManager;
import javax.swing.LookAndFeel;

public class MakeGlossariesProperties extends Properties
{
   public MakeGlossariesProperties(File propfile, File recentFile)
     throws IOException
   {
      super();

      this.propFile = propfile;
      this.recentFile = recentFile;

      recentList = new Vector<String>();

      BufferedReader in;

      if (propfile != null && propfile.exists())
      {
         in = new BufferedReader(new FileReader(propFile));

         load(in);

         in.close();
      }
      else
      {
         setDefaults();
      }

      if (recentFile != null && recentFile.exists())
      {
         in = new BufferedReader(new FileReader(recentFile));

         loadRecentFiles(in);

         in.close();
      }
   }

   public MakeGlossariesProperties()
   {
      super();

      propFile = null;
      recentFile = null;

      setDefaults();
   }

   protected void setDefaults()
   {
      setDefaultHomeDir();
      setProperty("language", Locale.getDefault().getDisplayLanguage().toLowerCase());
      setProperty("codepage", "utf8");
      setProperty("override", "false");
      setProperty("docdefscheck", "true");
      setProperty("langcheck", "true");
      setProperty("fontsize", "12");
      setProperty("fontname", "Serif");
      setProperty("fontstyle", ""+Font.PLAIN);
      setProperty("toolbar.position", "North");
      setProperty("toolbar.orientation", ""+JToolBar.HORIZONTAL);
   }

   public String getToolBarPosition()
   {
      String prop = getProperty("toolbar.position");

      return prop == null ? "North" : prop;
   }

   public void setToolBarPosition(String position)
   {
      setProperty("toolbar.position", position == null ? "North" : position);
   }

   public int getToolBarOrientation()
   {
      int orientation = JToolBar.HORIZONTAL;

      String prop = getProperty("toolbar.orientation");

      if (prop != null)
      {
         try
         {
            orientation = Integer.parseInt(prop);
         } 
         catch (NumberFormatException e)
         {
         }
      }

      return orientation;
   }

   public void setToolBarOrientation(int orientation)
   {
      setProperty("toolbar.orientation", ""+orientation);
   }

   public int getFontSize()
   {
      String prop = getProperty("fontsize");

      if (prop == null) return 12;

      try
      {
         return Integer.parseInt(prop);
      }
      catch (NumberFormatException e)
      {
      }

      return 12;
   }

   public int getFontStyle()
   {
      String prop = getProperty("fontstyle");

      if (prop == null) return Font.PLAIN;

      try
      {
         return Integer.parseInt(prop);
      }
      catch (NumberFormatException e)
      {
      }

      return Font.PLAIN;
   }

   public String getFontName()
   {
      String prop = getProperty("fontname");

      return prop == null ? "Serif" : prop;
   }

   public void setFontSize(int size)
   {
      setProperty("fontsize", ""+size);
   }

   public void setFontStyle(int style)
   {
      setProperty("fontstyle", ""+style);
   }

   public void setFontName(String name)
   {
      setProperty("fontname", name);
   }

   public String getDefaultXindyVariant()
   {
      String prop = getProperty("variant");

      return "".equals(prop) ? null : prop;
   }

   public void setDefaultXindyVariant(String variant)
   {
      setProperty("variant", variant==null?"":variant);
   }

   public String getDefaultLanguage()
   {
      String prop = getProperty("language");

      return prop == null ? "english" : prop;
   }

   public void setDefaultLanguage(String language)
   {
      setProperty("language", language);
   }

   public String getDefaultCodePage()
   {
      String prop = getProperty("codepage");

      return prop == null ? "utf8" : prop;
   }

   public void setDefaultCodePage(String codepage)
   {
      setProperty("codepage", codepage);
   }

   public void setOverride(boolean override)
   {
      setProperty("override", override?"true":"false");
   }

   public boolean isOverride()
   {
      String prop = getProperty("override");

      return prop == null ? false : Boolean.parseBoolean(prop);
   }

   public void setDocDefsCheck(boolean check)
   {
      setProperty("docdefscheck", check?"true":"false");
   }

   public boolean isDocDefsCheckOn()
   {
      String prop = getProperty("docdefscheck");

      return prop == null ? true : Boolean.parseBoolean(prop);
   }

   public void setMissingLangCheck(boolean check)
   {
      setProperty("langcheck", check?"true":"false");
   }

   public boolean isMissingLangCheckOn()
   {
      String prop = getProperty("langcheck");

      return prop == null ? true : Boolean.parseBoolean(prop);
   }

   public static MakeGlossariesProperties fetchProperties()
      throws IOException
   {
      File parent = getOrMakeConfigDir();
      File settings = null;
      File recent = null;

      if (parent != null)
      {
         settings = new File(parent, propName);
         recent = new File(parent, recentName);
      }

      return new MakeGlossariesProperties(settings, recent);
   }

   public void save(MakeGlossariesGUI app) throws IOException
   {
      File parent = getConfigDir();

      if (parent == null)
      {
         parent = getOrMakeConfigDir();
      }

      if (parent == null)
      {
         throw new IOException("Unable to create properties directory");
      }

      if (propFile == null)
      {
         propFile = new File(parent, propName);
      }

      if (getProperty("directory.setting").equals("last"))
      {
         setProperty("directory", app.getCurrentDirectoryName());
      }

      PrintWriter out = new PrintWriter(new FileWriter(propFile));

      store(out, "makeglossaries-gui properties");

      out.close();

      if (recentFile == null)
      {
         recentFile = new File(parent, recentName);
      }

      out = new PrintWriter(new FileWriter(recentFile));

      for (int i = 0, n = recentList.size(); i < n; i++)
      {
         out.println(recentList.get(i));
      }

      out.close();
   }

   public String getDefaultDirectory()
   {
      String settings = getProperty("directory.setting");

      if (settings == null) settings = "home";

      if (settings.equals("home"))
      {
         setProperty("directory", System.getProperty("user.home"));
      }

      return getProperty("directory");
   }

   public String getDefaultDirectorySetting()
   {
      return getProperty("directory.setting");
   }

   public String getMakeIndexApp()
   {
      String prop = getProperty("makeindex");

      if (prop == null || prop.equals("")) return null;

      return prop;
   }

   public String getXindyApp()
   {
      String prop = getProperty("xindy");

      if (prop == null || prop.equals("")) return null;

      return prop;
   }

   public void setDefaultCustomDir(String dir)
   {
      setProperty("directory", dir);
      setProperty("directory.setting", "custom");
   }

   public void setDefaultHomeDir()
   {
      setProperty("directory", System.getProperty("user.home"));
      setProperty("directory.setting", "home");
   }

   public void setDefaultLastDir()
   {
      setProperty("directory.setting", "last");
   }

   public void setMakeIndexApp(File pathToApp)
   {
      setMakeIndexApp(pathToApp.getAbsolutePath());
   }

   public void setMakeIndexApp(String pathToApp)
   {
      setProperty("makeindex", pathToApp);
   }

   public void setXindyApp(File pathToApp)
   {
      setXindyApp(pathToApp.getAbsolutePath());
   }

   public void setXindyApp(String pathToApp)
   {
      setProperty("xindy", pathToApp);
   }

   public String getLookAndFeel()
   {
      String prop = getProperty("look_and_feel");

      if (prop == null)
      {
         LookAndFeel current = UIManager.getLookAndFeel();

         if (current == null) return null;

         prop = current.getClass().getName();
         setProperty("look_and_feel", prop);
      }

      return prop;
   }

   public void setLookAndFeel(UIManager.LookAndFeelInfo info)
   {
      setLookAndFeel(info.getClassName());
   }

   public void setLookAndFeel(String lookAndFeel)
   {
      setProperty("look_and_feel", lookAndFeel);
   }

   private void loadRecentFiles(BufferedReader in)
     throws IOException
   {
      String line;

      while ((line = in.readLine()) != null)
      {
         recentList.add(line);
      }
   }

   public void addRecentFile(String fileName)
   {
      if (fileName == null)
      {
         throw new NullPointerException();
      }

      recentList.remove(fileName); // just in case it's already in the list
      recentList.add(fileName);
   }

   public void setRecentFiles(JMenu menu, ActionListener listener)
   {
      if (recentList == null) return;

      if (menu.getMenuComponentCount() > 0)
      {
         menu.removeAll();
      }

      int lastIdx = recentList.size()-1;

      int n = Math.min(MAX_RECENT_FILES-1, lastIdx);

      for (int i = 0; i <= n; i++)
      {
         File file = new File(recentList.get(lastIdx-i));
         String num = ""+i;
         JMenuItem item = new JMenuItem(num+": "+file.getName());
         item.setMnemonic(num.charAt(0));
         item.setToolTipText(file.getAbsolutePath());
         item.setActionCommand(num);
         item.addActionListener(listener);

         menu.add(item);
      }
   }

   public String getRecentFileName(int i)
   {
      return recentList.get(recentList.size()-1-i);
   }

   public static File getConfigDir()
   {
      File dir = null;

      String env = System.getenv("MAKEGLOSSARIES-SETTINGS");

      if (env != null)
      {
         dir = new File(env);

         if (dir.isDirectory()) return dir;
      }

      String home = System.getProperty("user.home");

      if (home == null) return null;

      dir = new File(home, ".makeglossaries");

      if (dir.isDirectory()) return dir;

      dir = new File(home, "makeglossaries-settings");

      if (dir.isDirectory()) return dir;

      return null;
   }

   public static File getOrMakeConfigDir()
   {
      File dir = null;

      String env = System.getenv("MAKEGLOSSARIES-SETTINGS");

      if (env != null)
      {
         dir = new File(env);

         if (!dir.exists())
         {
            if (dir.mkdir()) return dir;
         }

         if (dir.isDirectory()) return dir;
      }

      String home = System.getProperty("user.home");

      if (home == null) return null;

      File dir2;

      if (System.getProperty("os.name").toLowerCase().indexOf("windows") != -1)
      {
         dir = new File(home, "makeglossaries-settings");
         dir2 = new File(home, ".makeglossaries");
      }
      else
      {
         dir = new File(home, ".makeglossaries");
         dir2 = new File(home, "makeglossaries-settings");
      }

      if (dir.isDirectory()) return dir;

      if (dir2.isDirectory()) return dir2;

      if (dir.mkdir()) return dir;

      if (dir2.mkdir()) return dir2;

      return null;
   }

   private File propFile, recentFile;
   private static String propName = "makeglossaries.prop";
   private static String recentName = "recentfiles";

   private Vector<String> recentList;

   public static final int MAX_RECENT_FILES = 10;
}