/* $Id: DSCFileLoader.java 125 2011-03-09 09:49:51Z ohura $ */
/*
 * Created on 2006/08/24
 */
package jp.ac.hokudai.meme.core_smart_gs.io;

import java.awt.Rectangle;
import java.io.*;
import java.nio.*;
import java.nio.channels.FileChannel;
import java.util.ArrayList;

import jp.ac.hokudai.meme.core_smart_gs.*;

/**
 * @author hajime
 */
public class DSCFileLoader implements IDSCFileLoader {
    protected static final int HEADER_SIZE = 12;

    protected static final int BUF_MAX = 8192;

    protected static int bufSize_ = 0;

    protected ByteBuffer buffer_;

    // private int dbgCount_ = 0;

    public DSCFileLoader() {
    }

    public void loadDscFile(DSCData dataContainer, File dscFile)
            throws IOException, InvalidDataFormatException {
        FileChannel inChannel = new FileInputStream(dscFile).getChannel();
        DSCFileHeader header = loadHeader(inChannel);
        makeBuffer(header.getDscDimension());
        try {
            loadDscData(dataContainer, inChannel, header);
        } catch (InvalidDataFormatException e) {
            String mes = e.getMessage();
            mes += "in " + dscFile.getName() + " .";
            InvalidDataFormatException newEx = new InvalidDataFormatException(
                    mes);
            newEx.setFileName(dscFile.getName());
            throw newEx;
        }

    }

    protected DSCData loadDscData(DSCData dataContainer, FileChannel inChannel,
            DSCFileHeader header) throws IOException,
            InvalidDataFormatException {
        ArrayList dataArray = new ArrayList(header.getSlitCount());
        ArrayList areaArray = new ArrayList(header.getSlitCount());
        while (true) {
            buffer_.clear();
            if (inChannel.read(buffer_) < 0) {
                break;
            }
            buffer_.flip();
            constructData(dataArray, areaArray, buffer_, header
                    .getDscDimension());
        }
        inChannel.close();
        double[][] dscData = (double[][]) dataArray.toArray(new double[0][]);
        Rectangle[] areaData = (Rectangle[]) areaArray
                .toArray(new Rectangle[0]);
        dataContainer.addDscData(header, areaData, dscData);
        return dataContainer;
    }

    protected void constructData(ArrayList dscDataArray, ArrayList areaArray,
            ByteBuffer buffer, int dim) {
        int[] rect = new int[4];
        while (buffer.position() < buffer.limit()) {
            for (int i = 0; i < rect.length; i++) {
                rect[i] = (int) buffer.getShort();
            }
            areaArray.add(new Rectangle(rect[0], rect[1], rect[2] - rect[0],
                    rect[3] - rect[1]));
            double[] features = new double[dim];
            for (int i = 0; i < dim; i++) {
                features[i] = buffer.getDouble();
            }
            dscDataArray.add(features);
            // dbgCount_ ++;
            // System.out.print(dbgCount_ + " ");
        }
    }

    protected DSCFileHeader loadHeader(FileChannel inChannel)
            throws IOException {
        ByteBuffer headerBuffer = ByteBuffer.allocate(HEADER_SIZE);
        headerBuffer.order(ByteOrder.LITTLE_ENDIAN);
        int read = inChannel.read(headerBuffer);
        headerBuffer.flip();
        byte[] fileType = new byte[2];
        fileType[0] = headerBuffer.get();
        fileType[1] = headerBuffer.get();
        int version = (int) headerBuffer.getShort();
        headerBuffer.getShort();// —\”õ—Ìˆæ
        int dscDimension = headerBuffer.getShort();
        int slitCount = headerBuffer.getInt();
        return new DSCFileHeader(DSCFileHeader.checkFType(fileType), version,
                dscDimension, slitCount);
    }

    protected void makeBuffer(int featDim) {
        int bufSize_ = 8 * (featDim + 1);
        while (bufSize_ < BUF_MAX) {
            bufSize_ += bufSize_;
        }
        buffer_ = ByteBuffer.allocateDirect(bufSize_);
        buffer_.order(ByteOrder.LITTLE_ENDIAN);
    }

    public static void main(String[] args) {
    }

}
