package theGhastModding.midiPlayer.midi;

import java.io.File;
import java.io.FileInputStream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import javax.swing.JOptionPane;

import theGhastModding.midiPlayer.gui.ProgressDialog;
import theGhastModding.midiPlayer.main.TheGhastMidiPlayerMain;

public class MIDILoader {
	
	private List<Track> tracks;
	private int type = 0;
	private int trackCount;
	private int TPB;
	private long lengthInTicks;
	private int notecount;
	public static int multiplier = 1;
	
	//public static long tickLimit = Long.MAX_VALUE;
	
	public MIDILoader(File f) throws Exception {
		this(new FileInputStream(f));
	}
	
	public static MIDILoader loadMidi(File midiFile){
		try {
			return new MIDILoader(midiFile);
		} catch (Exception e) {
			JOptionPane.showMessageDialog(TheGhastMidiPlayerMain.frame, "Error loading MIDI", "Error", JOptionPane.ERROR_MESSAGE);
			e.printStackTrace();
			return null;
		}
	}
	
	public MIDILoader(FileInputStream stream) throws Exception{
		loadMidi(stream);
	}
	
	private void loadMidi(FileInputStream stream) throws Exception {
		ProgressDialog.status = "Getting MIDI information";
		tracks = new ArrayList<Track>();
		byte[] indentifier = new byte[4];
		stream.read(indentifier);
		String s = new String(indentifier);
		if(!s.equals("MThd")){
			JOptionPane.showMessageDialog(TheGhastMidiPlayerMain.frame, "Error loading MIDI: File identifier not MThd", "Error", JOptionPane.ERROR_MESSAGE);
			return;
		}
		indentifier = null;
		s = null;
		byte[] headerSize = new byte[4];
		stream.read(headerSize);
		int size = bytesToInt(headerSize);
		s = null;
		headerSize = null;
		byte[] header = new byte[size];
		stream.read(header);
		type = bytesToInt(Arrays.copyOfRange(header, 0, 2));
		trackCount = bytesToInt(Arrays.copyOfRange(header, 2, 4));
		TPB  = bytesToInt(Arrays.copyOfRange(header, 4, 6)) * multiplier;
		/*int trackCountSetting = Integer.parseInt(TGMMIDIConverterPanel.settings.spinner_1.getValue().toString());
		if(trackCountSetting > 0 && trackCountSetting < trackCount){
			trackCount = trackCountSetting;
		}*/
		long[] lengths = new long[trackCount];
		for(int i = 0; i < trackCount; i++){
			System.out.println("Loading track " + i + " of " + trackCount);
			ProgressDialog.status = "Loading track " + Integer.toString(i + 1) + " of " + Integer.toString(trackCount);
			ProgressDialog.progress = (int)((double)i / (double)trackCount * 50D) + 1;
			Track t = new Track();
			boolean b = t.loadTrack(stream);
			lengths[i] = t.getLengthInTicks();
			notecount += t.getNotecount();
			if(!b){
				return;
			}
			tracks.add(t);
		}
		lengthInTicks = 0;
		for(long l:lengths){
			if(l > lengthInTicks){
				lengthInTicks = l;
			}
		}
		//lengthInTicks = tickLimit;
		System.out.println(notecount);
		stream.close();
	}
	
	public long getLengthInTicks(){
		return lengthInTicks;
	}
	
	public void unload(){
		for(Track t:tracks){
			t.unload();
		}
	}
	
	private int bytesToInt(byte[] lol){
	    int value = 0;
	    for (int i = 0; i < lol.length; i++) {
	        int shift = (lol.length - 1 - i) * 8;
	        value += (lol[i] & 0x000000FF) << shift;
	    }
	    return value;
	}
	
	public int getType(){
		return type;
	}
	
	public int getTrackCount(){
		return trackCount;
	}
	
	public List<Track> getTracks(){
		return tracks;
	}
	
	public int getTPB(){
		return TPB;
	}
	
	public int getNoteCount(){
		return notecount;
	}
	
}
