package zero1hd.rhythmbullet;

import com.badlogic.gdx.Application;
import com.badlogic.gdx.Game;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.Preferences;
import com.badlogic.gdx.assets.AssetManager;
import com.badlogic.gdx.assets.loaders.ParticleEffectLoader;
import com.badlogic.gdx.assets.loaders.SoundLoader;
import com.badlogic.gdx.assets.loaders.TextureAtlasLoader;
import com.badlogic.gdx.assets.loaders.TextureLoader;
import com.badlogic.gdx.assets.loaders.resolvers.InternalFileHandleResolver;
import com.badlogic.gdx.assets.loaders.resolvers.ResolutionFileResolver.Resolution;
import com.badlogic.gdx.audio.Sound;
import com.badlogic.gdx.graphics.Color;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.graphics.g2d.ParticleEffect;
import com.badlogic.gdx.graphics.g2d.TextureAtlas;
import com.badlogic.gdx.graphics.g2d.freetype.FreeTypeFontGenerator;
import com.badlogic.gdx.graphics.g2d.freetype.FreeTypeFontGenerator.FreeTypeFontParameter;
import com.badlogic.gdx.math.MathUtils;
import com.badlogic.gdx.scenes.scene2d.ui.CheckBox.CheckBoxStyle;
import com.badlogic.gdx.scenes.scene2d.ui.Label.LabelStyle;
import com.badlogic.gdx.scenes.scene2d.ui.List.ListStyle;
import com.badlogic.gdx.scenes.scene2d.ui.ScrollPane.ScrollPaneStyle;
import com.badlogic.gdx.scenes.scene2d.ui.SelectBox.SelectBoxStyle;
import com.badlogic.gdx.scenes.scene2d.ui.Skin;
import com.badlogic.gdx.scenes.scene2d.ui.Slider.SliderStyle;
import com.badlogic.gdx.scenes.scene2d.ui.TextButton.TextButtonStyle;
import com.badlogic.gdx.scenes.scene2d.ui.TextField.TextFieldStyle;
import com.badlogic.gdx.scenes.scene2d.ui.Window.WindowStyle;

import zero1hd.rhythmbullet.screens.LoadingScreen;
import zero1hd.rhythmbullet.util.GenericFileTypeHandler;
import zero1hd.rhythmbullet.util.RoundingResolutionHandler;
import zero1hd.rhythmbullet.util.TransitionAdapter;


public class RhythmBullet extends Game {
	private boolean initComplete = false;
	private boolean resizing;
	
	public static final int GAME_AREA_WIDTH = 64;
	public static final int GAME_AREA_HEIGHT = 48;
	public static final String VERSION = "(0.1)R1-PreAlpha";
	
	private AssetManager assetManager = new AssetManager();
	private Skin defaultSkin = new Skin();
	private FreeTypeFontGenerator default_fontGenerator;
	private FreeTypeFontGenerator darktech_ldr_fontGenerator;
	TextureAtlas skinAtlas;
	private Preferences prefs;
	private RoundingResolutionHandler rRHandler;
	
	@Override
	public void create() {
		Gdx.app.setLogLevel(Application.LOG_DEBUG);
		prefs = Gdx.app.getPreferences("PolyJet_Preferences");
		
		if (getPrefs().getBoolean("fullscreen", true)) {
			Gdx.graphics.setFullscreenMode(Gdx.graphics.getDisplayMode());
		} else {
			Gdx.graphics.setWindowedMode(getPrefs().getInteger("screen-width"), getPrefs().getInteger("screen-height"));
		}
		
		Resolution[] resolution = {
				new Resolution(800, 480, "800x480"),
				new Resolution(1280, 720, "1280x720"),
				new Resolution(1366, 768, "1366x768"),
				new Resolution(1280, 800, "1280x800"),
				new Resolution(1920, 1080, "1920x1080"),
				new Resolution(1920, 1200, "1920x1200"),
				new Resolution(2560, 1440, "2560x1440"),
				new Resolution(3840, 2160, "3840x2160"),
				};
		InternalFileHandleResolver internalFileResolver = new InternalFileHandleResolver();
		rRHandler = new RoundingResolutionHandler(internalFileResolver, resolution);
		GenericFileTypeHandler genericFileFinder = new GenericFileTypeHandler(internalFileResolver);
		assetManager.setLoader(TextureAtlas.class, new TextureAtlasLoader(rRHandler));
		assetManager.setLoader(Texture.class, new TextureLoader(rRHandler));
		assetManager.setLoader(ParticleEffect.class, new ParticleEffectLoader(genericFileFinder));
		assetManager.setLoader(Sound.class, new SoundLoader(genericFileFinder));
		default_fontGenerator = new FreeTypeFontGenerator(Gdx.files.internal("fonts/Gasalt-Regular.ttf"));
		darktech_ldr_fontGenerator = new FreeTypeFontGenerator(Gdx.files.internal("fonts/darktech_ldr.ttf"));
		
		getrRHandler().setResolution(getPrefs().getInteger("screen-width"), getPrefs().getInteger("screen-height"));

		Gdx.app.debug("Prelaunch Debug Info", "\ncurrent window size: "
				+ Gdx.graphics.getWidth() + "x" + Gdx.graphics.getHeight() +"\n"
						+ "Pixel density (PPI): " + Gdx.graphics.getDensity());
		
		setScreen(new LoadingScreen(this));
	}
	
	@Override
	public void render() {
		if (resizing) {
			if (assetManager.update()) {
				Gdx.app.debug("Resize", "Post transition is happening");
				resizing = false;
				generateFonts(Gdx.graphics.getHeight());
				defineSkinStyles();
				assetManager.get("standard_thrust.p", ParticleEffect.class).flipY();
				((TransitionAdapter) getScreen()).postTransition();
			}
		}
		super.render();
	}
	
	@Override
	public void dispose() {
		Gdx.app.debug("Core", "disposing...");
		if (initComplete) {
			skinAtlas.dispose();
			getDefaultSkin().dispose();
			default_fontGenerator.dispose();
			darktech_ldr_fontGenerator.dispose();
			assetManager.dispose();
		}
		super.dispose();
	}
	
	@Override
	public void resize(int width, int height) {
		if (initComplete) {
			Gdx.app.debug("Resize", "Pre-transition is happening.");
			rRHandler.setResolution(width, height);
			((TransitionAdapter) getScreen()).preTransition();
			assetManager.clear();
			prefs.putInteger("screen-width", width);
			prefs.putInteger("screen-height", height);
			prefs.flush();
			resizing = true;
			queueAssets();
		}
		super.resize(width, height);
	}
	
	public int fontScale(float fontSize, int height) {
		return MathUtils.round(Gdx.graphics.getDensity()*(fontSize*height));
	}
	
	public AssetManager getAssetManager() {
		return assetManager;
	}

	public Skin getDefaultSkin() {
		return defaultSkin;
	}

	public Preferences getPrefs() {
		return prefs;
	}
	
	public void setInitComplete() {
		initComplete = true;
	}
	
	public void queueAssets() {
		assetManager.load("uiskin.atlas", TextureAtlas.class);
		assetManager.load("Tech-Circle1.png", Texture.class);
		assetManager.load("polyjet-standard.png", Texture.class);
		assetManager.load("standard_thrust.p", ParticleEffect.class);
		assetManager.load("keyboard.atlas", TextureAtlas.class);
		assetManager.load("cybercircle3B.png", Texture.class);
		assetManager.load("title.png", Texture.class);
		assetManager.load("cybercircle1.png", Texture.class);
		assetManager.load("defaultCover.png", Texture.class);
		assetManager.load("teleport-cloak.p", ParticleEffect.class);
		assetManager.load("pop_open.ogg", Sound.class);
		assetManager.load("pop_close.ogg", Sound.class);
		assetManager.load("laser.png", Texture.class);
		assetManager.load("pellet.png", Texture.class);
		assetManager.load("shard.png", Texture.class);
		assetManager.load("bar.png", Texture.class);
		assetManager.load("flake.png", Texture.class);
		assetManager.load("star_bg.png", Texture.class);
		assetManager.load("void_circle.png", Texture.class);
		assetManager.load("laser.ogg", Sound.class);
		assetManager.load("explosion.ogg", Sound.class);
		assetManager.load("disintegrate.ogg", Sound.class);
		assetManager.load("explosion-s.p", ParticleEffect.class);
		assetManager.load("tpSelector.png", Texture.class);
		assetManager.load("magic1.png", Texture.class);
	}
	public void generateFonts(final int height) {
		defaultSkin = new Skin();
		Gdx.app.debug("Prelaunch Debug Info", "Generating fonts...");
		skinAtlas = assetManager.get("uiskin.atlas", TextureAtlas.class);
		getDefaultSkin().addRegions(skinAtlas);
		
		getDefaultSkin().add("window-font", default_fontGenerator.generateFont(new FreeTypeFontParameter() {
			{
				size = 18;
			}
		}));
		getDefaultSkin().add("sub-font", default_fontGenerator.generateFont(new FreeTypeFontParameter() {
			{
				size = fontScale(0.04f, height);
			}
		}));
		getDefaultSkin().add("default-font", default_fontGenerator.generateFont(new FreeTypeFontParameter() {
			{
				size = fontScale(0.07f, height);
			}
		}));
		getDefaultSkin().add("large-font", default_fontGenerator.generateFont(new FreeTypeFontParameter() {
			{
				size = fontScale(0.085f, height);
			}
		}));
		getDefaultSkin().add("special-font", darktech_ldr_fontGenerator.generateFont(new FreeTypeFontParameter() {
			{
				size = fontScale(0.075f, height);
			}
		}));
	}
	
	public void defineSkinStyles() {
		getDefaultSkin().add("default", Color.WHITE);
		getDefaultSkin().add("inverse", Color.BLACK);
		
		TextButtonStyle defaultTextButton = new TextButtonStyle();
		defaultTextButton.up = getDefaultSkin().getDrawable("default-round");
		defaultTextButton.down = getDefaultSkin().getDrawable("default-round-down");
		defaultTextButton.font = getDefaultSkin().getFont("default-font");
		defaultTextButton.fontColor = getDefaultSkin().getColor("default");
		defaultTextButton.disabled = getDefaultSkin().getDrawable("default-round-disabled");
		getDefaultSkin().add("default", defaultTextButton);
		
		TextButtonStyle subTextbutton = new TextButtonStyle(defaultTextButton);
		subTextbutton.font = getDefaultSkin().getFont("sub-font");
		getDefaultSkin().add("sub", subTextbutton);
		
		TextButtonStyle windowTextButton = new TextButtonStyle(defaultTextButton);
		windowTextButton.font = getDefaultSkin().getFont("window-font");
		getDefaultSkin().add("window", windowTextButton);
		
		TextButtonStyle textButtonLeft = new TextButtonStyle();
		textButtonLeft.up = getDefaultSkin().getDrawable("left-button");
		textButtonLeft.down = getDefaultSkin().getDrawable("left-button-down");
		textButtonLeft.font = getDefaultSkin().getFont("default-font");
		textButtonLeft.fontColor = getDefaultSkin().getColor("default");
		getDefaultSkin().add("left", textButtonLeft);
		
		SliderStyle defaultSlider = new SliderStyle(getDefaultSkin().getDrawable("default-slider"), getDefaultSkin().getDrawable("default-slider-knob"));
		getDefaultSkin().add("default-horizontal", defaultSlider);
		
		SliderStyle vertSlider = new SliderStyle(defaultSlider);
		vertSlider.knob = getDefaultSkin().getDrawable("vertical-slider-knob");
		getDefaultSkin().add("default-vertical", vertSlider);
		
		LabelStyle defaultLabel = new LabelStyle();
		defaultLabel.font = getDefaultSkin().getFont("default-font");
		defaultLabel.fontColor = getDefaultSkin().getColor("default");
		getDefaultSkin().add("default", defaultLabel);
		
		TextFieldStyle defaultTextField = new TextFieldStyle(getDefaultSkin().getFont("sub-font"), getDefaultSkin().getColor("default"), getDefaultSkin().getDrawable("cursor"), getDefaultSkin().getDrawable("selection"), getDefaultSkin().getDrawable("textfield"));
		getDefaultSkin().add("default", defaultTextField);
		
		TextFieldStyle uiTextField = new TextFieldStyle(defaultTextField);
		uiTextField.font = getDefaultSkin().getFont("window-font");
		getDefaultSkin().add("ui", uiTextField);
		
		WindowStyle defaultWindow = new WindowStyle(getDefaultSkin().getFont("window-font"), getDefaultSkin().getColor("default"), getDefaultSkin().getDrawable("default-window"));
		getDefaultSkin().add("default", defaultWindow);
		
		WindowStyle tintedWindow = new WindowStyle(defaultWindow);
		tintedWindow.titleFontColor = getDefaultSkin().getColor("inverse");
		tintedWindow.background = getDefaultSkin().getDrawable("tinted-window");
		getDefaultSkin().add("tinted", tintedWindow);
		
		ListStyle defaultList = new ListStyle(getDefaultSkin().getFont("window-font"), getDefaultSkin().getColor("inverse"), getDefaultSkin().getColor("default"), getDefaultSkin().getDrawable("selection"));
		getDefaultSkin().add("default", defaultList);
		
		ScrollPaneStyle defaultScrollPane = new ScrollPaneStyle();
		defaultScrollPane.vScroll = getDefaultSkin().getDrawable("default-scroll");
		defaultScrollPane.hScrollKnob = getDefaultSkin().getDrawable("default-round-large");
		defaultScrollPane.hScroll = getDefaultSkin().getDrawable("default-scroll");
		defaultScrollPane.vScrollKnob = getDefaultSkin().getDrawable("default-round-large");
		getDefaultSkin().add("default", defaultScrollPane);
		
		CheckBoxStyle defaultCheckBox = new CheckBoxStyle(getDefaultSkin().getDrawable("check-off"), getDefaultSkin().getDrawable("check-on"), getDefaultSkin().getFont("window-font"), getDefaultSkin().getColor("default"));
		getDefaultSkin().add("default", defaultCheckBox);
		
		CheckBoxStyle expandableCheckBox = new CheckBoxStyle(defaultCheckBox);
		expandableCheckBox.font = getDefaultSkin().getFont("sub-font");
		getDefaultSkin().add("expandable", expandableCheckBox);
		
		SelectBoxStyle defaultSelectBox = new SelectBoxStyle(getDefaultSkin().getFont("default-font"), getDefaultSkin().getColor("default"), getDefaultSkin().getDrawable("default-select"), defaultScrollPane, defaultList);
		getDefaultSkin().add("default", defaultSelectBox);
		
		Gdx.app.debug("Prelaunch Debug Info", "UI Skin has been defined.");
	}
	
	public RoundingResolutionHandler getrRHandler() {
		return rRHandler;
	}
}
