package zero1hd.rhythmbullet.desktop.screens.main;

import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.ScreenAdapter;
import com.badlogic.gdx.graphics.GL20;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.graphics.g2d.Batch;
import com.badlogic.gdx.graphics.g2d.SpriteBatch;
import com.badlogic.gdx.math.Vector3;
import com.badlogic.gdx.scenes.scene2d.Actor;
import com.badlogic.gdx.scenes.scene2d.Stage;
import com.badlogic.gdx.scenes.scene2d.utils.ChangeListener;
import com.badlogic.gdx.utils.viewport.ScreenViewport;

import zero1hd.rhythmbullet.RhythmBullet;
import zero1hd.rhythmbullet.audio.AudioMetadataController;
import zero1hd.rhythmbullet.audio.MusicList;
import zero1hd.rhythmbullet.audio.MusicController;
import zero1hd.rhythmbullet.desktop.audio.processor.DesktopAudioProcessorFactory;
import zero1hd.rhythmbullet.graphics.shaders.BloomShader;
import zero1hd.rhythmbullet.graphics.ui.Page;
import zero1hd.rhythmbullet.util.ResizeReadyScreen;

public class MainScreen extends ScreenAdapter implements ResizeReadyScreen {
	private Stage stage;
	private Vector3 cameraPosition;
	private PageChangeListeners listeners;
	private String selectedPage;
	private MainPage mainPage;
	private OptionsPage optionsPage;
	private KeybindPage keybindPage;
	private GraphicsPage graphicsPage;
	private CreditsPage creditsPage;
	private MusicSelectionPage musicSelectionPage;
	private AnalysisPage analysisPage;
	
	private MusicController musicController;
	private AudioMetadataController musicMetadataController;
	
	private RhythmBullet rhythmBullet;
	
	private BloomShader bloomShader;
	
	private Texture background;
	
	private Batch screenBatch;
	private boolean resizing;
	
	public MainScreen(RhythmBullet core) {
		this.rhythmBullet = core;
		stage = new Stage(new ScreenViewport());
		cameraPosition = new Vector3(stage.getCamera().position);
		
		MusicList musicList = new MusicList(new DesktopAudioProcessorFactory(), core.getPreferences().getString("music dir"));
		musicController = new MusicController(musicList, core.getPreferences());
		musicController.setAutoPlay(true);
		musicController.setShuffle(true);
		musicMetadataController = new AudioMetadataController(musicList);
		
		listeners = new PageChangeListeners();
		screenBatch = new SpriteBatch();
	}
	
	@Override
	public void render(float delta) {
		Gdx.gl.glClearColor(0f, 0f, 0f, 1f);
        Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
        
        if (!resizing) {
    		stage.act(delta);
    		if (bloomShader != null) {
    			bloomShader.begin();
    			draw();
    			bloomShader.end(stage.getWidth(), stage.getHeight());
    		} else {
    			draw();
    		}
        }
        if (stage.getCamera().position.x != cameraPosition.x || stage.getCamera().position.y != cameraPosition.y) {
        	stage.getCamera().position.lerp(cameraPosition, 0.15f);
        	stage.getViewport().apply();
        }
		super.render(delta);
	}
	
	private void draw() {
		stage.getViewport().apply();
		screenBatch.begin();
		screenBatch.draw(background, 0, 0, stage.getViewport().getScreenWidth(), stage.getViewport().getScreenHeight());
		screenBatch.end();
		stage.draw();
	}
	
	@Override
	public void preAssetLoad() {
		resizing = true;
		stage.clear();
		if (bloomShader != null) {
			bloomShader.dispose();
			bloomShader = null;
		}
		background = null;
		musicController.deleteObservers();
		musicMetadataController.deleteObservers();
	}
	
	@Override
	public void postAssetLoad() {
		resizing = false;
		bloomShader = new BloomShader(screenBatch);
		
		background = rhythmBullet.getAssetManager().get("backgrounds/mainBG.png", Texture.class);
		
		mainPage = new MainPage(musicController, musicMetadataController, rhythmBullet.getAssetManager(), rhythmBullet.getSkin(), rhythmBullet.getScreenConfiguration(), listeners.musicSelectionPageButtonListener, listeners.optionsPageButtonListener);
		stage.addActor(mainPage);
		//End main menu

		optionsPage = new OptionsPage(musicController, rhythmBullet.getSkin(), rhythmBullet.getPreferences(), listeners.returnToMainPageListener, listeners.graphicsPageButtonListener, listeners.keybindPageButtonListener);
		stage.addActor(optionsPage);

		keybindPage = new KeybindPage(rhythmBullet.getAssetManager(), rhythmBullet.getSkin(), listeners.optionsPageButtonListener);
		stage.addActor(keybindPage);

		graphicsPage = new GraphicsPage(rhythmBullet.getSkin(), rhythmBullet.getPreferences(), listeners.optionsPageButtonListener);
		stage.addActor(graphicsPage);
		
		creditsPage = new CreditsPage(rhythmBullet.getSkin());
		stage.addActor(creditsPage);
		
		musicSelectionPage = new MusicSelectionPage(rhythmBullet.getAssetManager(), rhythmBullet.getSkin(), musicController, musicMetadataController, rhythmBullet.getScreenConfiguration(), listeners.returnToMainPageListener, listeners.analysisPageButtonListener);
		stage.addActor(musicSelectionPage);
		
		analysisPage = new AnalysisPage(musicController, musicMetadataController, rhythmBullet.getSkin(), listeners.musicSelectionPageButtonListener, listeners.confirmedSongListener);
		stage.addActor(analysisPage);
		
		musicController.getMusicList().attemptAsyncSearch(false);
		
		if (selectedPage != null) {
			for (Actor actor : stage.getActors().items) {
				if (actor.getName().equals(selectedPage)) {
					setDisplayedPage((Page) actor);
					break;
				}
			}
		}
	}
	
	@Override
	public void show() {
		Gdx.input.setInputProcessor(stage);
		super.show();
	}
	
	@Override
	public void hide() {
		saveAll();
		super.hide();
	}
	
	public void saveAll() {
		if (optionsPage != null) {
			optionsPage.saveOptions();
			rhythmBullet.getPreferences().flush();
		}
	}
	
	@Override
	public void resize(int width, int height) {
		stage.getViewport().update(width, height, false);
		super.resize(width, height);
	}
	
	@Override
	public void dispose() {
		Gdx.app.debug("Mainscreen", "disposing...");
		stage.dispose();
		musicMetadataController.dispose();
		screenBatch.dispose();
		super.dispose();
	}
	
	public void setDisplayedPage(Page page) {
		Gdx.app.debug("Mainscreen", "Switching to " + page.getName());
		page.setCameraPositionToPage(cameraPosition);
		this.selectedPage = page.getName();
	}
	
	private class PageChangeListeners {
		ChangeListener musicSelectionPageButtonListener = new ChangeListener() {
			@Override
			public void changed(ChangeEvent event, Actor actor) {
				setDisplayedPage(musicSelectionPage);
				mainPage.stopParticles();
			}
		};
		
		ChangeListener analysisPageButtonListener = new ChangeListener() {
			@Override
			public void changed(ChangeEvent event, Actor actor) {
				setDisplayedPage(analysisPage);
			}
		};
		
		ChangeListener returnToMainPageListener = new ChangeListener() {
			@Override
			public void changed(ChangeEvent event, Actor actor) {
				setDisplayedPage(mainPage);
			}
		};
		
		ChangeListener optionsPageButtonListener = new ChangeListener() {
			@Override
			public void changed(ChangeEvent event, Actor actor) {
				setDisplayedPage(optionsPage);
				mainPage.stopParticles();
			}
		};
		
		ChangeListener graphicsPageButtonListener = new ChangeListener() {
			@Override
			public void changed(ChangeEvent event, Actor actor) {
				setDisplayedPage(graphicsPage);
			}
		};
		
		ChangeListener keybindPageButtonListener = new ChangeListener() {
			@Override
			public void changed(ChangeEvent event, Actor actor) {
				setDisplayedPage(keybindPage);
			}
		};
		
		ChangeListener creditPageButtonListener = new ChangeListener() {
			@Override
			public void changed(ChangeEvent event, Actor actor) {
				setDisplayedPage(creditsPage);
				mainPage.stopParticles();
			}
		};
		
		ChangeListener confirmedSongListener = new ChangeListener() {
			@Override
			public void changed(ChangeEvent event, Actor actor) {
				
			}
		};
	}
}
