package org.levigo.jadice.server.converterclient.util;

import java.io.File;
import java.io.IOException;
import java.util.Map;
import java.util.regex.Matcher;

import org.apache.log4j.Logger;
import org.levigo.jadice.server.converterclient.Preferences;

import com.levigo.jadice.filetype.Analyzer;
import com.levigo.jadice.filetype.AnalyzerException;
import com.levigo.jadice.filetype.UncloseableSeekableInputStreamWrapper;
import com.levigo.jadice.filetype.database.ExtensionAction;
import com.levigo.jadice.server.Job;
import com.levigo.jadice.server.shared.types.Stream;

public class FilenameGenerator {
  
  private static final Logger LOGGER = Logger.getLogger(FilenameGenerator.class);

  public final static String DEFAULT_PATTERN = PatternKeys.ORIGINAL_FILENAME + "-" + PatternKeys.NUMMER + "."
      + PatternKeys.EXTENSION;

  public static interface PatternKeys {
    final String JOB_ID = "%j";
    final String ORIGINAL_FILENAME = "%f";
    final String EXTENSION = "%e";
    final String NUMMER = "%n";
    final String TIMESTAMP = "%t";
    final String PERCENT_SIGN = "%%";
  }

  public static String generateFilename(Job job, Stream stream, File originalFile, int nmbr) {
    String pttrn = Preferences.resultFilenamePatternProperty().getValue();
    // Caveat! Matcher.quoteReplacement(...) in order to escape $ and \ signs
    
    if (mustDetermineExtension()) {
      final String extension = determineExtension(stream);
      pttrn = pttrn.replaceAll(PatternKeys.EXTENSION, Matcher.quoteReplacement(extension));
    }
    return pttrn.replaceAll(PatternKeys.JOB_ID, Matcher.quoteReplacement(job.getUUID()))//
        .replaceAll(PatternKeys.ORIGINAL_FILENAME, Matcher.quoteReplacement(originalFile.getName()))//
        .replaceAll(PatternKeys.NUMMER, Integer.toString(nmbr))//
        .replaceAll(PatternKeys.TIMESTAMP, Long.toString(System.currentTimeMillis()))//
        .replaceAll(PatternKeys.PERCENT_SIGN, "%")
        // Paranoia checks to prevent from storing in other folders:
        .replaceAll("/", "")//
        .replace("\\", "");
  }
  
  protected static boolean mustDetermineExtension() {
    return Preferences.resultFilenamePatternProperty().getValue().contains(PatternKeys.EXTENSION);
  }

  private static String determineExtension(Stream stream) {
    try {
      final Analyzer al = Analyzer.getInstance("/magic.xml");
      final UncloseableSeekableInputStreamWrapper usis = new UncloseableSeekableInputStreamWrapper(stream.getInputStream());
      final Map<String, Object> alResults;
      try {
        usis.seek(0);
        usis.lockClose();
        alResults = al.analyze(usis);
      } finally {
        usis.seek(0);
        usis.unlockClose();
      }

      final Object o = alResults.get(ExtensionAction.KEY);
      return (o != null) ? o.toString() : Preferences.defaultExtensionProperty().getValue();
    } catch (IOException | AnalyzerException e) {
      LOGGER.error("Could not determine file extension", e);
      return Preferences.defaultExtensionProperty().getValue();
    }
  }

  /**
   * Explains the Filename pattern.
   * 
   * @param sep Separator between items
   * @return explanation
   * @see PatternKeys
   */
  public static String buildExplanationText(String sep) {
    String s = "";
    s += FilenameGenerator.PatternKeys.ORIGINAL_FILENAME + ": original filename";
    s += sep;
    s += FilenameGenerator.PatternKeys.JOB_ID + ": job ID";
    s += sep;
    s += FilenameGenerator.PatternKeys.NUMMER + ": sequential nmbr";
    s += sep;
    s += FilenameGenerator.PatternKeys.EXTENSION + ": result extension";
    s += sep;
    s += FilenameGenerator.PatternKeys.TIMESTAMP + ": timestamp";
    s += sep;
    s += FilenameGenerator.PatternKeys.PERCENT_SIGN + ": %";
    return s;
  }
}

@@ -705,16 +705,58 @@
 class);%0D
+%0A  %0D%0A  private static Analyzer analyzer; %0D
 %0A%0D%0A  pub
@@ -2400,71 +2400,8 @@
  %7B%0D%0A
-      final Analyzer al = Analyzer.getInstance(%22/magic.xml%22);%0D%0A
     
@@ -2518,24 +2518,24 @@
 Stream());%0D%0A
+
       final 
@@ -2649,18 +2649,29 @@
 sults = 
-al
+getAnalyzer()
 .analyze
@@ -3089,24 +3089,24 @@
 etValue();%0D%0A
-
     %7D%0D%0A  %7D%0D%0A
@@ -3107,16 +3107,227 @@
 %0A  %7D%0D%0A%0D%0A
+  private static Analyzer getAnalyzer() throws AnalyzerException %7B%0D%0A    // Initiate lazily%0D%0A    if (analyzer == null) %7B%0D%0A      analyzer = Analyzer.getInstance(%22/magic.xml%22);%0D%0A    %7D%0D%0A    return analyzer;%0D%0A  %7D%0D%0A%0D%0A
   /**%0D%0A 

Use a shared filetype analyzer