package albumgen.tools;

import java.io.*;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.*;

import albumgen.util.FileUtils;

public class ReorderFilesByDate {

    private final String INPUT_ROOT_DIR = "H:\\Pictures\\TOURS_2006\\in";
    
    private final String OUTPUT_ROOT_DIR = "K:\\TOURS_2006\\blah";

    /** 
     *  Note: Each entrry must consist of a relative directory (under INPUT_ROOT_DIR)
     *  plus a JPEG file name.
     *   -- The directory will be searched for other .JPEG files to process
     *   -- The file name nominates which Jpeg to use to synchronise the dates.
     */ 
    private final String[] SYNC_FILES = {
        "Amanda/IMG_2361.JPG",
        "Clayton/DSC00976.JPG",
        "Cubie/Loire valley 113.jpg",
        "Ella/CIMG0142.JPG",
        "Luke/IMG_3521.jpg",
        "Rich/IMG_0921.JPG"  
    };
    
    /** The date/time given to the synchronized file. */
    private final Date SYNC_DATE =
        new GregorianCalendar(20060501114500).getTime()
    
    /** Date format: used as a prefix when naming files. */
    private final DateFormat DATE_FORMAT = new SimpleDateFormat("yyyyMMdd_HHmmss")

    /** Number of millisecond adjustment to apply to each directory */
    private long[] m_Adjustments = new long[SYNC_FILES.length];
    
    
    //--------------------------------------------------------------------------------
    /**
     * Run me!
     @param args - unused.
     */
    public static void main(String[] args) {
        try {
            new ReorderFilesByDate();
        catch (IOException e) {
            e.printStackTrace();
        }
    }  
    //--------------------------------------------------------------------------------
    
    /** Constructor. Bulk of the code just slapped in here. (TODO: Break down) */
    public ReorderFilesByDate() throws IOException {
        int count = SYNC_FILES.length;
        
        //
        // Compute date adjustments for each directory from the selected sync-file.
        //
        for (int i = 0; i < count; i++) {
            File syncFile = new File(INPUT_ROOT_DIR + File.separatorChar + SYNC_FILES[i]);
            
            if (!syncFile.exists()) {
                throw new IOException(
                    "ERROR: Could not find file " + syncFile.toString());
            }
            
            Date fileSyncDate = FileUtils.extractDate(syncFile);
            m_Adjustments[i= SYNC_DATE.getTime() - fileSyncDate.getTime();
        }
        
        File outputDir = new File(OUTPUT_ROOT_DIR);
        if ((outputDir.exists() && (!outputDir.isDirectory() || !outputDir.canWrite()))) {
            throw new IOException("Cannot write directory " + OUTPUT_ROOT_DIR);
        }
        
        outputDir.mkdirs();
        
        if (!outputDir.exists() || !outputDir.isDirectory()) {
            throw new IOException("Could not create directory " + OUTPUT_ROOT_DIR);
        }
        
        //
        // Iterate through each directory.
        //
        for (int i = 0; i < count; i++) {

            //
            // Create output sub-directory
            //
            String outSubDirName = new File(SYNC_FILES[i]).getParent();
            File outSubDir = 
                new File(outputDir.getAbsolutePath() + File.separator + outSubDirName)
            outSubDir.mkdir();
            if (!outSubDir.exists()) {
                throw new IOException("Could not create directory " + outSubDir);
            }
            
            //
            // Iterate through all files in the directory containing each sync-file.
            //
            long adjustment = m_Adjustments[i];
            File[] files = getAllSiblingFiles(SYNC_FILES[i]);
            
            if (files == null) {
                throw new IOException(
                    "ERROR: Could not find directory containing " + SYNC_FILES[i]);
            }
            
            for (int j = 0; j < files.length; j++) {
                File inFile = files[j];
                File outFile = createAdjustedFile(outSubDir, inFile, adjustment);
                FileUtils.copyFile(inFile, outFile);
                setFileModifiedTime(inFile, outFile, adjustment)
            }
        }
    }
    
    /** 
     * Creates an empty file named appropriately, and located in the 
     * relevant output subdirectory
     
     @return a File object representing the renamed output file. 
     */
    private File createAdjustedFile(
    File outSubDir, File inFile, long adjustmentsthrows IOException {
        
        Date inDate = FileUtils.extractDate(inFile);
        File outFile = null;
        if (inDate == null) {
            //
            // If inDate is null, assume this is an EDITED file (not original
            // from camera). In this case, just prepend the subdirectory name
            // to the input file's name.
            //
            outFile = new File(
                outSubDir.getAbsolutePath() 
                File.separator + 
                outSubDir.getName() "_" + inFile.getName());
        else {
            
            // Create new file name from the subdirectory and the images adjusted date. 
            Date outDate = new Date(inDate.getTime() + adjustments);
            outFile = new File(
                outSubDir.getAbsolutePath() 
                File.separator + 
                DATE_FORMAT.format(outDate"_" + outSubDir.getName() 
                ".jpg");
        }
            
        
        if (outFile.exists()) {
            throw new IOException("ERROR: File already exists: " + outFile);
        }
        
        outFile.createNewFile();
        
        if (!outFile.exists()) {
            throw new IOException("ERROR: Error creating file : " + outFile);
        }
        
        return outFile;
    }
    
    private void setFileModifiedTime(File inFile, File outFile, long adjustment) {
        Date inDate = FileUtils.extractDate(inFile);
        if (inDate == null) {
            // If inDate is null, assume this is an EDITED file (not original
            // from camera). In this case, just copy the original's lastModified time.
            outFile.setLastModified(inFile.lastModified());
        else {
            
            // Create new file name from the subdirectory and the images adjusted date. 
            Date outDate = new Date(inDate.getTime() + adjustment);
            outFile.setLastModified(outDate.getTime());
        }
    }

    private File[] getAllSiblingFiles(String sync_file) {
        String parent = new File(sync_file).getParent();
        if (parent == null) {
            return null;
        }
        
        // Note: returns null if parent is not a directory.
        return new File(INPUT_ROOT_DIR + File.separatorChar + parent).listFiles();
    }
}