/*
 * Copyright (c) 2010-2011, The MiCode Open Source Community (www.micode.net)
 *
 * 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 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.res.Configuration;
import android.content.res.Resources;
import android.graphics.Color;
import android.media.AudioManager;
import android.media.MediaRecorder;
import android.os.Build;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.os.IBinder;
import android.text.TextUtils;
import android.util.Log;
import android.view.Gravity;
import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.View.OnTouchListener;
import android.view.Window;
import android.view.WindowManager;
import android.view.inputmethod.InputMethodManager;
import android.widget.Button;
import android.widget.EditText;
import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.ProgressBar;
import android.widget.TextView;
import android.widget.Toast;
import java.io.File;
import java.util.Observable;
import java.util.Observer;

import com.baidu.location.BDLocation;
import com.baidu.location.LocationClient;
import com.baidu.location.LocationClientOption;
import com.codeim.youliao.fanfou.Weibo;
import com.codeim.youliao.http.HttpClient;
import com.codeim.youliao.http.HttpException;
import com.codeim.youliao.location.LocationUtils;
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.TaskParams;
import com.codeim.youliao.task.TaskResult;
import com.codeim.youliao.ui.base.BaseActivity;
import com.codeim.youliao.ui.module.CategoryCheckBox;
import com.codeim.youliao.ui.module.NavBar;
import com.codeim.youliao.R;

public class SoundRecorderActivity extends BaseActivity implements Recorder.OnStateChangedListener {
    private static final String TAG = "SoundRecorder";
    private static final String RECORDER_STATE_KEY = "recorder_state";
    private static final String SAMPLE_INTERRUPTED_KEY = "sample_interrupted";
    private static final String MAX_FILE_SIZE_KEY = "max_file_size";
    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;  // 最小录音时间
	private static final String CATEGORY = "category";

    private String mRequestedType = AUDIO_ANY;
    // private boolean mCanRequestChanged = false;
    private Recorder mRecorder;
    private RecorderReceiver mReceiver;
    private boolean mSampleInterrupted = false;
    private boolean mShowFinishButton = 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 RemainingTimeCalculator mRemainingTimeCalculator;
    private String mTimerFormat;
    // private long mLastClickTime;
    // private int mLastButtonId;
	private CategoryCheckBox mCategoryCheckBox;
	private int mType;
	
	private SearchLocationObserver mSearchLocationObserver = new SearchLocationObserver();
	private LocationClient mLocClient;
	
	// Task
	private GenericTask mSendTask;
	
	private TaskListener mSendTaskListener = 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 "SendTask";
		}
	};

    private final Handler mHandler = new Handler();

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

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

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

    private Button mRecordButton;  // 录音按钮
	
	private FrameLayout mPlayLayoutBtn;  // 播放按钮，是一个布局控件
	
	private EditText mRecordTitleEditText;  // 录音标题
	
	private ProgressBar mPlayProgressBar;  // 录音进度
	
	private ImageView mPlayStopImage;  // 播放停止图案
	
	private TextView mTotalTime;
	
	// private TextView mProgressText;
	
	private Dialog mVolumeDialog;
	
	private ImageView volume_img;
	
	private TextView record_time_tv;
	
	private ProgressDialog dialog;

    private BroadcastReceiver mSDCardMountEventReceiver = null;

    private boolean mStopUiUpdate;
    
    private NavBar mNavbar;

    @Override
    public boolean _onCreate(Bundle savedInstanceState) {
    	if (super._onCreate(savedInstanceState)) {
		    Intent intent = getIntent();
			Bundle extras = intent.getExtras();
			int category = 0;
			if (extras != null) {
			    category = extras.getInt(CATEGORY);
		    }
			
		    // Log.d(TAG, "Intent: " + getIntent().toString());
            initInternalState(intent);
            setContentView(R.layout.record);
        
            // mNavbar = new NavBar(NavBar.HEADER_STYLE_WRITE, this);
            mNavbar = new NavBar(NavBar.HEADER_STYLE_BACK, this);
            mNavbar.setHeaderTitle("发布语音");

            mRecorder = new Recorder(this);
            mRecorder.setOnStateChangedListener(this);
            mReceiver = new RecorderReceiver();
            mRemainingTimeCalculator = new RemainingTimeCalculator();

            initResourceRefs();
			
			mLocClient = ((TwitterApplication)getApplication()).mLocationClient;

            setResult(RESULT_CANCELED);
            registerExternalStorageListener();
		
            if (savedInstanceState != null) {
                Bundle recorderState = savedInstanceState.getBundle(RECORDER_STATE_KEY);
                if (recorderState != null) {
                    mRecorder.restoreState(recorderState);
                    mSampleInterrupted = recorderState.getBoolean(SAMPLE_INTERRUPTED_KEY, false);
                    mMaxFileSize = recorderState.getLong(MAX_FILE_SIZE_KEY, -1);
                }
            }

            setVolumeControlStream(AudioManager.STREAM_MUSIC);
			
			mCategoryCheckBox = (CategoryCheckBox) findViewById(R.id.categoryCheck);
			mCategoryCheckBox.setCategory(category);
        
            Button mTopSendButton = (Button) findViewById(R.id.send_btn);
            mTopSendButton.setVisibility(View.VISIBLE);
		    mTopSendButton.setOnClickListener(new View.OnClickListener() {
			    public void onClick(View v) {
				    doSend();
			    }
		    });
        
            return true;
        
    	} else {
    		return false;
    	}
    }

    @Override
    protected void onNewIntent(Intent intent) {
        super.onNewIntent(intent);
        initInternalState(intent);
    }

    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;
    }

    @Override
    public void onConfigurationChanged(Configuration newConfig) {
        super.onConfigurationChanged(newConfig);

        setContentView(R.layout.record);
        initResourceRefs();
        updateUi();
    }

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

        if (mRecorder.sampleLength() == 0)
            return;

        Bundle recorderState = new Bundle();

        if (mRecorder.state() != Recorder.RECORDING_STATE) {
            mRecorder.saveState(recorderState);
        }
        recorderState.putBoolean(SAMPLE_INTERRUPTED_KEY, mSampleInterrupted);
        recorderState.putLong(MAX_FILE_SIZE_KEY, mMaxFileSize);

        outState.putBundle(RECORDER_STATE_KEY, recorderState);
    }

    /*
     * Whenever the UI is re-created (due f.ex. to orientation change) we have
     * to reinitialize references to the views.
     */
    private void initResourceRefs() {
		mRecordButton = (Button) findViewById(R.id.record_button);
		mPlayLayoutBtn = (FrameLayout) findViewById(R.id.play_progress_bar_layout);
		mRecordTitleEditText = (EditText) findViewById(R.id.recorder_title);
		mPlayProgressBar = (ProgressBar) findViewById(R.id.play_progress_bar);
		mPlayStopImage = (ImageView) findViewById(R.id.play_stop_image);
		mTotalTime = (TextView) findViewById(R.id.record_total_time_tv);
		// mProgressText = (TextView) findViewById(R.id.progress_text);
		
		mRecordTitleEditText.setOnFocusChangeListener(new View.OnFocusChangeListener() {
			public void onFocusChange(View v, boolean hasFocus) {
				InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
                
                if(hasFocus) {
            	    imm.showSoftInputFromInputMethod(SoundRecorderActivity.this.getCurrentFocus() .getWindowToken(), 0);
                    imm.showSoftInputFromInputMethod(mRecordTitleEditText.getWindowToken(), 0);
                } else {
            	    try {
                        imm.hideSoftInputFromWindow(mRecordTitleEditText.getWindowToken(), InputMethodManager.HIDE_NOT_ALWAYS);
                    } catch (Exception e) {
                    // TODO: handle exception
                    System.out.println(" null");
                    }        
                }
            }
		});
		
		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();
					    break;
				}
				return false;
			}
		});
		
		mPlayLayoutBtn.setOnClickListener(new OnClickListener() {
		    @Override
			public void onClick(View v){
			    if(mRecorder.sampleLength() >= MIX_TIME) {
			        switch (mRecorder.state()) {
			            case Recorder.IDLE_STATE:
					        mRecorder.startPlayback(mRecorder.playProgress());
					        break;
			            case Recorder.PLAYING_STATE:
					        mRecorder.stop();
					        break;
			            case Recorder.RECORDING_STATE:
					        break;
				    }
				}
			}
		});

        mPlayProgressBar.setMax(SEEK_BAR_MAX);

        mTimerFormat = getResources().getString(R.string.timer_format);
    }
	
	@Override
	public boolean dispatchTouchEvent(MotionEvent ev) {
	    if (ev.getAction() == MotionEvent.ACTION_DOWN) {
		    View v = getCurrentFocus();
			if (isShouldHideInput(v, ev)) {
			    hideSoftInput(v.getWindowToken());
			}
		}
		return super.dispatchTouchEvent(ev);
	}
	
	private boolean isShouldHideInput(View v, MotionEvent event) {
        if (v != null && (v instanceof EditText)) {
            int[] l = { 0, 0 };
            v.getLocationInWindow(l);
            int left = l[0], top = l[1], bottom = top + v.getHeight(), right = left + v.getWidth();
            if (event.getX() > left && event.getX() < right && event.getY() > top && event.getY() < bottom) {
                // 点击EditText的事件，忽略它。
                return false;
            } else {
                return true;
            }
        }
        // 如果焦点不是EditText则忽略，这个发生在视图刚绘制完，第一个焦点不在EditView上，和用户用轨迹球选择其他的焦点
        return false;
    }
	
	private void hideSoftInput(IBinder token) {
	    if (token != null) {
	        InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
		    imm.hideSoftInputFromWindow(mRecordTitleEditText.getWindowToken(), InputMethodManager.HIDE_NOT_ALWAYS);
	    }
	}

    /*
     * Make sure we're not recording music playing in the background, ask the
     * MediaPlaybackService to pause playback.
     */
    private void stopAudioPlayback() {
        // Shamelessly copied from MediaPlaybackService.java, which
        // should be public, but isn't.
        Intent i = new Intent("com.android.music.musicservicecommand");
        i.putExtra("command", "pause");

        sendBroadcast(i);
    }

    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);
            }
        }
    }

    /*
     * Handle the "back" hardware key.
     */
    @Override
    public boolean onKeyDown(int keyCode, KeyEvent event) {
        if (keyCode == KeyEvent.KEYCODE_BACK) {
            switch (mRecorder.state()) {
                case Recorder.IDLE_STATE:
                    finish();
                    break;
                case Recorder.PLAYING_STATE:
                    mRecorder.stop();
                    break;
                case Recorder.RECORDING_STATE:
                    if (mShowFinishButton) {
                        mRecorder.clear();
                    } else {
                        finish();
                    }
                    break;
            }
            return true;
        } else {
            return super.onKeyDown(keyCode, event);
        }
    }
	
	@Override
	protected void onStart() {
	    super.onStart();
		Log.d(TAG, "onStart");
	}

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

        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);
        }
		
		((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);
        }
		
		((TwitterApplication) getApplication()).removeLocationUpdates(mSearchLocationObserver);
		mLocClient.stop();

        super.onPause();
    }

    @Override
    protected void onStop() {
        if (mShowFinishButton) {
            finish();
        }
        super.onStop();
    }

    /*
    private void showDeleteConfirmDialog() {
        AlertDialog.Builder dialogBuilder = new AlertDialog.Builder(this);
        dialogBuilder.setIcon(android.R.drawable.ic_dialog_alert);
        dialogBuilder.setTitle(R.string.delete_dialog_title);
        dialogBuilder.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialog, int which) {
                mRecorder.delete();
            }
        });
        dialogBuilder.setNegativeButton(android.R.string.cancel,
                new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialog, int which) {
                        mLastButtonId = 0;
                    }
                });
        dialogBuilder.show();
    }
    */

    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) {
                            // mLastButtonId = 0;
                        }
                    });
            dialogBuilder.show();
        } else {
            startRecording();
        }
    }

    /*
     * Called on destroy to unregister the SD card mount event receiver.
     */
    @Override
    public void onDestroy() {
        if (mSDCardMountEventReceiver != null) {
            unregisterReceiver(mSDCardMountEventReceiver);
            mSDCardMountEventReceiver = null;
        }
		
		if (mSendTask != null && mSendTask.getStatus() == GenericTask.Status.RUNNING) {
			// Doesn't really cancel execution (we let it continue running).
			// See the SendTask code for more details.
			mSendTask.cancel(true);
		}

		// Don't need to cancel FollowersTask (assuming it ends properly).
		if (dialog != null) {
			dialog.dismiss();
		}

        super.onDestroy();
    }

    /*
     * 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);
	}

    /*
     * 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 updateProgressBar() {
        if (mRecorder.state() == Recorder.PLAYING_STATE) {
            mPlayProgressBar.setProgress((int) (SEEK_BAR_MAX * mRecorder.playProgress()));
            mHandler.postDelayed(mUpdateSeekBar, 50);
        }
    }

    /*
     * 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;
        }
    }

    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);
        }
    }

    /**
     * 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);
                // mLastButtonId = 0;
				
				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();
    }
	
	// 录音时显示的Dialog
	void showVoiceDialog() {
		mVolumeDialog = new Dialog(SoundRecorderActivity.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();
	}
	
	// 录音时间太短时Toast显示
	void showWarnToast(){
		Toast toast = new Toast(SoundRecorderActivity.this);
		LinearLayout linearLayout = new LinearLayout(SoundRecorderActivity.this);
		linearLayout.setOrientation(LinearLayout.VERTICAL); 
		linearLayout.setPadding(20, 20, 20, 20);
		
		// 定义一个ImageView
		ImageView imageView = new ImageView(SoundRecorderActivity.this);
		imageView.setImageResource(R.drawable.voice_too_short);  // 图标
		 
		TextView mTv = new TextView(SoundRecorderActivity.this);
		mTv.setText("时间太短录音失败");
		mTv.setTextSize(14);
		mTv.setTextColor(Color.WHITE);  // 字体颜色
		//mTv.setPadding(0, 10, 0, 0);
		 
		// 将ImageView和ToastView合并到Layout中
		linearLayout.addView(imageView);
		linearLayout.addView(mTv);
		linearLayout.setGravity(Gravity.CENTER);  // 内容居中
		linearLayout.setBackgroundResource(R.drawable.record_bg);  // 设置自定义Toast的背景
		 
		toast.setView(linearLayout); 
		toast.setGravity(Gravity.CENTER, 0,0);  // 起点位置为中间，100为向下偏移100dp
		toast.show();				
	}
	
	// 录音Dialog图片随声音大小切换
	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();
        }
    }
	
	/*
	private void updateProgress(String progress) {
		mProgressText.setText(progress);
	}
	*/
    
    private void doSend() {
	    Log.d(TAG, "dosend");
    	if (mSendTask != null && mSendTask.getStatus() == GenericTask.Status.RUNNING) {
			return;
		} else {
			String status = mRecordTitleEditText.getText().toString();
			mType = mCategoryCheckBox.getCategory();

			if (!TextUtils.isEmpty(status) || (mRecorder.sampleFile() != null)) {

				mSendTask = new SendTask();
				mSendTask.setListener(mSendTaskListener);

				//TaskParams params = new TaskParams();
				//params.put("mode", mode);
				mSendTask.execute();
			} else {
				// updateProgress(getString(R.string.page_text_is_null));
			}
		}
    }
	
	private class SendTask 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();
				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，并且有语音的时长
					Log.d(TAG, "audio_duration = " + String.valueOf(mRecorder.sampleLength()));
					getApi().updateStatus(status, audioFile, String.valueOf(mRecorder.sampleLength()), mType, 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();
		dialog = ProgressDialog.show(SoundRecorderActivity.this, "", getString(R.string.page_status_updating), true);
		if (dialog != null) {
			dialog.setCancelable(false);
		}
		// updateProgress(getString(R.string.page_status_updating));
	}

	private void onSendSuccess() {
		if (dialog != null) {
			dialog.setMessage(getString(R.string.page_status_update_success));
			dialog.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 (dialog != null){
			dialog.setMessage(getString(R.string.page_status_unable_to_update));
			dialog.dismiss();
		}
		// updateProgress(getString(R.string.page_status_unable_to_update));
		enableEntry();
	}
	
	private void enableEntry() {
		mRecordTitleEditText.setEnabled(true);
	}

	private void disableEntry() {
		mRecordTitleEditText.setEnabled(false);
	}

    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) {
        }
    }
}
