package org.broad.tribble.index;

import org.apache.log4j.Logger;
import org.broad.tribble.index.interval.IntervalTreeIndex;
import org.broad.tribble.index.linear.LinearIndex;
import org.broad.tribble.util.LittleEndianInputStream;
import org.broad.tribble.util.SeekableStreamFactory;

import java.io.BufferedInputStream;
import java.io.IOException;
import java.io.InputStream;

/**
 * Factory class for creating indexes.  It is the responsibility of this class to determine and create the
 * correct index type from the input file or stream
 */

public class IndexFactory {

    private static Logger log = Logger.getLogger(IndexFactory.class);

    final public static int LINEAR = 1;
    final public static int INTERVAL_TREE = 2;

    /**
     * Load in index from the specified file.   The type of index (LinearIndex or IntervalTreeIndex) is determined
     * at run time by reading the type flag in the file.
     *
     * @param indexFile
     * @return
     */
    public static Index loadIndex(String indexFile) {
        Index idx = null;
        InputStream is = null;
        try {
            is = SeekableStreamFactory.getStreamFor(indexFile);
            LittleEndianInputStream dis = new LittleEndianInputStream(new BufferedInputStream(is));

            // Read the type and version,  then create the appropriate type
            int magicNumber = dis.readInt();
            int type = dis.readInt();
            Class indexClass = getIndexClass(type);

            idx = (Index) indexClass.newInstance();
            idx.read(dis);


        } catch (Exception ex) {
            log.error("Error reading index file: " + indexFile, ex);
            // TODO -- throw application exception ?
            throw new RuntimeException(ex);
        }
        finally {
            if (is != null) {
                try {
                    is.close();
                } catch (IOException e) {
                    log.error("Error closing indexFile: " + indexFile, e);
                }
            }
        }
        return idx;
    }


    /**
     * @param type -- type flag
     * @return Return the index class for the type.
     */
    private static Class getIndexClass(int type) {
        switch (type) {
            case LINEAR:
                return LinearIndex.class;
            case INTERVAL_TREE:
                return IntervalTreeIndex.class;
            default:
                throw new RuntimeException("Unrecognized type flag in index file");
        }
    }

}
