package kr;

import java.io.File;
import java.io.IOException;

import javax.sound.midi.InvalidMidiDataException;
import javax.sound.midi.MidiSystem;
import javax.sound.midi.Sequence;
import javax.sound.midi.Track;
import javax.swing.JOptionPane;

import kr.midireader.krwriter.KRWriter;
import kr.miditunemodel.MidiTuneModel;
import kr.util.Listener;
import kr.util.ListenerManager;
import kr.util.NotificationManager;

public class MidiFileModel implements Listener
{
	private File file;
	private Sequence sequence;
	private Track[] tracks;
	private MidiTuneModel midiTuneModel;
	
	private boolean fileModified = false;

	public enum MessageType {
		FILE_CHANGED
	}

	public MidiFileModel()
	{
		midiTuneModel = new MidiTuneModel();
		
		ListenerManager.inst().registerListener(midiTuneModel.getNoteEventGroup(), this);
		ListenerManager.inst().registerListener(midiTuneModel.getKREventGroup(), this);
		ListenerManager.inst().registerListener(midiTuneModel.getMetrodomeEventGroup(), this);
	}
	
	public void setFile(File file)
	{
		this.file = file;

		try {
			sequence = MidiSystem.getSequence(file);
		} catch (InvalidMidiDataException e) {
			NotificationManager.inst().error("Mid file, "+file+", appears to be corrupt: "+e);
			throw new IllegalArgumentException(e);
		} catch (IOException e) {
			NotificationManager.inst().error("IO error reading mid file, "+file+": "+e);
			throw new IllegalArgumentException(e);
		}

		tracks = sequence.getTracks();
		
		fileModified = false;
		
		ListenerManager.inst().notify(this, MessageType.FILE_CHANGED);
	}

	public MidiTuneModel getMidiTuneModel() {
		return midiTuneModel;
	}

	public Track [] getTracks() {
		return tracks;
	}

	public Sequence getSequence() {
		return sequence;
	}

	public File getFile() {
		return file;
	}

	public void saveMidi(String krFileBase) {

		KRWriter krWriter = new KRWriter();
		try {
			krWriter.write(getMidiTuneModel().getNoteEventGroup(),
					getMidiTuneModel().getKREventGroup(),
					getMidiTuneModel().getMetrodomeEventGroup(),
					krFileBase+".mid");
		} catch (IOException e1) {
			NotificationManager.inst().error("Can not write '"+krFileBase+",mid': "+e1);
		}
		fileModified = false;
	}

	public void notify(Object source, Object type, Object... values) {
		fileModified = true;
	}

	public boolean isModified() {
		return fileModified;
	}

	public void notifyFileSaved() {
		fileModified = false;
		
	}
}
