package zero1hd.rhythmbullet.stages;

import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.Input.Keys;
import com.badlogic.gdx.scenes.scene2d.Actor;
import com.badlogic.gdx.scenes.scene2d.InputEvent;
import com.badlogic.gdx.scenes.scene2d.InputListener;
import com.badlogic.gdx.scenes.scene2d.Stage;
import com.badlogic.gdx.scenes.scene2d.ui.CheckBox;
import com.badlogic.gdx.scenes.scene2d.ui.ScrollPane;
import com.badlogic.gdx.scenes.scene2d.ui.Table;
import com.badlogic.gdx.scenes.scene2d.ui.TextButton;
import com.badlogic.gdx.scenes.scene2d.ui.Window;
import com.badlogic.gdx.scenes.scene2d.utils.ChangeListener;

import zero1hd.rhythmbullet.RhythmBullet;
import zero1hd.rhythmbullet.audio.AudioAnalyzer;
import zero1hd.rhythmbullet.audio.AudioDataPackage;
import zero1hd.rhythmbullet.audio.SongList;
import zero1hd.rhythmbullet.audio.map.RhythmMapAlgorithm;
import zero1hd.rhythmbullet.screens.MainMenu;
import zero1hd.rhythmbullet.ui.components.AudioGraph;
import zero1hd.rhythmbullet.ui.windows.BeatViewer;
import zero1hd.rhythmbullet.ui.windows.DifficultyWindow;
import zero1hd.rhythmbullet.ui.windows.FPSWindow;
import zero1hd.rhythmbullet.ui.windows.MusicController;
import zero1hd.rhythmbullet.ui.windows.MusicSelector;
import zero1hd.rhythmbullet.ui.windows.SpawnerWindow;
import zero1hd.rhythmbullet.ui.windows.VolumeWindow;
import zero1hd.rhythmbullet.util.MiniEvents;
import zero1hd.rhythmbullet.util.MiniListener;

public class CreativeHUD extends Stage implements MiniListener {
	MusicController musicPlayBackControls;
	MusicSelector musicSelector;
	FPSWindow fpsViewer;
	BeatViewer beatViewer;
	AudioGraph bassUMgraphWindow;
	AudioGraph mGraphWindow;
	VolumeWindow volumeWindow;
	SpawnerWindow spawnerWindow;
	DifficultyWindow diffWindow;
	
	AudioAnalyzer analyzer;
	RhythmMapAlgorithm mapGen;
	Window toolbox;
	
	GamePlayArea gpa;
	GameHUD ghud;
	public CreativeHUD(final RhythmBullet core, final MainMenu mainMenu, final GamePlayArea gpa, GameHUD ghud, SongList sl) {
		this.gpa = gpa;
		this.ghud = ghud;
		
		musicSelector = new MusicSelector("Select Audio File", core.getDefaultSkin(), core.getPrefs().getString("music dir"), sl);
		musicSelector.miniSender.addListener(this);
		musicSelector.refresh();

		fpsViewer = new FPSWindow("FPS", core.getDefaultSkin());
		beatViewer = new BeatViewer("Beat", core.getDefaultSkin());
		bassUMgraphWindow = new AudioGraph(512, 256);
		bassUMgraphWindow.setPosition(getWidth() - bassUMgraphWindow.getWidth(), 0);
		mGraphWindow = new AudioGraph(512, 256);
		mGraphWindow.setPosition(getWidth() - mGraphWindow.getWidth(), bassUMgraphWindow.getHeight());
		volumeWindow = new VolumeWindow("Volume adjustments", core.getDefaultSkin(), core.getPrefs());
		spawnerWindow = new SpawnerWindow("Spawn Tool", core.getDefaultSkin(), gpa.em, gpa.cm, gpa);
		diffWindow = new DifficultyWindow(core.getDefaultSkin());
		
		toolbox = new Window("Tools", core.getDefaultSkin(), "tinted");
		toolbox.defaults().pad(5f);
		
		Table toolboxToolSet = new Table(core.getDefaultSkin());
		toolboxToolSet.defaults().space(5f).left();
		
		//Back button
		TextButton backButton = new TextButton("Back", core.getDefaultSkin(), "window");
		backButton.addListener(new ChangeListener() {
			
			@Override
			public void changed(ChangeEvent event, Actor actor) {
				dispose();
				core.setScreen(mainMenu);
			}
		});
		toolboxToolSet.add(backButton);
		toolboxToolSet.row();

		final CheckBox musicSelectorCheckbox = new CheckBox(" Music selector", core.getDefaultSkin());
		musicSelectorCheckbox.addListener(new ChangeListener() {

			@Override
			public void changed(ChangeEvent event, Actor actor) {
				if (musicSelectorCheckbox.isChecked()) {
					addActor(musicSelector);
				} else {
					musicSelector.remove();
				}
			}
		});
		toolboxToolSet.add(musicSelectorCheckbox);
		toolboxToolSet.row();
		
		musicPlayBackControls = new MusicController(core.getDefaultSkin());
		final CheckBox musicPlayBackCheckbox = new CheckBox(" Playback controls", core.getDefaultSkin());
		musicPlayBackCheckbox.addListener(new ChangeListener() {

			@Override
			public void changed(ChangeEvent event, Actor actor) {
				if (musicPlayBackCheckbox.isChecked()) {
					addActor(musicPlayBackControls);
				} else {
					musicPlayBackControls.remove();
				}
			}
		});
		toolboxToolSet.add(musicPlayBackCheckbox);
		toolboxToolSet.row();
		
		final CheckBox beatViewerCheckbox = new CheckBox(" Beat viewer", core.getDefaultSkin());
		beatViewerCheckbox.addListener(new ChangeListener() {
			
			@Override
			public void changed(ChangeEvent event, Actor actor) {
				if (beatViewerCheckbox.isChecked()) {
					addActor(beatViewer);
				} else {
					beatViewer.remove();
				}
			}
		});
		toolboxToolSet.add(beatViewerCheckbox);
		toolboxToolSet.row();
		
		final CheckBox fpsViewerCheckbox = new CheckBox(" FPS", core.getDefaultSkin());
		fpsViewerCheckbox.addListener(new ChangeListener() {
			
			@Override
			public void changed(ChangeEvent event, Actor actor) {
				if (fpsViewerCheckbox.isChecked()) {
					addActor(fpsViewer);
				} else {
					fpsViewer.remove();
				}
			}
		});
		toolboxToolSet.add(fpsViewerCheckbox);
		toolboxToolSet.row();
		
		final CheckBox peakGraphCheckbox = new CheckBox(" Peak Graphs", core.getDefaultSkin());
		peakGraphCheckbox.addListener(new ChangeListener() {
			@Override
			public void changed(ChangeEvent event, Actor actor) {
				if (peakGraphCheckbox.isChecked()) {
					addActor(bassUMgraphWindow);
					addActor(mGraphWindow);
				} else {
					bassUMgraphWindow.remove();
					mGraphWindow.remove();
				}
				
			}
		});
		toolboxToolSet.add(peakGraphCheckbox);
		toolboxToolSet.row();
		
		final CheckBox volumeMixerCheckbox = new CheckBox(" Volume", core.getDefaultSkin());
		volumeMixerCheckbox.addListener(new ChangeListener() {
			@Override
			public void changed(ChangeEvent event, Actor actor) {
				if (volumeMixerCheckbox.isChecked()) {
					addActor(volumeWindow);
				} else {
					volumeWindow.remove();
				}
			}
		});
		toolboxToolSet.add(volumeMixerCheckbox);
		toolboxToolSet.row();
		
		final CheckBox spawnToolCheckBox = new CheckBox(" Spawn Tool", core.getDefaultSkin());
		spawnToolCheckBox.addListener(new ChangeListener() {
			@Override
			public void changed(ChangeEvent event, Actor actor) {
				if (spawnToolCheckBox.isChecked()) {
					addActor(spawnerWindow);
				} else {
					spawnerWindow.remove();
				}
			}
		});
		toolboxToolSet.add(spawnToolCheckBox);
		toolboxToolSet.row();
		
		final CheckBox diffAdjusterCheckBox = new CheckBox(" Difficulty", core.getDefaultSkin());
		diffAdjusterCheckBox.addListener(new ChangeListener() {
			
			@Override
			public void changed(ChangeEvent event, Actor actor) {
				if (diffAdjusterCheckBox.isChecked()) {
					addActor(diffWindow);
				} else {
					diffWindow.remove();
				}
			}
		});
		toolboxToolSet.add(diffAdjusterCheckBox);
		
		ScrollPane scroller = new ScrollPane(toolboxToolSet, core.getDefaultSkin());
		toolbox.add(scroller).height(250f).width(150f);
		addActor(toolbox);
		
		addListener(new InputListener() {
			@Override
			public boolean keyUp(InputEvent event, int keycode) {
				if (keycode == Keys.ENTER || keycode == Keys.ESCAPE) {
					setKeyboardFocus(null);
				}
				return super.keyUp(event, keycode);
			}
		});
		toolbox.pack();
	}

	@Override
	public void act(float delta) {
		super.act(delta);
	}
	
	@Override
	public void dispose() {
		if (analyzer != null) {
			analyzer.getAudioDataPackage().getMusicInfo().dispose();
		}
		super.dispose();
	}

	@Override
	public void handle(MiniEvents ID) {
		switch (ID) {
		case BACK:
			
			break;
		case MUSIC_SELECTED:
			beatViewer.setMusic(null, null);
			volumeWindow.setMusic(null);
			bassUMgraphWindow.setGraphingData(null, null, null);
			mGraphWindow.setGraphingData(null, null, null);
			if (musicPlayBackControls.getAudiofile() != null) {
				musicPlayBackControls.getAudiofile().dispose();
			}
			musicPlayBackControls.setAudiofile(null);
			analyzer = new AudioAnalyzer(musicSelector.getSelectedMusic());
			analyzer.sender.addListener(this);
			ghud.setMusic(null);

			break;
		case SPECTRAL_FLUX_DONE:
			analyzer.runThresholdCleaning();
			break;
		case MUSIC_DATA_CLEANED:
			mapGen = new RhythmMapAlgorithm(gpa.em, gpa.cm, analyzer.getAudioDataPackage(), diffWindow.getSpeedModifier(), diffWindow.getHealthModifier(), diffWindow.getOverallDiffMod());
			mapGen.getSender().addListener(this);
			Thread mapGenThread = new Thread(mapGen);
			mapGenThread.start();
			break;
		case MAP_GENERATED:
			Gdx.app.debug("creative", "successfully generated map.");
			AudioDataPackage adp = analyzer.getAudioDataPackage();
			musicPlayBackControls.setAudiofile(adp.getMusicInfo());
			volumeWindow.setMusic(adp.getMusicInfo());
			beatViewer.setMusic(adp.getMusicInfo(), analyzer.getAudioDataPackage());
			
			bassUMgraphWindow.setGraphingData(analyzer.getAudioDataPackage().getBassPeaks(), analyzer.getAudioDataPackage().getuMPeaks(), adp.getMusicInfo());
			bassUMgraphWindow.avgG1 = adp.getBassAvg();
			bassUMgraphWindow.normalDataG1 = adp.getBassMaxVal();
			bassUMgraphWindow.avgG2 = adp.getuMAvg();
			bassUMgraphWindow.normalDataG2 = adp.getuMMaxval();
			
			mGraphWindow.setGraphingData(analyzer.getAudioDataPackage().getmPeaks(), null, adp.getMusicInfo());
			mGraphWindow.normalDataG1 = adp.getmMaxVal();
			mGraphWindow.avgG1 = adp.getmAvg();
			gpa.setAudioMap(mapGen.getMap());
			ghud.setMusic(adp.getMusicInfo().getPlaybackMusic());
			break;
		default:
			break;
		}
	}
}
