/*
 * Copyright (C) 2009 Google Inc.
 *
 * 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.codeim.youliao;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
// import java.io.IOException;
// import java.io.InputStream;
// import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.List;
import java.util.Observable;
import java.util.Observer;
// import java.util.regex.Matcher;
// import java.util.regex.Pattern;

import android.app.AlertDialog;
import android.app.Dialog;
import android.app.NotificationManager;
import android.app.ProgressDialog;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.IntentFilter;
// import android.content.SharedPreferences;
import android.content.res.Resources;
import android.graphics.Bitmap;
// import android.graphics.BitmapFactory;
import android.graphics.Color;
import android.media.MediaPlayer;
import android.media.MediaPlayer.OnCompletionListener;
import android.media.MediaPlayer.OnErrorListener;
import android.media.MediaRecorder;
import android.os.AsyncTask;
import android.os.Build;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.text.ClipboardManager;
import android.text.TextUtils;
import android.util.Log;
import android.view.ContextMenu;
import android.view.ContextMenu.ContextMenuInfo;
import android.view.Gravity;
import android.view.MenuItem;
import android.view.View;
import android.view.MotionEvent;
import android.view.View.OnClickListener;
// import android.view.View.OnClickListener;
import android.view.View.OnTouchListener;
import android.view.Window;
import android.view.WindowManager;
import android.widget.Button;
import android.widget.FrameLayout;
// import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.ListView;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.ProgressBar;
import android.widget.TextView;
import android.widget.Toast;

// import com.codeim.youliao.app.ImageCache;
import com.baidu.location.BDLocation;
import com.baidu.location.LocationClient;
import com.baidu.location.LocationClientOption;
import com.codeim.youliao.app.LazyImageLoader.ImageLoaderCallback;
import com.codeim.youliao.app.Preferences;
import com.codeim.youliao.data.Tweet;
import com.codeim.youliao.fanfou.Paging;
import com.codeim.youliao.fanfou.Status;
import com.codeim.youliao.fanfou.Weibo;
import com.codeim.youliao.http.HttpClient;
import com.codeim.youliao.http.HttpException;
import com.codeim.youliao.http.Response;
import com.codeim.youliao.location.LocationUtils;
// import com.codeim.youliao.http.Response;
import com.codeim.youliao.record.Recorder;
import com.codeim.youliao.record.RecorderService;
import com.codeim.youliao.record.RemainingTimeCalculator;
import com.codeim.youliao.task.GenericTask;
import com.codeim.youliao.task.TaskAdapter;
import com.codeim.youliao.task.TaskListener;
import com.codeim.youliao.task.TaskManager;
import com.codeim.youliao.task.TaskParams;
import com.codeim.youliao.task.TaskResult;
// import com.codeim.youliao.task.TweetCommonTask;
import com.codeim.youliao.ui.base.BaseActivity;
import com.codeim.youliao.ui.module.CommentArrayAdapter;
import com.codeim.youliao.ui.module.Feedback;
import com.codeim.youliao.ui.module.FeedbackFactory;
import com.codeim.youliao.ui.module.FeedbackFactory.FeedbackType;
import com.codeim.youliao.ui.module.NavBar;
import com.codeim.youliao.ui.module.SimpleFeedback;
import com.codeim.youliao.util.DateTimeHelper;
import com.codeim.youliao.util.TextHelper;
// import com.markupartist.android.widget.PullToRefreshListView;
// import com.markupartist.android.widget.PullToRefreshListView.OnRefreshListener;
import com.markupartist.android.widget.MyListView;
import com.markupartist.android.widget.MyListView.OnRefreshListener;
import com.codeim.youliao.R;

public class StatusWithCommentActivity extends BaseActivity implements Recorder.OnStateChangedListener, 
        OnCompletionListener, OnErrorListener {

	private static final String TAG = "StatusWithCommentActivity";
	public static final String DOWNLOAD_DEFAULT_DIR = "/youliao/download";
	private static final String SIS_RUNNING_KEY = "running";
	// private static final String PREFS_NAME = "com.codeim.youliao";
	protected static final int STATE_ALL = 0;
	private static final String EXTRA_TWEET = "tweet";
	private static final String LAUNCH_ACTION = "com.codeim.youliao.STATUS";
	private static final String AUDIO_3GPP = "audio/3gpp";
    private static final String AUDIO_AMR = "audio/amr";
    private static final String AUDIO_ANY = "audio/*";
    private static final String ANY_ANY = "*/*";
    private static final String FILE_EXTENSION_AMR = ".amr";
    private static final String FILE_EXTENSION_3GPP = ".3gpp";
	public static final int BITRATE_AMR = 2 * 1024 * 8; // bits/sec
    public static final int BITRATE_3GPP = 20 * 1024 * 8; // bits/sec
    // private static final int SEEK_BAR_MAX = 10000;
	private static int MAX_TIME = 60;    
	private static int MIX_TIME = 2;  
	static final private int CONTEXT_REFRESH_ID = 0x0001;
	static final private int CONTEXT_CLIPBOARD_ID = 0x0002;
	static final private int CONTEXT_DELETE_ID = 0x0003;
    private static final long REFRESH_THRESHOLD = 5 * 60 * 1000;  // Refresh data at startup if last refresh was this long ago or greater.

	private NavBar mNavBar;
	private Feedback mFeedback;
	
	private Recorder mRecorder;
	private RecorderReceiver mReceiver;
	private RemainingTimeCalculator mRemainingTimeCalculator;
	private String mTimerFormat;
	private boolean mSampleInterrupted = false;
	private String mErrorUiMessage = null; // Some error messages are displayed in the UI, not a dialog. This happens when a recording is interrupted for some reason.
	private long mMaxFileSize = -1; // can be specified in the intent
	private String mRequestedType = AUDIO_ANY;
	private boolean mShowFinishButton = false;
	// private boolean mCanRequestChanged = false;
	private BroadcastReceiver mSDCardMountEventReceiver = null;
	
	private Dialog mVolumeDialog;  // 按住录音时，音量显示对话框
	private ImageView volume_img;  // 显示不同音量的图片
	private TextView record_time_tv;  // 录音时间
	
	private boolean mStopUiUpdate;
	
	// View
	private ImageView profileImage;  // 头像
	private TextView screenName;  // 第一行：用户名
	private TextView distanceAndCreatedAt;  // 第一行：距离与时间
	private TextView lastStatus;  // 第二行：标题
	private FrameLayout playBtn;  // 第三行：播放按钮
	private FrameLayout downloadingBtn;  // 第三行：正在下载按钮
	private FrameLayout stopBtn;  // 第三行：停止按钮
	private ProgressBar playProgressBar;  // 第三行：播放进度
	private TextView totalTimeText;  // 第三行：语音时间长度
	private TextView commentCountText;  // 第三行：评论个数
	
	private Button mRecordButton;  //评论按钮
	
	private SearchLocationObserver mSearchLocationObserver = new SearchLocationObserver();
	private LocationClient mLocClient;
	
	// protected PullToRefreshListView mCommentList;  // 评论列表
	protected MyListView mCommentList;  // 评论列表
	private ArrayList<com.codeim.youliao.data.Tweet> allCommentList;  // 评论
	protected CommentArrayAdapter mCommentAdapter;
	protected String mNameType = "comment_";
	
	protected View mListHeader;
    protected View mListFooter;
	protected TextView loadMoreBtn;
    protected ProgressBar loadMoreGIF;
    protected TextView loadMoreBtnTop;
    protected ProgressBar loadMoreGIFTop;
	
	private ProgressDialog mSendDialog;
	
	private HttpClient mClient;
	
	private File mDownloadDir = null;
	private boolean mPlayBtnSwitch = false;
	private MediaPlayer mMediaPlayer = null;
	private String mFilePath;

	private Tweet tweet = null;
	// private Tweet relativeTweet = null; // if exists
	
	protected static int lastPosition = 0;
	
	// Task
	protected TaskManager taskManager = new TaskManager();
	// private GenericTask mRelativeTweetTask;
	private GenericTask mGetTopicAudioTask;
	// private GenericTask mStatusTask;
	private GenericTask mSendCommentTask;
	private GenericTask mGetCommentTask;
	private GenericTask mGetConversationTask;
	private GenericTask mGetMoreCommentTask;
	private GenericTask mGetMoreConversationTask;
	private int currentPage = 1;
	
	private TaskListener mSendCommentTaskListener = new TaskAdapter() {
		@Override
		public void onPreExecute(GenericTask task) {
			onSendBegin();
		}

		@Override
		public void onPostExecute(GenericTask task, TaskResult result) {
			//endTime = System.currentTimeMillis();
			//Log.d("LDS", "Sended a status in " + (endTime - startTime));
			if (result == TaskResult.AUTH_ERROR) {
				logout();
			} else if (result == TaskResult.OK) {
				onSendSuccess();
			} else if (result == TaskResult.IO_ERROR) {
				onSendFailure();
			}
		}

		@Override
		public String getName() {
			// TODO Auto-generated method stub
			return "SendCommentTask";
		}
	};
	
	private TaskListener mGetCommentTaskListener = new TaskAdapter() {
		@Override
		public String getName() {
			// TODO Auto-generated method stub
			return "GetCommentTask";
		}
		
		@Override
        public void onPostExecute(GenericTask task, TaskResult result) {
		    // 刷新按钮停止旋转
            loadMoreGIF.setVisibility(View.GONE);
			if (task == mGetCommentTask) {
			    mCommentList.onRefreshComplete();
			} else {
			    mCommentList.onMoreRefreshComplete();
			}
            
			if (result == TaskResult.AUTH_ERROR) {
                mFeedback.failed("登录信息出错");
                logout();
            } else if (result == TaskResult.OK) {
            	drawList();
            } else if (result == TaskResult.IO_ERROR) {
                // FIXME: bad smell
                if (task == mGetCommentTask) {
                    mFeedback.failed(((GetCommentTask) task).getErrorMsg());
                } else if (task == mGetMoreCommentTask) {
                    mFeedback.failed(((GetMoreCommentTask) task).getErrorMsg());
                }
            } else {
                // do nothing
            }
		}
		
		@Override
        public void onPreExecute(GenericTask task) {
			// mCommentList.prepareForRefresh();
		}
		
		@Override
        public void onProgressUpdate(GenericTask task, Object param) {
			Log.d(TAG, "onProgressUpdate");
			drawList();
		}
	};
	
	private TaskListener mGetConversationTaskListener = new TaskAdapter() {
		@Override
		public String getName() {
			// TODO Auto-generated method stub
			return "GetConversationTask";
		}
		
		@Override
        public void onPostExecute(GenericTask task, TaskResult result) {
			// 刷新按钮停止旋转
            loadMoreGIF.setVisibility(View.GONE);
            if (task == mGetConversationTask) {
			    mCommentList.onRefreshComplete();
			} else {
			    mCommentList.onMoreRefreshComplete();
			}
			
			if (result == TaskResult.AUTH_ERROR) {
                mFeedback.failed("登录信息出错");
                logout();
            } else if (result == TaskResult.OK) {
            	drawList();
                if (task == mGetConversationTask) {
                    goTop();
                }
            } else if (result == TaskResult.IO_ERROR) {
                // FIXME: bad smell
                if (task == mGetConversationTask) {
                    mFeedback.failed(((GetConversationTask) task).getErrorMsg());
                } else if (task == mGetMoreConversationTask) {
                    mFeedback.failed(((GetMoreConversationTask) task).getErrorMsg());
                }
            } else {
                // do nothing
            }
		}
		
		@Override
        public void onPreExecute(GenericTask task) {
			// mCommentList.prepareForRefresh();
		}
		
		@Override
        public void onProgressUpdate(GenericTask task, Object param) {
			Log.d(TAG, "onProgressUpdate");
			drawList();
		}
	};

	public static Intent createIntent(Tweet tweet) {
		Intent intent = new Intent(LAUNCH_ACTION);
		intent.putExtra(EXTRA_TWEET, tweet);
		return intent;
	}
	
	private ImageLoaderCallback callback = new ImageLoaderCallback() {
		@Override
		public void refresh(String url, Bitmap bitmap) {
			profileImage.setImageBitmap(bitmap);
		} 
	};
	
	private final Handler mHandler = new Handler();

    private Runnable mUpdateTimer = new Runnable() {
        public void run() {
            if (!mStopUiUpdate) {
                updateTimerView();
            }
        }
    };

    private Runnable mUpdateVUMetur = new Runnable() {
        @Override
        public void run() {
            if (!mStopUiUpdate) {
                updateVUMeterView();
            }
        }
    };

	@Override
	protected boolean _onCreate(Bundle savedInstanceState) {
		Log.d(TAG, "_onCreate.");
		if (super._onCreate(savedInstanceState)) {
		    initInternalState(getIntent());

			// Intent & Action & Extras
			Intent intent = getIntent();
			// String action = intent.getAction();
			Bundle extras = intent.getExtras();
			// Must has extras
			if (null == extras) {
				Log.e(TAG, this.getClass().getName() + " must has extras.");
				finish();
				return false;
			}
			this.tweet = extras.getParcelable(EXTRA_TWEET);  // Set view with intent data
			// Log.d(TAG, "tweet attachmentUrl: " + tweet.attachmentUrl);
			// Log.d(TAG, "tweet screenName: " + tweet.screenName);
			// Log.d(TAG, "tweet text: " + tweet.text);
			// Log.d(TAG, "tweet: " + tweet.toString());

			setContentView(R.layout.status_with_comment);
			mFeedback = FeedbackFactory.create(this, FeedbackType.PROGRESS);
			mRecorder = new Recorder(this);
            mRecorder.setOnStateChangedListener(this);
            mReceiver = new RecorderReceiver();
            mRemainingTimeCalculator = new RemainingTimeCalculator();
            
            mNavBar = new NavBar(NavBar.HEADER_STYLE_BACK, this);
            mNavBar.setHeaderTitle("友聊");
			
			registerExternalStorageListener();
			mTimerFormat = getResources().getString(R.string.timer_format);
			
			mClient = getApi().getHttpClient();
			mPlayBtnSwitch = false;

			findView();
			draw();
			
			File downloadDir = new File(Environment.getExternalStorageDirectory().getAbsolutePath() + DOWNLOAD_DEFAULT_DIR);
            if (!downloadDir.exists()) {
                downloadDir.mkdirs();
            }
            mDownloadDir = downloadDir;
			
			mLocClient = ((TwitterApplication)getApplication()).mLocationClient;
			
			// mCommentList = (PullToRefreshListView) findViewById(R.id.comment_list);
			mCommentList = (MyListView) findViewById(R.id.comment_list);
			setupListHeader(true);
			mCommentAdapter = new CommentArrayAdapter(this);
			mCommentList.setAdapter(mCommentAdapter);
			allCommentList = new ArrayList<com.codeim.youliao.data.Tweet>();
			registerOnClickListener(getCommentList());
			
			mPreferences.getInt(Preferences.TWITTER_ACTIVITY_STATE_KEY, STATE_ALL);
			boolean shouldRetrieve = false;
            long lastRefreshTime = mPreferences.getLong(mNameType + Preferences.LAST_TWEET_REFRESH_KEY, 0);  // FIXME：该子类页面全部使用了这个统一的计时器，导致进入Mention等分页面后经常不会自动刷新
            long nowTime = DateTimeHelper.getNowTime();
            long diff = nowTime - lastRefreshTime;
            Log.d(TAG, "Last refresh was " + diff + " ms ago.");
            if (diff > REFRESH_THRESHOLD) {
                shouldRetrieve = true;
            } else if (isTrue(savedInstanceState, SIS_RUNNING_KEY)) {
                // Check to see if it was running a send or retrieve task.
                // It makes no sense to resend the send request (don't want
                // dupes)
                // so we instead retrieve (refresh) to see if the message has
                // posted.
                Log.d(TAG, "Was last running a retrieve or send task. Let's refresh.");
                shouldRetrieve = true;
            }
            if (shouldRetrieve) {
			    if (tweet.inReplyToStatusId != null && tweet.inReplyToStatusId.length() != 0) {
		            doGetComment();  // 这是一个回答，获取对这个回答的回答
		        } else {
		            doGetConversation();  // 这是一个提问，获取与这个提问相关的对话
		        }
            }
			
			String playLink = tweet.attachmentUrl;
			String fileName = playLink.substring(playLink.lastIndexOf("/") + 1);
			File downloadFile = new File(mDownloadDir.getAbsolutePath() + "/" + fileName);
			if (downloadFile.exists()) {
			    mPlayBtnSwitch = true;
				mFilePath = downloadFile.getAbsolutePath();
			} else {
			    doGetTopicAudio(fileName, playLink);
			}

            goTop(); // skip the header

			return true;
		} else {
			return false;
		}
	}
	
	private void initInternalState(Intent i) {
        mRequestedType = AUDIO_ANY;
        mShowFinishButton = false;
        if (i != null) {
		    Log.d(TAG, "i is not null");
            String s = i.getType();
            if (AUDIO_AMR.equals(s) || AUDIO_3GPP.equals(s) || AUDIO_ANY.equals(s) || ANY_ANY.equals(s)) {
                mRequestedType = s;
                mShowFinishButton = true;
            } else if (s != null) {
                // we only support amr and 3gpp formats right now
                setResult(RESULT_CANCELED);
                finish();
                return;
            }

            final String EXTRA_MAX_BYTES = android.provider.MediaStore.Audio.Media.EXTRA_MAX_BYTES;
            mMaxFileSize = i.getLongExtra(EXTRA_MAX_BYTES, -1);
        }
		
		mRequestedType = AUDIO_3GPP;
    }
	
	/**
     * 绑定listView底部 - 载入更多 NOTE: 必须在listView#setAdapter之前调用
     */
    protected void setupListHeader(boolean addFooter) {
        // Add Header to ListView
        // mListHeader = View.inflate(this, R.layout.listview_header, null);
        // mTweetList.addHeaderView(mListHeader, null, true);
    	mCommentList.setOnRefreshListener(new OnRefreshListener(){
    		@Override
    		public void onRefresh(){
			    if (tweet.inReplyToStatusId != null && tweet.inReplyToStatusId.length() != 0) {
		            doGetComment();  // 这是一个回答，获取对这个回答的回答
		        } else {
		            doGetConversation();  // 这是一个提问，获取与这个提问相关的对话
		        }
    		}
    	});

        // Add Footer to ListView
        mListFooter = View.inflate(this, R.layout.listview_footer, null);
        mCommentList.addFooterView(mListFooter, null, true);
        
        // Find View
        loadMoreBtn = (TextView) findViewById(R.id.ask_for_more);
        loadMoreGIF = (ProgressBar) findViewById(R.id.rectangleProgressBar);
        loadMoreBtnTop = (TextView) findViewById(R.id.ask_for_more_header);
        loadMoreGIFTop = (ProgressBar) findViewById(R.id.rectangleProgressBar_header);
    }
	
    protected void specialItemClicked(int position) {
        // 注意 mTweetAdapter.getCount 和 mTweetList.getCount的区别
        // 前者仅包含数据的数量（不包括foot和head），后者包含foot和head
        // 因此在同时存在foot和head的情况下，list.count = adapter.count + 2
		/*
        if (position == 0) {
            // 第一个Item(header)
            loadMoreGIFTop.setVisibility(View.VISIBLE);
            if (tweet.inReplyToStatusId.equals("null")) {
		    	doGetConversation();
		    } else {
		    	doGetComment();
		    }
        } else if (position == mCommentList.getCount() - 1) {
            // 最后一个Item(footer)
            loadMoreGIF.setVisibility(View.VISIBLE);
            if (tweet.inReplyToStatusId.equals("null")) {
		    	doGetMoreConversation();
		    } else {
		    	doGetMoreComment();
		    }
        }
		*/
		if (position == mCommentList.getCount() - 1) {
            // 最后一个Item(footer)
            loadMoreGIF.setVisibility(View.VISIBLE);
			if (tweet.inReplyToStatusId != null && tweet.inReplyToStatusId.length() != 0) {
		        doGetMoreComment();  // 这是一个回答，获取对这个回答的回答
		    } else {
		        doGetMoreConversation();  // 这是一个提问，获取与这个提问相关的对话
		    }
        }
    }
	
	protected ListView getCommentList() {
        return mCommentList;
    }
	
	protected void registerOnClickListener(ListView listView) {

		listView.setOnItemClickListener(new OnItemClickListener() {
			@Override
			public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
			    Log.d(TAG, "position = " + position);
				Tweet item = getContextItemTweet(position);
                
				if (item == null) {
					Log.w(TAG, "Selected item not available.");
					specialItemClicked(position);
				} else {
	
				}
			}
		});
	}
	
	protected Tweet getContextItemTweet(int position) {
        position = position - 1;
        // 因为List加了Header和footer，所以要跳过第一个以及忽略最后一个
        if (position >= 0 && position < mCommentAdapter.getCount()) {
        	Tweet item = (Tweet) mCommentAdapter.getItem(position);
            if (item == null) {
                return null;
            } else {
                return item;
            }
        } else {
            return null;
        }
    }

	private void findView() {
		profileImage = (ImageView) findViewById(R.id.profile_image);
		screenName = (TextView) findViewById(R.id.screen_name);
		distanceAndCreatedAt = (TextView) findViewById(R.id.tweet_meta_text);
		lastStatus = (TextView) findViewById(R.id.tweet_text);
		playBtn = (FrameLayout) findViewById(R.id.play_btn_layout);
		downloadingBtn = (FrameLayout) findViewById(R.id.downloading_btn_layout);
		stopBtn = (FrameLayout) findViewById(R.id.stop_btn_layout);
		playProgressBar = (ProgressBar) findViewById(R.id.play_progressbar);
		totalTimeText = (TextView) findViewById(R.id.play_total_time_text);   // 2013.9.24
		commentCountText = (TextView) findViewById(R.id.comment_count_text);  // 2013.9.24
		mRecordButton = (Button) findViewById(R.id.record_button);
		
		playBtn.setOnClickListener(new OnClickListener() {
		    @Override
			public void onClick(View v) {
		    	if (mPlayBtnSwitch) {
		    		mCommentAdapter.stopPlay();
		    		startPlay();
		    	} else {
		    		return;
		    	}
		    	
			}
		});
		
		stopBtn.setOnClickListener(new OnClickListener() {
			@Override
			public void onClick(View v) {
				stopPlay();
			}
		});
		
		mRecordButton.setOnTouchListener(new OnTouchListener() {
		    @Override
			public boolean onTouch(View v, MotionEvent event) {
			    switch (event.getAction()) {
				    case MotionEvent.ACTION_DOWN:
					    showOverwriteConfirmDialogIfConflicts();
					    break;
					case MotionEvent.ACTION_UP:
					    mRecorder.stop();
					    doSendComment();
					    break;
					case MotionEvent.ACTION_CANCEL:
						mRecorder.stop();
				}
				return false;
			}
		});
	}
	
	public void startPlay() {
		mMediaPlayer = new MediaPlayer();
		try {
            mMediaPlayer.setDataSource(mFilePath);
            mMediaPlayer.setOnCompletionListener(this);
            mMediaPlayer.setOnErrorListener(this);
            mMediaPlayer.prepare();
            mMediaPlayer.seekTo(0);
            mMediaPlayer.start();
        } catch (IllegalArgumentException e) {
            mMediaPlayer = null;
            return;
        } catch (IOException e) {
            mMediaPlayer = null;
            return;
        }
		playBtn.setVisibility(View.GONE);
		stopBtn.setVisibility(View.VISIBLE);
	}
	
	public void stopPlay() {
		if (mMediaPlayer == null) // we were not in playback
            return;
        //Log.d(TAG, "stopPlay");
		mMediaPlayer.stop();
		mMediaPlayer.release();
		mMediaPlayer = null;
		playBtn.setVisibility(View.VISIBLE);
		stopBtn.setVisibility(View.GONE);
	}
	
	@Override
	public boolean onError(MediaPlayer mp, int what, int extra) {
        stopPlay();
        return true;
    }

	@Override
    public void onCompletion(MediaPlayer mp) {
        stopPlay();
    }

	@Override
	protected void onRestart() {
		super.onRestart();
		Log.d(TAG, "onRestart.");
	}
	
	@Override
    protected void onResume() {
        Log.d(TAG, "onResume.");
        if (lastPosition != 0) {
            mCommentList.setSelection(lastPosition);
        }

        if (!mRecorder.syncStateWithService()) {
            mRecorder.reset();
        }

        if (mRecorder.state() == Recorder.RECORDING_STATE) {
            String preExtension = AUDIO_AMR.equals(mRequestedType) ? FILE_EXTENSION_AMR : FILE_EXTENSION_3GPP;
            if (!mRecorder.sampleFile().getName().endsWith(preExtension)) {
                // the extension is changed need to stop current recording
                mRecorder.reset();
            } else {
                if (AUDIO_AMR.equals(mRequestedType)) {
                    mRemainingTimeCalculator.setBitRate(BITRATE_AMR);
                } else if (AUDIO_3GPP.equals(mRequestedType)) {
                    mRemainingTimeCalculator.setBitRate(BITRATE_3GPP);
                }
            }
        } else {
            File file = mRecorder.sampleFile();
            if (file != null && !file.exists()) {
                mRecorder.reset();
            }
        }

        IntentFilter filter = new IntentFilter();
        filter.addAction(RecorderService.RECORDER_SERVICE_BROADCAST_NAME);
        registerReceiver(mReceiver, filter);

        mStopUiUpdate = false;
        updateUi();

        if (RecorderService.isRecording()) {
            Intent intent = new Intent(this, RecorderService.class);
            intent.putExtra(RecorderService.ACTION_NAME, RecorderService.ACTION_DISABLE_MONITOR_REMAIN_TIME);
            startService(intent);
        }
		super.onResume();
		checkIsLogedIn();
		
		((TwitterApplication) getApplication()).requestLocationUpdates(mSearchLocationObserver);
		setLocationOption();
		mLocClient.start();
    }

    @Override
    protected void onPause() {
        if (mRecorder.state() != Recorder.RECORDING_STATE || mShowFinishButton || mMaxFileSize != -1) {
            mRecorder.stop();
            ((NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE)).cancel(RecorderService.NOTIFICATION_ID);
        }

        if (mReceiver != null) {
            unregisterReceiver(mReceiver);
        }

        // mCanRequestChanged = true;
        mStopUiUpdate = true;

        if (RecorderService.isRecording()) {
            Intent intent = new Intent(this, RecorderService.class);
            intent.putExtra(RecorderService.ACTION_NAME, RecorderService.ACTION_ENABLE_MONITOR_REMAIN_TIME);
            startService(intent);
        }
		
		stopPlay();
		mCommentAdapter.stopPlay();

        super.onPause();
		lastPosition = mCommentList.getFirstVisiblePosition();
		
		((TwitterApplication) getApplication()).removeLocationUpdates(mSearchLocationObserver);
		mLocClient.stop();
    }

	@Override
	protected void onStart() {
		super.onStart();
		Log.d(TAG, "onStart.");
	}

	@Override
	protected void onStop() {
		super.onStop();
		Log.d(TAG, "onStop.");
	}

	@Override
	protected void onDestroy() {
		Log.d(TAG, "onDestroy.");
		if (mSDCardMountEventReceiver != null) {
            unregisterReceiver(mSDCardMountEventReceiver);
            mSDCardMountEventReceiver = null;
        }

		/*
		if (mRelativeTweetTask != null && mRelativeTweetTask.getStatus() == GenericTask.Status.RUNNING) {
			mRelativeTweetTask.cancel(true);
		}
		*/

		super.onDestroy();
		
		taskManager.cancelAll();
        // 刷新按钮停止旋转
        if (loadMoreGIF != null){
        	loadMoreGIF.setVisibility(View.GONE);
        }
        if (mCommentList != null){
        	mCommentList.onRefreshComplete();
        }
	}
	
	/*
     * Registers an intent to listen for
     * ACTION_MEDIA_EJECT/ACTION_MEDIA_UNMOUNTED/ACTION_MEDIA_MOUNTED
     * notifications.
     */
    private void registerExternalStorageListener() {
        if (mSDCardMountEventReceiver == null) {
            mSDCardMountEventReceiver = new BroadcastReceiver() {
                @Override
                public void onReceive(Context context, Intent intent) {
                    mSampleInterrupted = false;
                    mRecorder.reset();
                    updateUi();
                }
            };
            IntentFilter iFilter = new IntentFilter();
            iFilter.addAction(Intent.ACTION_MEDIA_EJECT);
            iFilter.addAction(Intent.ACTION_MEDIA_UNMOUNTED);
            iFilter.addAction(Intent.ACTION_MEDIA_MOUNTED);
            iFilter.addDataScheme("file");
            registerReceiver(mSDCardMountEventReceiver, iFilter);
        }
    }
	
	//设置相关参数
	private void setLocationOption() {
		LocationClientOption option = new LocationClientOption();
		option.setOpenGps(true);  //打开gps
		option.setCoorType("bd0911");  //设置坐标类型
		option.setServiceName("com.baidu.location.service_v2.9");
		option.setPoiExtraInfo(true);
        option.setAddrType("all");
        option.setScanSpan(1000);
        option.setPriority(LocationClientOption.NetWorkFirst);  // LocationClientOption.GpsFirst 
		option.setPoiNumber(10);
		option.disableCache(true);		
		mLocClient.setLocOption(option);
	}

	private void draw() {
		Log.d(TAG, "StatusWithCommentActivity draw");
        profileImage.setImageBitmap(TwitterApplication.mImageLoader.get(tweet.profileImageUrl, callback));
		screenName.setText(tweet.screenName);
		lastStatus.setText(tweet.text);
		if (tweet.createdAt != null) {
			distanceAndCreatedAt.setText(DateTimeHelper.getRelativeDate(tweet.createdAt));
		}
		totalTimeText.setText(String.valueOf(tweet.audioDuration) + "''");
		
		if (tweet.inReplyToStatusId != null && tweet.inReplyToStatusId.length() != 0) {
		    commentCountText.setText("评:" + String.valueOf(tweet.replyCount));
		} else {
		    commentCountText.setText("评:" + String.valueOf(tweet.conversationCount-1));
		}

		playBtn.setVisibility(View.VISIBLE);
		downloadingBtn.setVisibility(View.GONE);
		stopBtn.setVisibility(View.GONE);
		playProgressBar.setMax(10000);
	}
	
	public void drawList() {
		mCommentAdapter.refresh(allCommentList);
    }
	
	public void goTop() {
        Log.d(TAG, "goTop");
        mCommentList.setSelection(1);
        
    }
	
	private void showOverwriteConfirmDialogIfConflicts() {
	
	    long time = System.currentTimeMillis();
        String fileName = "youliao" + "_"  + time + (AUDIO_AMR.equals(mRequestedType) ? FILE_EXTENSION_AMR : FILE_EXTENSION_3GPP);
        if (mRecorder.isRecordExisted(fileName) && !mShowFinishButton) {
            // file already existed and it's not a recording request from other app
            AlertDialog.Builder dialogBuilder = new AlertDialog.Builder(this);
            dialogBuilder.setIcon(android.R.drawable.ic_dialog_alert);
            dialogBuilder.setTitle(getString(R.string.overwrite_dialog_title, fileName));
            dialogBuilder.setPositiveButton(android.R.string.ok,
                    new DialogInterface.OnClickListener() {
                        @Override
                        public void onClick(DialogInterface dialog, int which) {
                            startRecording();
                        }
                    });
            dialogBuilder.setNegativeButton(android.R.string.cancel,
                    new DialogInterface.OnClickListener() {
                        @Override
                        public void onClick(DialogInterface dialog, int which) {
                        
                        }
                    });
            dialogBuilder.show();
        } else {
            startRecording();
        }
    }

	@Override
	protected void onSaveInstanceState(Bundle outState) {
		super.onSaveInstanceState(outState);

		/*
		if (mRelativeTweetTask != null && mRelativeTweetTask.getStatus() == GenericTask.Status.RUNNING) {
			outState.putBoolean(SIS_RUNNING_KEY, true);
		}
		*/
	}
	
	private void startRecording() {
	    Log.d(TAG, "start recording");
        mRemainingTimeCalculator.reset();
        if (!Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
            mSampleInterrupted = true;
            mErrorUiMessage = getResources().getString(R.string.insert_sd_card);
            updateUi();
        } else if (!mRemainingTimeCalculator.diskSpaceAvailable()) {
            mSampleInterrupted = true;
            mErrorUiMessage = getResources().getString(R.string.storage_is_full);
            updateUi();
        } else {
            //stopAudioPlayback();

            boolean isHighQuality = true;
            if (AUDIO_AMR.equals(mRequestedType)) {
                mRemainingTimeCalculator.setBitRate(BITRATE_AMR);
                int outputfileformat = isHighQuality ? MediaRecorder.OutputFormat.AMR_WB : MediaRecorder.OutputFormat.AMR_NB;
                mRecorder.startRecording(outputfileformat, "youliao" + "_" + System.currentTimeMillis(), FILE_EXTENSION_AMR, isHighQuality, mMaxFileSize);
            } else if (AUDIO_3GPP.equals(mRequestedType)) {
                // HACKME: for HD2, there is an issue with high quality 3gpp
                // use low quality instead
                if (Build.MODEL.equals("HTC HD2")) {
                    isHighQuality = false;
                }

                mRemainingTimeCalculator.setBitRate(BITRATE_3GPP);
                mRecorder.startRecording(MediaRecorder.OutputFormat.THREE_GPP, "youliao" + "_" + System.currentTimeMillis(), FILE_EXTENSION_3GPP, isHighQuality, mMaxFileSize);
            } else {
                throw new IllegalArgumentException("Invalid output file type requested");
            }

            if (mMaxFileSize != -1) {
            	Log.d(TAG, "mMaxFileSize != -1");
                mRemainingTimeCalculator.setFileSizeLimit(mRecorder.sampleFile(), mMaxFileSize);
            }
        }
    }
	
	/**
     * Shows/hides the appropriate child views for the new state.
     */
    private void updateUi( ) {
        switch (mRecorder.state()) {
            case Recorder.IDLE_STATE:
			    // mPlayStopImage.setImageResource(R.drawable.player_play);
				
				if ((mRecorder.sampleLength() > 0) && (mRecorder.sampleLength() < MIX_TIME)) {
				    if (mVolumeDialog.isShowing()) {
					    mVolumeDialog.dismiss();
				    }
				    mRecordButton.setText("重新评论");
					// mPlayProgressBar.setProgress(0);
					mRecorder.delete();
					showWarnToast();
				} else if (mRecorder.sampleLength() >= MIX_TIME) {
				    mRecordButton.setText("重新评论");
                    // mTotalTime.setText(String.format(mTimerFormat, mRecorder.sampleLength() / 60, mRecorder.sampleLength() % 60));
				    // mPlayProgressBar.setProgress(0);
					if (mVolumeDialog.isShowing()) {
					    mVolumeDialog.dismiss();
				    }
                }

                // we allow only one toast at one time
                if (mSampleInterrupted && mErrorUiMessage == null) {
                    Toast.makeText(this, R.string.recording_stopped, Toast.LENGTH_SHORT).show();
                }

                if (mErrorUiMessage != null) {
                    Toast.makeText(this, mErrorUiMessage, Toast.LENGTH_SHORT).show();
                }
                break;
            case Recorder.RECORDING_STATE:
			    mRecordButton.setText("松开停止");
				showVoiceDialog();
                break;
            case Recorder.PLAYING_STATE:
                // mPlayStopImage.setImageResource(R.drawable.player_stop);
                break;
        }

        updateTimerView();
        // updateProgressBar();
        updateVUMeterView();
    }
	
	/**
     * Update the big MM:SS timer. If we are in playback, also update the
     * progress bar.
     */
    private void updateTimerView() {
        int state = mRecorder.state();

        boolean ongoing = state == Recorder.RECORDING_STATE;

        if (state == Recorder.RECORDING_STATE) {
            updateTimeRemaining();
        }

        if (ongoing) {
		    long time = mRecorder.progress();
            String timeStr = String.format(mTimerFormat, time / 60, time % 60);
		    record_time_tv.setText(timeStr);
            mHandler.postDelayed(mUpdateTimer, 500);
			if (time >= MAX_TIME) {
			    mRecorder.stop();
			}
        }
    }
	
	private void updateVUMeterView() {
        final int MAX_VU_SIZE = 14;
        if (mRecorder.state() == Recorder.RECORDING_STATE) {
            int vuSize = MAX_VU_SIZE * mRecorder.getMaxAmplitude() / 32768;
            if (vuSize >= MAX_VU_SIZE) {
                vuSize = MAX_VU_SIZE - 1;
            }

            setDialogImage(vuSize);
            mHandler.postDelayed(mUpdateVUMetur, 100);
        }
    }
	
	/*
     * Called when we're in recording state. Find out how much longer we can go
     * on recording. If it's under 5 minutes, we display a count-down in the UI.
     * If we've run out of time, stop the recording.
     */
    private void updateTimeRemaining() {
        long t = mRemainingTimeCalculator.timeRemaining();

        if (t <= 0) {
            mSampleInterrupted = true;
            int limit = mRemainingTimeCalculator.currentLowerLimit();
            switch (limit) {
                case RemainingTimeCalculator.DISK_SPACE_LIMIT:
                    mErrorUiMessage = getResources().getString(R.string.storage_is_full);
                    break;
                case RemainingTimeCalculator.FILE_SIZE_LIMIT:
                    mErrorUiMessage = getResources().getString(R.string.max_length_reached);
                    break;
                default:
                    mErrorUiMessage = null;
                    break;
            }

            mRecorder.stop();
            return;
        }
    }
    
    void showVoiceDialog() {
		mVolumeDialog = new Dialog(StatusWithCommentActivity.this, R.style.DialogStyle);
		mVolumeDialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
		mVolumeDialog.getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
		mVolumeDialog.setContentView(R.layout.volume_dialog);
		volume_img = (ImageView) mVolumeDialog.findViewById(R.id.volume_img);
		record_time_tv = (TextView) mVolumeDialog.findViewById(R.id.record_time_tv);
		mVolumeDialog.show();
	}
	
	void showWarnToast(){
		Toast toast = new Toast(StatusWithCommentActivity.this);
		LinearLayout linearLayout = new LinearLayout(StatusWithCommentActivity.this);
		linearLayout.setOrientation(LinearLayout.VERTICAL); 
		linearLayout.setPadding(20, 20, 20, 20);
		ImageView imageView = new ImageView(StatusWithCommentActivity.this);
		imageView.setImageResource(R.drawable.voice_too_short); 
		 
		TextView mTv = new TextView(StatusWithCommentActivity.this);
		mTv.setText("时间太短录音失败");
		mTv.setTextSize(14);
		mTv.setTextColor(Color.WHITE);
		//mTv.setPadding(0, 10, 0, 0);
		 
		linearLayout.addView(imageView);
		linearLayout.addView(mTv);
		linearLayout.setGravity(Gravity.CENTER);
		linearLayout.setBackgroundResource(R.drawable.record_bg);
		 
		toast.setView(linearLayout); 
		toast.setGravity(Gravity.CENTER, 0,0);
		toast.show();				
	}
	
	void setDialogImage(int voiceValue){
	    switch(voiceValue) {
		    case 0:
			    volume_img.setImageResource(R.drawable.record_animate_01);
				break;
			case 1:
			    volume_img.setImageResource(R.drawable.record_animate_02);
				break;
			case 2:
			    volume_img.setImageResource(R.drawable.record_animate_03);
				break;
			case 3:
			    volume_img.setImageResource(R.drawable.record_animate_04);
				break;
			case 4:
			    volume_img.setImageResource(R.drawable.record_animate_05);
				break;
			case 5:
			    volume_img.setImageResource(R.drawable.record_animate_06);
				break;
			case 6:
			    volume_img.setImageResource(R.drawable.record_animate_07);
				break;
			case 7:
			    volume_img.setImageResource(R.drawable.record_animate_08);
				break;
			case 8:
			    volume_img.setImageResource(R.drawable.record_animate_09);
				break;
			case 9:
			    volume_img.setImageResource(R.drawable.record_animate_10);
				break;
			case 10:
			    volume_img.setImageResource(R.drawable.record_animate_11);
				break;
			case 11:
			    volume_img.setImageResource(R.drawable.record_animate_12);
				break;
			case 12:
			    volume_img.setImageResource(R.drawable.record_animate_13);
				break;
			case 13:
			    volume_img.setImageResource(R.drawable.record_animate_14);
				break;
		}
	}
	
	/*
     * Called when Recorder changed it's state.
     */
    public void onStateChanged(int state) {
        if (state == Recorder.PLAYING_STATE || state == Recorder.RECORDING_STATE) {
            mSampleInterrupted = false;
            mErrorUiMessage = null;
        }

        updateUi();
    }

    /*
     * Called when MediaPlayer encounters an error.
     */
    public void onError(int error) {
        Resources res = getResources();
        String message = null;
        switch (error) {
            case Recorder.STORAGE_ACCESS_ERROR:
                message = res.getString(R.string.error_sdcard_access);
                break;
            case Recorder.IN_CALL_RECORD_ERROR:
                // TODO: update error message to reflect that the recording
                // could not be
                // performed during a call.
            case Recorder.INTERNAL_ERROR:
                message = res.getString(R.string.error_app_internal);
                break;
        }
        if (message != null) {
            new AlertDialog.Builder(this).setTitle(R.string.app_name).setMessage(message)
                    .setPositiveButton(R.string.button_ok, null).setCancelable(false).show();
        }
    }
    
    public List<Status> getCommentMsg() throws HttpException {
		currentPage = 1;
		Paging paging = new Paging(currentPage, 20);
		return getApi().getComment(tweet.id, paging);
	}

	public List<Status> getMoreCommentMsg() throws HttpException {
		++currentPage;
		Paging paging = new Paging(currentPage, 20);
		return getApi().getComment(tweet.id, paging);
	}
    
	public List<Status> getConversationMsg() throws HttpException {
		currentPage = 1;
		Paging paging = new Paging(currentPage, 20);
		return getApi().getConversation(tweet.conversationId, paging);
	}
	
	public List<Status> getMoreConversationMsg() throws HttpException {
		++currentPage;
		Paging paging = new Paging(currentPage, 20);
		return getApi().getConversation(tweet.conversationId, paging);
	}
	
	private void doGetTopicAudio(String fileName, String audioURL) {
	    if (mGetTopicAudioTask != null && mGetTopicAudioTask.getStatus() == AsyncTask.Status.RUNNING) {
			return;
		} else {
			GetTopicAudioTask mGetTopicAudioTask = new GetTopicAudioTask();
			TaskParams params = new TaskParams();
			params.put("filename_str", fileName);
			params.put("audio_url", audioURL);
			mGetTopicAudioTask.execute(params);
		}
	}
	
	public void doGetComment() {
	    Log.d(TAG, "Attempting GetComment.");

        if (mGetCommentTask != null && mGetCommentTask.getStatus() == GenericTask.Status.RUNNING) {
            return;
        } else {
            mGetCommentTask = new GetCommentTask();
            mGetCommentTask.setFeedback(mFeedback);
            mGetCommentTask.setListener(mGetCommentTaskListener);
            mGetCommentTask.execute();
            // Add Task to manager
            taskManager.addTask(mGetCommentTask);
        }
	}
	
	public void doGetConversation() {
	    Log.d(TAG, "Attempting GetConversation.");
        if (mGetConversationTask != null && mGetConversationTask.getStatus() == GenericTask.Status.RUNNING) {
            return;
        } else {
            mGetConversationTask = new GetConversationTask();
            mGetConversationTask.setFeedback(mFeedback);
            mGetConversationTask.setListener(mGetConversationTaskListener);
            mGetConversationTask.execute();
            // Add Task to manager
            taskManager.addTask(mGetConversationTask);
        }
	}
	
	public void doGetMoreComment() {
		Log.d(TAG, "Attempting GetComment.");

        if (mGetMoreCommentTask != null && mGetMoreCommentTask.getStatus() == GenericTask.Status.RUNNING) {
            return;
        } else {
            mGetMoreCommentTask = new GetMoreCommentTask();
            mGetMoreCommentTask.setFeedback(mFeedback);
            mGetMoreCommentTask.setListener(mGetCommentTaskListener);
            mGetMoreCommentTask.execute();
            // Add Task to manager
            taskManager.addTask(mGetMoreCommentTask);
        }
	}
	
	public void doGetMoreConversation() {
	    Log.d(TAG, "Attempting GetConversation.");
        if (mGetMoreConversationTask != null && mGetMoreConversationTask.getStatus() == GenericTask.Status.RUNNING) {
            return;
        } else {
            mGetMoreConversationTask = new GetMoreConversationTask();
            mGetMoreConversationTask.setFeedback(mFeedback);
            mGetMoreConversationTask.setListener(mGetConversationTaskListener);
            mGetMoreConversationTask.execute();
            // Add Task to manager
            taskManager.addTask(mGetMoreConversationTask);
        }
	}
	
	private void doSendComment() {
	    Log.d(TAG, "dosend");
    	if (mSendCommentTask != null && mSendCommentTask.getStatus() == GenericTask.Status.RUNNING) {
			return;
		} else {
			//String status = mRecordTitleEditText.getText().toString();
			String status = "回复：" + tweet.text;
			if (!TextUtils.isEmpty(status) || (mRecorder.sampleFile() != null)) {
				mSendCommentTask = new SendCommentTask();
				mSendCommentTask.setListener(mSendCommentTaskListener);
				// TaskParams params = new TaskParams();
				// params.put("mode", mode);
				mSendCommentTask.execute();
			} else {
				// updateProgress(getString(R.string.page_text_is_null));
			}
		}
    }
	
	private InputStream getInputStream(String url) throws HttpException, IOException {
	    Response res = mClient.get(url);
		InputStream is = res.asStream();
		return is;
	}
	
	private class GetTopicAudioTask extends AsyncTask<TaskParams, Object, TaskResult> {
	    @Override
		protected TaskResult doInBackground(TaskParams... params) {
		    TaskParams param = params[0];
			try {
			    String fileName = param.getString("filename_str");
			    String audioURL = param.getString("audio_url");
				if (!TextUtils.isEmpty(audioURL)) {
				    InputStream is = getInputStream(audioURL);
				    File downloadFile = new File(mDownloadDir.getAbsolutePath() + "/" + fileName);
				    mFilePath = downloadFile.getAbsolutePath();
				    downloadFile.createNewFile();
					OutputStream out = null;
					out = new FileOutputStream(downloadFile);
					int temp = 0;
			        byte[] data = new byte[1024];
			        while((temp = is.read(data))!=-1){
				        out.write(data, 0, temp);
			        }
			        out.flush();
			        is.close();
			        out.close();
				} 
			} catch (HttpException e) {
				Log.e(TAG, e.getMessage(), e);
				return TaskResult.IO_ERROR;
			} catch (IOException e) {
				Log.e(TAG, e.getMessage(), e);
				return TaskResult.IO_ERROR;
			} 
			return TaskResult.OK;
		}
		
		@Override
		protected void onPreExecute() {
		    super.onPreExecute();
		    mPlayBtnSwitch = false;
		}
		
		@Override
		protected void onPostExecute(TaskResult result) {
		    super.onPostExecute(result);
			if (result == TaskResult.AUTH_ERROR) {
			
			} else if (result == TaskResult.OK) {
				mPlayBtnSwitch = true;
			} else if (result == TaskResult.IO_ERROR) {
			
			} else {
			
			}
		}
		
		@Override
		protected void onProgressUpdate(Object... values) {
		    super.onProgressUpdate(values);
		}
	}
	
	private class GetCommentTask extends GenericTask {
		private String _errorMsg;

        public String getErrorMsg() {
            return _errorMsg;
        }

        @Override
        protected TaskResult _doInBackground(TaskParams... params) {
            List<com.codeim.youliao.fanfou.Status> statusList = null;
            try {
                //statusList = getMessageSinceId(maxId);
            	statusList = getCommentMsg();
            } catch (HttpException e) {
                Log.e(TAG, e.getMessage(), e);
                _errorMsg = e.getMessage();
                return TaskResult.IO_ERROR;
            }

            publishProgress(SimpleFeedback.calProgressBySize(40, 20, statusList));
            allCommentList.clear();
			for (com.codeim.youliao.fanfou.Status status : statusList) {
				if (isCancelled()) {
					return TaskResult.CANCELLED;
				}
				Tweet t = Tweet.create(status);
				allCommentList.add(t);

				if (isCancelled()) {
					return TaskResult.CANCELLED;
				}
			}

            return TaskResult.OK;
        }
	}
	
	private class GetConversationTask extends GenericTask {
		private String _errorMsg;

        public String getErrorMsg() {
            return _errorMsg;
        }

        @Override
        protected TaskResult _doInBackground(TaskParams... params) {
            List<com.codeim.youliao.fanfou.Status> statusList = null;
            try {
                //statusList = getMessageSinceId(maxId);
            	statusList = getConversationMsg();
            } catch (HttpException e) {
                Log.e(TAG, e.getMessage(), e);
                _errorMsg = e.getMessage();
                return TaskResult.IO_ERROR;
            }

            publishProgress(SimpleFeedback.calProgressBySize(40, 20, statusList));
            allCommentList.clear();
			for (com.codeim.youliao.fanfou.Status status : statusList) {
				if (isCancelled()) {
					return TaskResult.CANCELLED;
				}
				
				Log.d(TAG, "ReplyToStatusId = " + status.getInReplyToStatusId());
				
				if (!(status.getInReplyToStatusId().equals(""))) {
				    Tweet t = Tweet.create(status);
				    allCommentList.add(t);
				}

				if (isCancelled()) {
					return TaskResult.CANCELLED;
				}
			}

            return TaskResult.OK;
        }
	}
	
	private class GetMoreCommentTask extends GenericTask {
	    private String _errorMsg;

        public String getErrorMsg() {
            return _errorMsg;
        }
		
		@Override
        protected TaskResult _doInBackground(TaskParams... params) {
			List<com.codeim.youliao.fanfou.Status> statusList = null;
		    try {
            	statusList = getMoreCommentMsg();
            } catch (HttpException e) {
                Log.e(TAG, e.getMessage(), e);
                _errorMsg = e.getMessage();
                return TaskResult.IO_ERROR;
            }

            publishProgress(SimpleFeedback.calProgressBySize(40, 20, statusList));
			for (com.codeim.youliao.fanfou.Status status : statusList) {
				if (isCancelled()) {
					return TaskResult.CANCELLED;
				}
				Tweet t = Tweet.create(status);
				allCommentList.add(t);

				if (isCancelled()) {
					return TaskResult.CANCELLED;
				}
			}

            return TaskResult.OK;
		}
	}
	
	private class GetMoreConversationTask extends GenericTask {
	    private String _errorMsg;

        public String getErrorMsg() {
            return _errorMsg;
        }
		
		@Override
        protected TaskResult _doInBackground(TaskParams... params) {
		    List<com.codeim.youliao.fanfou.Status> statusList = null;
            try {
            	statusList = getMoreConversationMsg();
            } catch (HttpException e) {
                Log.e(TAG, e.getMessage(), e);
                _errorMsg = e.getMessage();
                return TaskResult.IO_ERROR;
            }

            publishProgress(SimpleFeedback.calProgressBySize(40, 20, statusList));
			for (com.codeim.youliao.fanfou.Status status : statusList) {
				if (isCancelled()) {
					return TaskResult.CANCELLED;
				}
				// Log.d(TAG, "User: " + user.toString());
				Tweet t = Tweet.create(status);
				allCommentList.add(t);

				if (isCancelled()) {
					return TaskResult.CANCELLED;
				}
			}

            return TaskResult.OK;
		}
	}
	
	private class SendCommentTask extends GenericTask {

		@Override
		protected TaskResult _doInBackground(TaskParams... params) {
		    TwitterApplication twitterApplication = (TwitterApplication) getApplication();
			try {
			    double latitude;
				double longitude;
				Weibo.Location location = null;
				location = LocationUtils.createFoursquareLocation(twitterApplication.getLastKnownLocation());
				if (twitterApplication.getLastKnownLocation() != null) {
				    latitude = location.getLat();
				    longitude = location.getLon();
				} else {
				    BDLocation BDLoc = twitterApplication.getBDLocation();
					while (BDLoc == null) {
					    BDLoc = twitterApplication.getBDLocation();
					}
					latitude = BDLoc.getLatitude();
					longitude = BDLoc.getLongitude();
				}
				
				// String status = mRecordTitleEditText.getText().toString();
				String status;
				status = tweet.text;
				/*
				if (tweet.inReplyToStatusId.equals("null") || tweet.inReplyToStatusId.equals("")) {
				    // status = "回复: " + tweet.text + " @" + tweet.screenName;
					// status = "回复: " + tweet.text;
					status = tweet.text;
					// in_reply_to_status_id = tweet.id;
				} else {
				    Log.d(TAG, "inReplyToStatusId is " + tweet.inReplyToStatusId);
					status = tweet.text;
					// in_reply_to_status_id = tweet.id;
				}
				*/
				
				String in_reply_to_status_id = tweet.id;
				int type = tweet.type;
				File audioFile = mRecorder.sampleFile();
				
				if (audioFile != null) {
				    /*
					// Compress image
					try {
						mFile = getImageManager().compressImage(mFile, 100);
						// ImageManager.DEFAULT_COMPRESS_QUALITY);
					} catch (IOException ioe) {
						Log.e(TAG, "Cann't compress images.");
					}
					*/
					// 发送一条带语音的tweet，并且有语音的时长
					getApi().updateStatusComment(status, audioFile, String.valueOf(mRecorder.sampleLength()), type, in_reply_to_status_id, latitude, longitude);
					// getApi().updateStatusAudio(status, audioFile);
				} else {
					Log.e(TAG, "Cann't send status without AUDIO.");
				}
			} catch (HttpException e) {
				Log.e(TAG, e.getMessage(), e);

				if (e.getStatusCode() == HttpClient.NOT_AUTHORIZED) {
					return TaskResult.AUTH_ERROR;
				}
				return TaskResult.IO_ERROR;
			}

			return TaskResult.OK;
		}
	}
	
	private void onSendBegin() {
		// disableEntry();
		mSendDialog = ProgressDialog.show(StatusWithCommentActivity.this, "", getString(R.string.page_status_updating), true);
		if (mSendDialog != null) {
			mSendDialog.setCancelable(false);
		}
		// updateProgress(getString(R.string.page_status_updating));
	}

	private void onSendSuccess() {
		if (mSendDialog != null) {
			mSendDialog.setMessage(getString(R.string.page_status_update_success));
			mSendDialog.dismiss();
		}

		// updateProgress(getString(R.string.page_status_update_success));
		// enableEntry();

		// FIXME: 不理解这段代码的含义，暂时注释掉
		// try {
		// Thread.currentThread();
		// Thread.sleep(500);
		// updateProgress("");
		// } catch (InterruptedException e) {
		// Log.d(TAG, e.getMessage());
		// }
		// updateProgress("");

		// 发送成功就自动关闭界面
		finish();

		// 关闭软键盘
		// InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
		// imm.hideSoftInputFromWindow(mRecordTitleEditText.getWindowToken(), 0);
	}

	private void onSendFailure() {
		if (mSendDialog != null){
			mSendDialog.setMessage(getString(R.string.page_status_unable_to_update));
			mSendDialog.dismiss();
		}
		// updateProgress(getString(R.string.page_status_unable_to_update));
		// enableEntry();
	}

	/*
	private void doGetRelativeTweet(String status_id) {
		Log.d(TAG, "Attempting get status task.");
		mFeedback.start("");

		if (mRelativeTweetTask != null && mRelativeTweetTask.getStatus() == GenericTask.Status.RUNNING) {
			return;
		} else {
			mRelativeTweetTask = new GetRelativeTweetTask();
			mRelativeTweetTask.setListener(mRelativeTaskListener);

			TaskParams params = new TaskParams();
			params.put("relative_id", status_id);
			mRelativeTweetTask.execute(params);
		}
	}
	*/

	/*
	private class GetRelativeTweetTask extends GenericTask {

		@Override
		protected TaskResult _doInBackground(TaskParams... params) {
			TaskParams param = params[0];
			com.codeim.youliao.fanfou.Status status;
			try {
				String relative_id = param.getString("relative_id");

				if (!TextUtils.isEmpty(relative_id)) {
					// 首先查看是否在数据库中，如不在再去获取
					relativeTweet = getDb().queryTweet(relative_id, -1);
					if (relativeTweet == null) {
						status = getApi().showStatus(relative_id);
						relativeTweet = Tweet.create(status);
					}
				} 		
			} catch (HttpException e) {
				Log.e(TAG, e.getMessage(), e);
				return TaskResult.IO_ERROR;
			}

			return TaskResult.OK;
		}
	}
	*/

	/*
	private void doGetStatus(String status_id) {
		Log.d(TAG, "Attempting get status task.");
		mFeedback.start("");

		if (mStatusTask != null && mStatusTask.getStatus() == GenericTask.Status.RUNNING) {
			return;
		} else {
			mStatusTask = new GetStatusTask();
			mStatusTask.setListener(mStatusTaskListener);

			TaskParams params = new TaskParams();
			params.put("id", status_id);
			mStatusTask.execute(params);
		}
	}
	*/

	/*
	private class GetStatusTask extends GenericTask {

		@Override
		protected TaskResult _doInBackground(TaskParams... params) {
			TaskParams param = params[0];
			com.codeim.youliao.fanfou.Status status;
			try {
				String id = param.getString("id");

				if (!TextUtils.isEmpty(id)) {
					status = getApi().showStatus(id);
					mFeedback.update(80);
					tweet = Tweet.create(status);
				}
			} catch (HttpException e) {
				Log.e(TAG, e.getMessage(), e);
				return TaskResult.IO_ERROR;
			}

			mFeedback.update(99);
			return TaskResult.OK;
		}
	}
	*/

	public void onDeleteFailure() {
		Log.e(TAG, "Delete failed");
	}

	public void onDeleteSuccess() {
		finish();
	}

	@Override
	public boolean onContextItemSelected(MenuItem item) {
		switch (item.getItemId()) {
		case CONTEXT_REFRESH_ID:
			//doGetStatus(tweet.id);
			return true;
		case CONTEXT_CLIPBOARD_ID:
			ClipboardManager clipboard = (ClipboardManager) getSystemService(CLIPBOARD_SERVICE);
			clipboard.setText(TextHelper.getSimpleTweetText(tweet.text));
			return true;
		case CONTEXT_DELETE_ID:
			return true;
		}
		return super.onContextItemSelected(item);
	}

	@Override
	public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) {
		menu.setHeaderIcon(android.R.drawable.ic_menu_more);
		menu.setHeaderTitle(getString(R.string.cmenu_more));

		menu.add(0, CONTEXT_REFRESH_ID, 0, R.string.omenu_refresh);
		menu.add(0, CONTEXT_CLIPBOARD_ID, 0, R.string.cmenu_clipboard);

		if (tweet.userId.equals(TwitterApplication.getMyselfId(false))) {
			menu.add(0, CONTEXT_DELETE_ID, 0, R.string.cmenu_delete);
		}
	}
	
	private class RecorderReceiver extends BroadcastReceiver {

        @Override
        public void onReceive(Context context, Intent intent) {
            if (intent.hasExtra(RecorderService.RECORDER_SERVICE_BROADCAST_STATE)) {
                boolean isRecording = intent.getBooleanExtra(RecorderService.RECORDER_SERVICE_BROADCAST_STATE, false);
                mRecorder.setState(isRecording ? Recorder.RECORDING_STATE : Recorder.IDLE_STATE);
            } else if (intent.hasExtra(RecorderService.RECORDER_SERVICE_BROADCAST_ERROR)) {
                int error = intent.getIntExtra(RecorderService.RECORDER_SERVICE_BROADCAST_ERROR, 0);
                mRecorder.setError(error);
            }
        }
    }
	
	/** 
     * This is really just a dummy observer to get the GPS running
     * since this is the new splash page. After getting a fix, we
     * might want to stop registering this observer thereafter so
     * it doesn't annoy the user too much.
     */
    private class SearchLocationObserver implements Observer {
        @Override
        public void update(Observable observable, Object data) {
        }
    }
}