package org.osmdroid.tileprovider.util;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;

import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.DefaultHttpClient;
import org.osmdroid.tileprovider.constants.OpenStreetMapTileProviderConstants;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import android.content.Context;
import android.content.SharedPreferences;
import android.content.SharedPreferences.Editor;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.preference.PreferenceManager;
import android.provider.Settings;

/**
 * Utility class for implementing Cloudmade authorization. See
 * http://developers.cloudmade.com/projects/show/auth
 *
 * The CloudMade token is persisted because it doesn't change:
 * http://support.cloudmade.com/answers/api-keys-and-authentication
 * "you will always get the same token for the unique user id"
 *
 */
public class CloudmadeUtil implements OpenStreetMapTileProviderConstants {

	private static final Logger logger = LoggerFactory.getLogger(CloudmadeUtil.class);

	/** the meta data key in the manifest */
	private static final String CLOUDMADE_KEY = "CLOUDMADE_KEY";

	/** the key for the id preference */
	private static final String CLOUDMADE_ID = "CLOUDMADE_ID";

	/** the key for the token preference */
	private static final String CLOUDMADE_TOKEN = "CLOUDMADE_TOKEN";

	private static String mAndroidId = Settings.Secure.ANDROID_ID; // will get real id later

	/** the key retrieved from the manifest */
	private static String mKey = "";

	/** the token */
	private static String mToken = "";

	private static Editor mPreferenceEditor;

	/**
	 * Retrieve the key from the manifest and store it for later use.
	 */
	public static void retrieveCloudmadeKey(final Context pContext) {

		mAndroidId = Settings.Secure.getString(pContext.getContentResolver(), Settings.Secure.ANDROID_ID);

		// get the key from the manifest
		final PackageManager pm = pContext.getPackageManager();
		try {
			final ApplicationInfo info = pm.getApplicationInfo(pContext.getPackageName(),
					PackageManager.GET_META_DATA);
			if (info.metaData != null) {
				final String key = info.metaData.getString(CLOUDMADE_KEY);
				if (key != null) {
					if (DEBUGMODE) {
						logger.debug("Cloudmade key: " + key);
					}
					mKey = key.trim();
				}
			}
		} catch (final NameNotFoundException e) {
			logger.info("Cloudmade key not found in manifest", e);
		}

		// if the id hasn't changed then set the token to the previous token
		final SharedPreferences pref = PreferenceManager.getDefaultSharedPreferences(pContext);
		mPreferenceEditor = pref.edit();
		final String id = pref.getString(CLOUDMADE_ID, "");
		if (id.equals(mAndroidId)) {
			mToken = pref.getString(CLOUDMADE_TOKEN, "");
		} else {
			mPreferenceEditor.putString(CLOUDMADE_ID, mAndroidId);
			mPreferenceEditor.commit();
		}

	}

	/**
	 * Get the key that was previously retrieved from the manifest.
	 *
	 * @return the key, or empty string if not found
	 */
	public static String getCloudmadeKey() {
		return mKey;
	}

	/**
	 * Get the token from the Cloudmade server.
	 *
	 * @return the token returned from the server, or null if not found
	 */
	public static String getCloudmadeToken() {

		if (mToken.length() == 0) {
			synchronized (mToken) {
				// check again because it may have been set while we were blocking
				if (mToken.length() == 0) {
					final String url = "http://auth.cloudmade.com/token/" + mKey + "?userid=" + mAndroidId;
					final HttpClient httpClient = new DefaultHttpClient();
					final HttpPost httpPost = new HttpPost(url);
					try {
						final HttpResponse response = httpClient.execute(httpPost);
						if (DEBUGMODE) {
							logger.debug("Response from Cloudmade auth: " + response.getStatusLine());
						}
						if (response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
							final BufferedReader br =
								new BufferedReader(
										new InputStreamReader(response.getEntity().getContent()),
										StreamUtils.IO_BUFFER_SIZE);
							final String line = br.readLine();
							if (DEBUGMODE) {
								logger.debug("First line from Cloudmade auth: " + line);
							}
							mToken = line.trim();
							if (mToken.length() > 0) {
								mPreferenceEditor.putString(CLOUDMADE_TOKEN, mToken);
								mPreferenceEditor.commit();
							} else {
								logger.error("No authorization token received from Cloudmade");
							}
						}
					} catch (final IOException e) {
						logger.error("No authorization token received from Cloudmade: " + e);
					}
				}
			}
		}

		return mToken;
	};
}

@@ -3115,16 +3115,146 @@
 , %22%22);%0D%0A
+%09%09%09// if we've got a token we don't need the editor any more%0D%0A%09%09%09if (mToken.length() %3E 0) %7B%0D%0A%09%09%09%09mPreferenceEditor = null;%0D%0A%09%09%09%7D%0D%0A
 %09%09%7D else
@@ -4857,24 +4857,105 @@
 .commit();%0D%0A
+%09%09%09%09%09%09%09%09// we don't need the editor any more%0D%0A%09%09%09%09%09%09%09%09mPreferenceEditor = null;%0D%0A
 %09%09%09%09%09%09%09%7D els

Remove reference when no longer needed