package org.osmdroid.views.overlay.infowindow;

import java.util.ArrayList;

import org.osmdroid.api.IMapView;
import org.osmdroid.config.Configuration;
import org.osmdroid.util.GeoPoint;
import org.osmdroid.views.MapView;

import android.content.Context;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

/** {@link org.osmdroid.views.overlay.infowindow.InfoWindow} is a (pop-up-) View that can
 * be displayed on an {@link org.osmdroid.views.MapView}, associated to a
 * {@link org.osmdroid.api.IGeoPoint}.
 *
 * Typical usage: cartoon-like bubbles displayed when clicking an overlay item (i.e. a
 * {@link org.osmdroid.views.overlay.Marker}).
 * It mimics the InfoWindow class of Google Maps JavaScript API V3. 
 * Main differences are: 
 * <ul>
 * <li>Structure and content of the view is let to the responsibility of the caller. </li>
 * <li>The same InfoWindow can be associated to many items. </li>
 * </ul>
 * 
 * This is an abstract class. 
 *
 * <img alt="Class diagram around Marker class" width="686" height="413" src='./doc-files/marker-infowindow-classes.png' />
 *
 * @see MarkerInfoWindow
 * @author M.Kergall
 */
public abstract class InfoWindow {

	protected View mView;
	protected boolean mIsVisible;
	protected MapView mMapView;
	
	/**
	 * @param layoutResId	the id of the view resource. 
	 * @param mapView	the mapview on which is hooked the view
	 */
	public InfoWindow(int layoutResId, MapView mapView) {
		mMapView = mapView;
		mIsVisible = false;
		ViewGroup parent=(ViewGroup)mapView.getParent();
		Context context = mapView.getContext();
		LayoutInflater inflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
		mView = inflater.inflate(layoutResId, parent, false);
		mView.setTag(this);
	}

	/**
	 * may return null if the info window hasn't been attached yet
	 * @return
     */
	public MapView getMapView(){
		return mMapView;
	}

	/**
	 * Returns the Android view. This allows to set its content. 
	 * @return the Android view
	 */
	public View getView() {
		return(mView);
	}

	/**
	 * open the InfoWindow at the specified GeoPosition + offset. 
	 * If it was already opened, close it before reopening. 
	 * @param object the graphical object on which is hooked the view
	 * @param position to place the window on the map
	 * @param offsetX (&offsetY) the offset of the view to the position, in pixels. 
	 * This allows to offset the view from the object position. 
	 */
	public void open(Object object, GeoPoint position, int offsetX, int offsetY) {
		close(); //if it was already opened
		onOpen(object);
		MapView.LayoutParams lp = new MapView.LayoutParams(
				MapView.LayoutParams.WRAP_CONTENT,
				MapView.LayoutParams.WRAP_CONTENT,
				position, MapView.LayoutParams.BOTTOM_CENTER, 
				offsetX, offsetY);
		if (mMapView!=null && mView!=null) {
			mMapView.addView(mView, lp);
			mIsVisible = true;
		} else {
			Log.w(IMapView.LOGTAG, "Error trapped, InfoWindow.open mMapView: " + (mMapView==null ? "null" : "ok") + " mView: "  + (mView==null ? "null" : "ok"));
		}
	}
    
	public void close() {
		if (mIsVisible) {
			mIsVisible = false;
			((ViewGroup)mView.getParent()).removeView(mView);
			onClose();
		}
	}

	/**
	 * this destroys the window and all references to views
	 */
	public void onDetach(){
		close();
		if (mView!=null)
			mView.setTag(null);
		mView=null;
		mMapView=null;
		if (Configuration.getInstance().isDebugMode())
			Log.d(IMapView.LOGTAG, "Marked detached");
	}
	
	public boolean isOpen(){
		return mIsVisible;
	}
	
	/** close all InfoWindows currently opened on this MapView */
	static public void closeAllInfoWindowsOn(MapView mapView){
		ArrayList<InfoWindow> opened = getOpenedInfoWindowsOn(mapView);
		for (InfoWindow infoWindow:opened){
			infoWindow.close();
		}
	}
	
	/** return all InfoWindows currently opened on this MapView */
	static public ArrayList<InfoWindow> getOpenedInfoWindowsOn(MapView mapView){
		int count = mapView.getChildCount();
		ArrayList<InfoWindow> opened = new ArrayList<InfoWindow>(count);
		for (int i = 0; i < count; i++) {
			final View child = mapView.getChildAt(i);
			Object tag = child.getTag();
			if (tag != null && tag instanceof InfoWindow){
				InfoWindow infoWindow = (InfoWindow)tag;
				opened.add(infoWindow);
			}
		}
		return opened;
	}
	
	//Abstract methods to implement in sub-classes:
	public abstract void onOpen(Object item);
	public abstract void onClose();
	
}

@@ -1311,17 +1311,16 @@
 apView;%0A
-%09
 %0A%09/**%0A%09 
@@ -1807,24 +1807,217 @@
 (this);%0A%09%7D%0A%0A
+%09public InfoWindow(View v, MapView mapView) %7B%0A%09%09mMapView = mapView;%0A%09%09mIsVisible = false;%0A%09%09mView = v;%0A%09%09mView.setTag(this);%0A%09%09Log.w(IMapView.LOGTAG, %22foobar Infowwindow new constructor%22);%0A%09%7D%0A%0A
 %09/**%0A%09 * may

add constructor InfoWindow(View, Mapview) (#695)