/*
 * Gaia CU3 WP-T-360 FL Copyright (c) 2006-2011 Gaia Data Processing and Analysis Consortium (DPAC)
 * 
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 * 
 * This library 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
 * Lesser General Public License for more details.
 * 
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
 * MA 02110-1301, USA.
 */

package gaia.cu3.gbin2ascii;

import gaia.cu1.mdb.cu2.um.umtypes.dm.UMSuperNova;
import gaia.cu1.mdb.cu2.um.umtypes.dm.UMStellarSource;
import gaia.cu1.mdb.cu2.um.umtypes.dm.UMGalaxy;
import gaia.cu1.mdb.cu2.um.umtypes.dm.UMQuasar;
import gaia.cu1.tools.dal.file.FileStore;
import gaia.cu1.tools.dal.gbin.GbinFactory;
import gaia.cu1.tools.dal.gbin.GbinMetaData;
import gaia.cu1.tools.dal.gbin.GbinReader;
import gaia.cu1.tools.dal.gbin.GbinMetaData.ChunkMetaData;
import gaia.cu1.tools.exception.GaiaConfigurationException;
import gaia.cu1.tools.exception.GaiaDataAccessException;
import gaia.cu1.tools.exception.GaiaException;
import gaia.cu1.tools.util.GaiaFactory;
import gaia.cu1.tools.util.doc.FileLister;
import gaia.cu1.tools.util.props.PropertyLoader;
import gaia.cu3.gbin2ascii.converter.Converter;
import gaia.cu3.gbin2ascii.converter.UMSuperNovaAsciiConverter;
import gaia.cu3.gbin2ascii.converter.UMStellarSourceAsciiConverter;
import gaia.cu3.gbin2ascii.converter.UMQuasarAsciiConverter;
import gaia.cu3.gbin2ascii.converter.UMGalaxyAsciiConverter;

import java.io.Writer;
import java.io.File;
import java.io.FileWriter;
import java.io.FilenameFilter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;

// import org.slf4j.Logger;
// import org.slf4j.LoggerFactory;

/**
 * Converts Gbin files into ASCII files
 * 
 * @author Thomas Bruesemeister &lt;tbruese@ari.uni-heidelberg.de&gt;
 * @version $Id: $
 * 
 */
public class Gbin2Ascii {

    // public Logger logger = new LoggerFactory.getLogger(Gbin2Ascii.class);

    /**
     * Application entry point
     * 
     * @param args
     *            TBD
     * @throws GaiaConfigurationException
     */
    public static void main(String[] args) throws GaiaConfigurationException {

        PropertyLoader.load();

        if (args == null || args.length < 1) {
            
            System.err.println("Data directory argument missing.");
            return;
            
        }
        
        new Gbin2Ascii().convertDataFiles(new File(args[0]));

    }

    /**
     * Returns the converter for a given class type or null if no converter could be found
     * 
     * @return the converter for a given class type or null if no converter could be found
     */
    public Converter getConverterFor(Class<?> clazz) {

        if (clazz.equals(UMSuperNova.class)) {
            return new UMSuperNovaAsciiConverter();
        } else if (clazz.equals(UMGalaxy.class)) {
            return new UMGalaxyAsciiConverter();
        } else if (clazz.equals(UMStellarSource.class)) {
            return new UMStellarSourceAsciiConverter();
        } else if (clazz.equals(UMQuasar.class)) {
            return new UMQuasarAsciiConverter();
        } else {
            return null;
        }

    }

    /**
     * Converts all gbins in the data directory in case a suitable converter is found.
     * 
     * @param dataDir
     *            the data directory containing the gbin files
     */
    public void convertDataFiles(File dataDir) {

        try {

            Collection<File> dataFiles = getDataFiles(dataDir);

            for (Iterator<File> it = dataFiles.iterator(); it.hasNext();) {

                File file = it.next();

                GbinReader<?> reader;

                reader = GbinFactory.getGbinReader(file);

                Class<?> clazz = null;

                GbinMetaData bm = reader.getGbinMetaData();
                ArrayList<ChunkMetaData> ch = (ArrayList<ChunkMetaData>) bm.getChunkList();

                if (ch.size() > 0) {

                    clazz = GaiaFactory.getClassMap().getDefinition(Class.forName(ch.get(0).classKey()));

                } else {

                    reader.close();

                    reader = GbinFactory.getGbinReader(file);
                    
                    if (reader.hasNext()) {
                        clazz = GaiaFactory.getClassMap().getDefinition(reader.next().getClass());
                    }

                    reader.close();
                }

                System.err.println("Converting file " + file.getName() + ", type: " + clazz.getName());
                
                try {
                    
                    this.convertDataFile(clazz, file);
                    
                } catch (IOException e) {
                    
                   System.err.println("Got an " + e.getClass().getSimpleName() + ": " + e.getMessage());
                }
                
            }

        } catch (GaiaException e) {
            System.err.println("Got a" + e.getClass().getSimpleName() + ": " + e.getMessage());
        } catch (ClassNotFoundException e) {
            System.err.println("Got a" + e.getClass().getSimpleName() + ": " + e.getMessage());
        }

    }

    /**
     * Converts and writes the given file
     * 
     * @param clazz
     *            the class type of the given file
     * @param file
     *            the file to convert and write
     * 
     * @throws IOException
     *             in case writing the converted file failed
     */
    public void convertDataFile(Class<?> clazz, File file) throws IOException {

        Converter converter = this.getConverterFor(clazz);

        if (converter == null) {

            System.err.println("No converter found for " + file.getName());

        } else {
            converter.convert(file, System.out);
        }

    }

    /**
     * Returns a list of gbin files, taken from ExtractIngest
     * 
     * @param location
     * @return
     * @throws GaiaDataAccessException
     */
    private Collection<File> getDataFiles(File location)

    throws GaiaDataAccessException {
        Collection<File> c = FileLister.listFiles(location, new GbinFileFilter(), true);
        return c;

    }

    /**
     * Simple file filter, taken from ExtractIngest
     * 
     */
    class GbinFileFilter implements FilenameFilter {

        private String fileEnding = ".gbin";

        public GbinFileFilter() {

            try {
                fileEnding = FileStore.fileEnding[FileStore.getFileFormat()];
            } catch (GaiaConfigurationException e) {
                System.err.println("Got a " + e.getClass().getSimpleName() + ": " + e.getMessage());
            }

        }

        public boolean accept(File dir, String name) {
            return name.endsWith(fileEnding);
        }
    }

}
