package zero1hd.polyjet.ui.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.polyjet.Polyjet;
import zero1hd.polyjet.audio.AudioAnalyzer;
import zero1hd.polyjet.screens.MainMenu;
import zero1hd.polyjet.ui.windows.BeatViewer;
import zero1hd.polyjet.ui.windows.FPSWindow;
import zero1hd.polyjet.ui.windows.GraphWindow;
import zero1hd.polyjet.ui.windows.MusicController;
import zero1hd.polyjet.ui.windows.MusicSelector;
import zero1hd.polyjet.ui.windows.VolumeWindow;
import zero1hd.polyjet.util.MiniEvents;
import zero1hd.polyjet.util.MiniListener;

public class CreativeStage extends Stage implements MiniListener {
	MusicController musicPlayBackControls;
	MusicSelector musicSelector;
	FPSWindow fpsViewer;
	
	BeatViewer beatViewer;
	GraphWindow graphViewer;
	VolumeWindow volumeWindow;
	
	AudioAnalyzer analyzer;
	Window toolbox;
	Polyjet core;
	
	public CreativeStage(final Polyjet core, final MainMenu mainMenu) {
		this.core = core;
		musicSelector = new MusicSelector("Select Audio File", core.getDefaultSkin(), core.getPrefs().getString("music dir"), "default");
		musicSelector.miniSender.addListener(this);
		musicSelector.refresh();

		fpsViewer = new FPSWindow("FPS", core.getDefaultSkin());

		beatViewer = new BeatViewer("Beat", core.getDefaultSkin(), core);
		
		graphViewer = new GraphWindow("Peak Values", core.getDefaultSkin());
		volumeWindow = new VolumeWindow("Volume adjustments", core.getDefaultSkin(), core.getPrefs());
		
		//Back button
		TextButton backButton = new TextButton("Back", core.getDefaultSkin());
		backButton.addListener(new ChangeListener() {
			
			@Override
			public void changed(ChangeEvent event, Actor actor) {
				dispose();
				musicSelector.getSelectedMusic().reset();
				core.setScreen(mainMenu);
			}
		});
		backButton.setPosition(10, Gdx.graphics.getHeight()-backButton.getHeight()-10);
		addActor(backButton);
		
		
		toolbox = new Window("Tools", core.getDefaultSkin());
		toolbox.defaults().pad(5f);
		
		Table toolboxToolSet = new Table(core.getDefaultSkin());
		toolboxToolSet.defaults().space(5f);
		
		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 Graph", core.getDefaultSkin());
		peakGraphCheckbox.addListener(new ChangeListener() {
			@Override
			public void changed(ChangeEvent event, Actor actor) {
				if (peakGraphCheckbox.isChecked()) {
					addActor(graphViewer);
				} else {
					graphViewer.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);
		
		ScrollPane scroller = new ScrollPane(toolboxToolSet, core.getDefaultSkin());
		toolbox.add(scroller).expand().fill();
		toolbox.setSize(300, 300);
		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);
			}
		});
	}

	@Override
	public void act(float delta) {
		if (musicPlayBackControls.getAudiofile() != null) {
			musicPlayBackControls.getAudiofile().readIndexUpdate();
		}
		super.act(delta);
	}
	
	@Override
	public void dispose() {
		musicSelector.getSelectedMusic().dispose();
		super.dispose();
	}

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

			analyzer.startAnalyticalThread(musicSelector.getSelectedMusic());
			break;
		case SPECTRAL_FLUX_DONE:
			analyzer.runThresholdCleaning();
			break;
		case MUSIC_DATA_CLEANED:
			musicPlayBackControls.setAudiofile(musicSelector.getSelectedMusic());
			volumeWindow.setMusic(musicPlayBackControls.getAudiofile());
			beatViewer.setMusic(musicPlayBackControls.getAudiofile(), analyzer);
			graphViewer.setData(analyzer.getBassPeaks(), analyzer.getUMPeaks(), musicPlayBackControls.getAudiofile());
			break;
		case MAP_GENERATED:
			break;
		default:
			break;
		}
	}
}
