content: /*
   * Copyright 2011 - AndroidQuery.com (tinyeeliu@gmail.com)
   * 
   * Licensed under the Apache License, Version 2.0 (the "License"); you may not
   * use this file except in compliance with the License. You may obtain a copy of
   * the License at
   * 
   * http://www.apache.org/licenses/LICENSE-2.0
   * 
   * Unless required by applicable law or agreed to in writing, software
   * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
   * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
   * License for the specific language governing permissions and limitations under
   * the License.
   */
  
  package com.androidquery.auth;
  
  import java.io.IOException;
  
  import org.apache.http.HttpRequest;
  
  import android.accounts.Account;
  import android.accounts.AccountManager;
  import android.accounts.AccountManagerFuture;
  import android.accounts.AuthenticatorException;
  import android.accounts.OperationCanceledException;
  import android.app.Activity;
  import android.app.AlertDialog;
  import android.content.Context;
  import android.content.DialogInterface;
  import android.content.DialogInterface.OnCancelListener;
  import android.os.AsyncTask;
  import android.os.Bundle;
  import android.preference.PreferenceManager;
  
  import com.androidquery.AQuery;
  import com.androidquery.callback.AbstractAjaxCallback;
  import com.androidquery.callback.AjaxStatus;
  import com.androidquery.util.AQUtility;
  
  /**
   * AQuery internal use only. Handle account, account manager related tasks.
   * 
   */
  
  public class GoogleHandle extends AccountHandle implements DialogInterface.OnClickListener, OnCancelListener{
  
  	private AccountManager am;
  	private Account acc;
  	private String type;
  	private Activity act;
  	private String email;
  	private Account[] accs;
  	private String token;
  	
  	public GoogleHandle(Activity act, String type, String email){
  	
  		if(AQuery.ACTIVE_ACCOUNT.equals(email)){
  			email = getActiveAccount(act);
  		}
  		
  		this.act = act;
  		this.type = type.substring(2);
  		this.email = email;
  		this.am = AccountManager.get(act);
  		
  	}
  	
  	@Override
  	protected void auth(){
  		
  		if(email == null){
  			accountDialog();
  		}else{
  	        Account[] accounts = am.getAccountsByType("com.google");
  	        for(int i = 0; i < accounts.length; i++) {
  	        	Account account = accounts[i];
  	            if(email.equals(account.name)) {
  	            	auth(account);
  	            	return;
  	            }
  	        }
  		}
  	}
  	
  	
  	public boolean reauth(AbstractAjaxCallback<?, ?> cb){
  		
  		am.invalidateAuthToken(acc.type, token);
  		
  		try {
  			token = am.blockingGetAuthToken(acc, type, true);
  			AQUtility.debug("re token", token);
  		} catch (Exception e) {			
  			AQUtility.debug(e);
  			token = null;
  		} 
  		
  		return token != null;
  		
  	}
  	
  	public String getType(){
  		return type;
  	}
  	
  	private void accountDialog() {
  	    
          AlertDialog.Builder builder = new AlertDialog.Builder(act);
          //builder.setTitle("Select a Google account");
          accs = am.getAccountsByType("com.google");
          int size = accs.length;
          
          if(size == 1){
          	auth(accs[0]);
          }else{
          
  	        String[] names = new String[size];
  	        for(int i = 0; i < size; i++) {
  	        	names[i] = accs[i].name;
  	        }
  	        builder.setItems(names, this);
  	        builder.setOnCancelListener(this);
  	        
  	        AlertDialog dialog = builder.create();//.show();
  	        new AQuery(act).show(dialog);
          }
  	}
  	
  	@Override
  	public void onClick(DialogInterface dialog, int which) {
  		
  		Account acc = accs[which];
  		AQUtility.debug("acc", acc.name);
  		
  		setActiveAccount(act, acc.name);		
  		auth(acc);
  	}
  	
  	public static void setActiveAccount(Context context, String account){
  		PreferenceManager.getDefaultSharedPreferences(context).edit().putString(AQuery.ACTIVE_ACCOUNT, account).commit();		
  	}
  
  	public static String getActiveAccount(Context context){
  		return PreferenceManager.getDefaultSharedPreferences(context).getString(AQuery.ACTIVE_ACCOUNT, null);
  	}
  	
  	private void auth(Account account){
  		
  		this.acc = account;
  		
  		Task task = new Task();
  		task.execute();
  	}
  	
  	private class Task extends AsyncTask<String, String, Bundle>{
  	
  		@Override
  		protected Bundle doInBackground(String... params) {
  	
  			Bundle bundle = null;
  			
  			try {
  			    AccountManagerFuture<Bundle> future = am.getAuthToken(acc, type, null, act, null, null);
  				bundle = future.getResult();
  			} catch (OperationCanceledException e) {
  			} catch (AuthenticatorException e) {
  				AQUtility.debug(e);
  			} catch (Exception e) {
  				AQUtility.debug(e);
  			}
  			
  			
  			return bundle;
  		}
  		
  		
  		@Override
  		protected void onPostExecute(Bundle bundle) {
  			
  			if(bundle != null && bundle.containsKey(AccountManager.KEY_AUTHTOKEN)) {
  	          	token = bundle.getString(AccountManager.KEY_AUTHTOKEN);
  	          	//AQUtility.debug("stored auth", token);        	
  	          	success(act);
  			}else{
  	        	failure(act, AjaxStatus.AUTH_ERROR, "rejected");
  	        }
  			
  		}
  	
  		
  	
  	}
  	
  
  	@Override
  	public void onCancel(DialogInterface dialog) {		
  		failure(act, AjaxStatus.AUTH_ERROR, "cancel");
  	}
  	
  	@Override
  	public boolean expired(AbstractAjaxCallback<?, ?> cb, AjaxStatus status) {
  		int code = status.getCode();
  		return code == 401 || code == 403;
  	}
  	
  	@Override
  	public void applyToken(AbstractAjaxCallback<?, ?> cb, HttpRequest request) {
  		
  		//AQUtility.debug("apply token", token);
  		
  		request.addHeader("Authorization", "GoogleLogin auth=" + token);
  	}
  
  	@Override
  	public String getCacheUrl(String url){
  		return url + "#" + token;
  	}
  
  
  	@Override
  	public boolean authenticated() {
  		return token != null;
  	}
  
  	
  	
  }
  