/* $Id: DSCFileLoader5002.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
 * ver 5002 用のDSCFileLoader
 * 
 */
public class DSCFileLoader5002 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 DSCFileLoader5002(){
    }
    
    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());
        ArrayList tmpLineNos = new ArrayList(header.getSlitCount());
        ArrayList tmpSlitNos = new ArrayList(header.getSlitCount());
        
        while (true) {
            buffer_.clear();
            if (inChannel.read(buffer_) < 0) {
                break;
            }
            buffer_.flip();
            constructData(dataArray, areaArray, tmpLineNos, tmpSlitNos, buffer_, header.getDscDimension());
        }
        inChannel.close();
        double[][] dscData = (double[][]) dataArray.toArray(new double[0][]);
        Rectangle[] areaData = (Rectangle[]) areaArray.toArray(new Rectangle[0]);
        Integer[] lineNoIntegers = (Integer[]) tmpLineNos.toArray(new Integer[0]);
        Integer[] slitNoIntegers = (Integer[]) tmpSlitNos.toArray(new Integer[0]);
        
        int[] lineNos = new int[lineNoIntegers.length];
        for (int i = 0; i < lineNos.length; i++) {
            lineNos[i] = lineNoIntegers[i].intValue();
        }
        
        int[] slitNos = new int[slitNoIntegers.length];
        for (int i = 0; i < slitNos.length; i++) {
            slitNos[i] = slitNoIntegers[i].intValue();
        }

        dataContainer.addDscData(header, areaData, dscData, lineNos, slitNos);
        return dataContainer;
    }

    protected void constructData(ArrayList dscDataArray, ArrayList areaArray, ArrayList lineNos, ArrayList slitNos, ByteBuffer buffer, int dim) {
        int[] rect = new int[4];
        int slitNo = 0;
        int lineNo = 0;
        while (buffer.position() < buffer.limit()) {
//            read Slit And LineNo
            slitNo = (int) buffer.getShort();
            lineNo = (int) buffer.getShort();
            slitNos.add(new Integer(slitNo));
            lineNos.add(new Integer(lineNo));
            
//            予備領域分
            buffer.getShort();
            buffer.getShort();
            
            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 + 2);
        while (bufSize_ < BUF_MAX) {
            bufSize_ += bufSize_;
        }
        buffer_ = ByteBuffer.allocateDirect(bufSize_);
        buffer_.order(ByteOrder.LITTLE_ENDIAN);
    }
    
    public static void main(String[] args) {
    }
    
}
