package org.cocos2d.tests;

import org.cocos2d.CCDirector;
import org.cocos2d.actions.base.CCRepeatForever;
import org.cocos2d.actions.interval.CCIntervalAction;
import org.cocos2d.actions.interval.CCMoveBy;
import org.cocos2d.actions.interval.CCSequence;
import org.cocos2d.base_nodes.CCNode;
import org.cocos2d.cocoa.CCGeometry.CCPoint;
import org.cocos2d.cocoa.CCGeometry.CCSize;
import org.cocos2d.events.CCTouchDispatcher;
import org.cocos2d.layers_scenes_transitions_nodes.CCLayer;
import org.cocos2d.layers_scenes_transitions_nodes.CCScene;
import org.cocos2d.lib.Cocos2dActivity;
import org.cocos2d.menu_nodes.CCMenu;
import org.cocos2d.menu_nodes.CCMenuItemImage;
import org.cocos2d.nodes.CCLabel;
import org.cocos2d.nodes.CCParallaxNode;
import org.cocos2d.nodes.CCSprite;
import org.cocos2d.nodes.CCTileMapAtlas;
import org.cocos2d.support.CCPointExtension;
import org.cocos2d.textures.CCTextureAtlas;

import android.os.Bundle;
import android.view.MotionEvent;

public class ParallaxTest extends Cocos2dActivity {
	// private static final String TAG = AtlasSpriteTest.class.getSimpleName();

	private static final boolean DEBUG = true;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);

		// set landscape mode
		CCDirector.sharedDirector().setLandscape(false);

		// show Stats
		CCDirector.sharedDirector().setDisplayStats(true);

		// frames per second
		CCDirector.sharedDirector().setAnimationInterval(1.0f / 60.0f);

		CCScene scene = CCScene.create();
		scene.addChild(nextAction());

		// Make the Scene active
		CCDirector.sharedDirector().runWithScene(scene);
	}

	static int sceneIdx = -1;
	static Class<?> transitions[] = {
		Parallax1.class,
		Parallax2.class,
	};

	static CCLayer nextAction() {
		sceneIdx++;
		sceneIdx = sceneIdx % transitions.length;
		return restartAction();
	}

	static CCLayer backAction() {
		sceneIdx--;
		if(sceneIdx < 0) {
			sceneIdx += transitions.length;
		}
		return restartAction();
	}

	static CCLayer restartAction() {
		try {
			Class<?> c = transitions[sceneIdx];
			return (CCLayer) c.newInstance();
		} catch (Exception e) {
			if (DEBUG) e.printStackTrace();
			return null;
		}
	}

	static abstract class ParallaxDemo extends CCLayer {
		CCTextureAtlas atlas;

		static final int kTagNode = 1;
		static final int kTagGrossini = 2;

		public ParallaxDemo() {
			CCSize s = CCDirector.sharedDirector().getWinSizeInPixels();

			CCLabel label = CCLabel.makeLabel(title(), "DroidSans", 18);
			label.setPosition(s.width / 2, s.height - 30);
			addChild(label, 1);

			CCMenuItemImage item1 = CCMenuItemImage.create("b1.png", "b2.png", this, "backCallback");
			CCMenuItemImage item2 = CCMenuItemImage.create("r1.png", "r2.png", this, "restartCallback");
			CCMenuItemImage item3 = CCMenuItemImage.create("f1.png", "f2.png", this, "nextCallback");

			CCMenu menu = CCMenu.create(item1, item2, item3);
			menu.setPosition(CCPoint.Zero);
			item1.setPosition(s.width / 2 - 100, 30);
			item2.setPosition(s.width / 2, 30);
			item3.setPosition(s.width / 2 + 100, 30);
			addChild(menu, 1);
		}

		public void restartCallback(Object sender) {
			CCScene s = CCScene.create();
			s.addChild(restartAction());
			CCDirector.sharedDirector().replaceScene(s);
		}

		public void nextCallback(Object sender) {
			CCScene s = CCScene.create();
			s.addChild(nextAction());
			CCDirector.sharedDirector().replaceScene(s);
		}

		public void backCallback(Object sender) {
			CCScene s = CCScene.create();
			s.addChild(backAction());
			CCDirector.sharedDirector().replaceScene(s);
		}

		public abstract String title();
	}

	static class Parallax1 extends ParallaxDemo {
		public Parallax1() {
			// Top Layer, a simple image
			CCSprite cocosImage = CCSprite.sprite("powered.png");
			// scale the image (optional)
			cocosImage.setScale(2.5f);
			// change the transform anchor point to 0,0 (optional)
			cocosImage.setAnchorPoint(CCPoint.Zero);

			// Middle layer: a Tile map atlas
			CCTileMapAtlas tilemap = CCTileMapAtlas.tilemap("tiles.png", "levelmap.tga", 16, 16);

			// change the transform anchor to 0,0 (optional)
			tilemap.setAnchorPoint(CCPoint.Zero);

			// Aliased images
			//	tilemap.texture.setAliasTexParameters();

			// background layer: another image
			CCSprite background = CCSprite.sprite("background.png");
			// scale the image (optional)
			background.setScale(1.5f);
			// change the transform anchor point (optional)
			background.setAnchorPoint(CCPoint.Zero);

			// create a void node, a parent node
			CCParallaxNode voidNode = CCParallaxNode.node();

			// NOW add the 3 layers to the 'void' node

			// background image is moved at a ratio of 0.4x, 0.5y
			voidNode.addChild(background, -1, 0.4f, 0.5f, 0, 0);

			// tiles are moved at a ratio of 2.2x, 1.0y
			voidNode.addChild(tilemap, 1, 2.2f, 1.0f, 0, -200);

			// top image is moved at a ratio of 3.0x, 2.5y
			voidNode.addChild(cocosImage, 2, 3.0f, 2.5f, 200, 800);

			// now create some actions that will move the 'void' node
			// and the children of the 'void' node will move at different
			// speed, thus, simulation the 3D environment
			CCIntervalAction goUp = CCMoveBy.action(4, CCPointExtension.ccp(0,-500));
			CCIntervalAction goDown = goUp.reverse();
			CCIntervalAction go = CCMoveBy.action(8, CCPointExtension.ccp(-1000, 0));
			CCIntervalAction goBack = go.reverse();
			CCIntervalAction seq = CCSequence.actions(
					goUp,
					go,
					goDown,
					goBack);
			voidNode.runAction(CCRepeatForever.action(seq));

			addChild(voidNode);
		}

		@Override
		public String title() {
			return "Parallax: parent and 3 children";
		}
	}

	static class Parallax2 extends ParallaxDemo {
		CCPoint previousLocation = new CCPoint();

		public Parallax2() {
			setTouchEnabled(true);

			// Top Layer, a simple image
			CCSprite cocosImage = CCSprite.sprite("powered.png");
			// scale the image (optional)
			cocosImage.setScale(2.5f);
			// change the transform anchor point to 0,0 (optional)
			cocosImage.setAnchorPoint(CCPointExtension.ccp(0,0));

			// Middle layer: a Tile map atlas
			CCTileMapAtlas tilemap = CCTileMapAtlas.tilemap("tiles.png", "levelmap.tga", 16, 16);

			// change the transform anchor to 0,0 (optional)
			tilemap.setAnchorPoint(CCPoint.Zero);

			// Aliased images
			//tilemap.texture.setAliasTexParameters();

			// background layer: another image
			CCSprite background = CCSprite.sprite("background.png");
			// scale the image (optional)
			background.setScale(1.5f);
			// change the transform anchor point (optional)
			background.setAnchorPoint(CCPointExtension.ccp(0,0));

			// create a void node, a parent node
			CCParallaxNode voidNode = CCParallaxNode.node();

			// NOW add the 3 layers to the 'void' node

			// background image is moved at a ratio of 0.4x, 0.5y
			voidNode.addChild(background, -1, 0.4f, 0.5f, 0, 0);

			// tiles are moved at a ratio of 1.0, 1.0y
			voidNode.addChild(tilemap, 1, 1.0f, 1.0f, 0, -200);

			// top image is moved at a ratio of 3.0x, 2.5y
			voidNode.addChild(cocosImage, 2, 3.0f, 2.5f, 200, 1000);
			addChild(voidNode, 0, kTagNode);
		}

		@Override
		public void registerWithTouchDispatcher() {
			System.out.println("ParallaxTest: registerWithTouchDispatcher");
			CCTouchDispatcher.sharedDispatcher().addDelegate(this, 0);
		}

		@Override
		public boolean ccTouchesBegan(MotionEvent event) {
			previousLocation.setPoint(event.getX(), event.getY());
			return CCTouchDispatcher.kEventHandled;
		}

		@Override
		public boolean ccTouchesEnded(MotionEvent event) {
			return CCTouchDispatcher.kEventHandled;
		}

		@Override
		public boolean ccTouchesCancelled(MotionEvent event) {
			return CCTouchDispatcher.kEventIgnored;
		}

		@Override
		public boolean ccTouchesMoved(MotionEvent event) {
			CCPoint diff = new CCPoint();

			CCPoint touchLocation = CCPointExtension.ccp(event.getX(), event.getY());

			CCPoint location = CCDirector.sharedDirector().convertToGL(touchLocation);
			CCPoint prevLocation = CCDirector.sharedDirector().convertToGL(previousLocation);

			diff.x = location.x-prevLocation.x;
			diff.y = location.y-prevLocation.y;

			CCNode node = getChildByTag(kTagNode);
			node.setPosition(CCPointExtension.ccpAdd(node.getPosition(), diff));

			previousLocation = touchLocation;

			return CCTouchDispatcher.kEventHandled;
		}

		@Override
		public String title() {
			return "Parallax: drag screen";
		}
	}
}
