package com.group_finity.mascot.environment;

import java.awt.GraphicsDevice;
import java.awt.GraphicsEnvironment;
import java.awt.MouseInfo;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.Toolkit;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;

/**
 * Original Author: Yuki Yamada of Group Finity (http://www.group-finity.com/Shimeji/)
 * Currently developed by Shimeji-ee Group.
 */

public abstract class Environment {

	protected abstract Area getWorkArea();

	public abstract Area getActiveIE();

	public abstract void moveActiveIE(final Point point);

	public abstract void restoreIE();
    
    public abstract void refreshCache( );

	private static Rectangle screenRect = new Rectangle(new Point(0, 0), Toolkit.getDefaultToolkit().getScreenSize());

	private static Map<String, Rectangle> screenRects = new HashMap<String, Rectangle>();

	static {

		final Thread thread = new Thread() {
			@Override
			public void run() {
				try {
					for (;;) {
						updateScreenRect();
						Thread.sleep(5000);
					}
				} catch (final InterruptedException e) {
				}
			}

		};
		thread.setDaemon(true);
		thread.setPriority(Thread.MIN_PRIORITY);
		thread.start();
	}

	private static void updateScreenRect() {

		Rectangle virtualBounds = new Rectangle();

		Map<String, Rectangle> screenRects = new HashMap<String, Rectangle>();

		final GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
		final GraphicsDevice[] gs = ge.getScreenDevices();

		for (int j = 0; j < gs.length; j++) {
			final GraphicsDevice gd = gs[j];
			screenRects.put(gd.getIDstring(), gd.getDefaultConfiguration().getBounds());
			virtualBounds = virtualBounds.union(gd.getDefaultConfiguration().getBounds());
		}

		Environment.screenRects = screenRects;

		screenRect = virtualBounds;
	}

	private static Rectangle getScreenRect() {
		return screenRect;
	}

	private static Point getCursorPos() {
		return MouseInfo.getPointerInfo().getLocation();
	}

	public ComplexArea complexScreen = new ComplexArea();

	public Area screen = new Area();

	public Location cursor = new Location();

	protected Environment() {
		tick();
	}

	public void tick() {
		this.screen.set(Environment.getScreenRect());
		this.complexScreen.set(screenRects);
		this.cursor.set(Environment.getCursorPos());
	}

	public Area getScreen() {
		return screen;
	}

	public Collection<Area> getScreens() {
		return complexScreen.getAreas();
	}

	public ComplexArea getComplexScreen() {
		return complexScreen;
	}

	public Location getCursor() {
		return cursor;
	}

	public boolean isScreenTopBottom(final Point location) {


		int count = 0;

		for( Area area: getScreens() ) {
			if ( area.getTopBorder().isOn(location)) {
				++count;
			}
			if ( area.getBottomBorder().isOn(location)) {
				++count;
			}
		}


		if ( count==0 ) {
			if ( getWorkArea().getTopBorder().isOn(location) ) {
				return true;
			}
			if ( getWorkArea().getBottomBorder().isOn(location) ) {
				return true;
			}
		}

		return count==1;
	}

	public boolean isScreenLeftRight(final Point location) {


		int count = 0;

		for( Area area: getScreens() ) {
			if ( area.getLeftBorder().isOn(location)) {
				++count;
			}
			if ( area.getRightBorder().isOn(location)) {
				++count;
			}
		}

		if ( count==0 ) {
			if ( getWorkArea().getLeftBorder().isOn(location) ) {
				return true;
			}
			if ( getWorkArea().getRightBorder().isOn(location) ) {
				return true;
			}
		}

		return count==1;
	}

}
