/*
 *  Copyright 2002-2009 Mikhail Kryshen <mikhail@kryshen.net>
 *
 *  This file is part of BMTron.
 *
 *  BMTron is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation, either version 3 of the License, or
 *  (at your option) any later version.
 *
 *  BMTron 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 General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with BMTron.  If not, see <http://www.gnu.org/licenses/>.
 */

package kryshen.util;

import java.awt.Color;
import java.awt.Component;
import java.awt.Font;
import java.awt.Image;
import java.awt.MediaTracker;
import java.awt.Toolkit;
import java.io.DataInputStream;
import java.io.IOException;
import java.io.InputStream;

/**
 * Read "BM Resources" data.
 */
public class ResourceLoader {
    private static final byte[] FIRST_BYTES = "(BM Resources)".getBytes();
    private static final int VERSION = 3;

    public static final int DATA_INT = 4;
    public static final int DATA_IMAGE = 8;
    public static final int DATA_COLOR = 9;
    public static final int DATA_FONT = 10;

    private Component target;
    private Toolkit toolkit;
    private DataInputStream in;
    private String name;
    private int progress;

    private int recordType = -1;
    private String recordName = null;
    private Object record = null;

    public ResourceLoader(Component target, String name, 
			  InputStream inputStream) throws IOException {
	this.target = target;
	this.in = new DataInputStream(inputStream);
	this.name = name;
	this.toolkit = target.getToolkit();
	this.progress = 0;

	for (int i = 0; i <= FIRST_BYTES.length - 1; i++) {
	    if (FIRST_BYTES[i] != in.read()) 
		throw new IOException("Not a resource file");
	}
	
	if (in.readInt() != VERSION)
	    throw new IOException("Unsupported file format version");
	
	if (!name.equals(in.readUTF()))
	    throw new IOException("Bad resource file type");

	progress = in.readUnsignedByte();
    }

    /**
     * Load the next record.
     *
     * @return progress value from 0 to 255 (255 - last record loaded).
     */
    public synchronized int loadNext() 
	throws IOException, InterruptedException {

	if (progress == 0xFF)
	    throw new IOException("No more records.");
		
	if (progress == 0xFF) return 0xFF;
	
	record = null;
	recordType = in.readInt();
	recordName = in.readUTF();

	int length = in.readInt();


	if (recordType == DATA_IMAGE) {
	    
	    byte[] imageData = new byte[length];
	    in.readFully(imageData);
	    Image image = toolkit.createImage(imageData);
	    MediaTracker tracker = new MediaTracker(target);
	    tracker.addImage(image, 0);
	    tracker.waitForID(0);

	    record = image;
	    
	} else if (recordType == DATA_COLOR) {
	    
	    record = new Color(in.readInt());
	    
	} else if (recordType == DATA_FONT) {
	    
	    String fontName = in.readUTF();
	    int style = in.readInt();
	    int size = in.readInt();

	    record = new Font(fontName, style, size);
	    
	} else { 
	    record = null;
	    recordName = null;
	    recordType = -1;

	    if (length < 0) {
		throw new IOException("Could not skip unknown data: bad length.");
	    } else {
		for (; length > 0; length--)
		    in.read();
	    }
	}

	progress = in.readUnsignedByte();
	return progress;
    }

    public int getResourceType() {
	return recordType;
    }

    public String getResourceName() {
	return recordName;
    }

    public Object getResource() {
	return record;
    }

    public Image getImage() {
	return (recordType == DATA_IMAGE) ? 
	    (Image)record : null;
    }

    public Color getColor() {
	return (recordType == DATA_COLOR) ? 
	    (Color)record : null;
    }

    public Font getFont() {
	return (recordType == DATA_FONT) ? 
	    (Font)record : null;
    }
}
