public class MainActivity extends Activity implements View.OnClickListener {

	private String tag = MainActivity.class.getSimpleName();
	
	public static final String EXTRA_IMAGE = "extra_image";

	public static final int REQUEST_PICK_PIC = 1000;
	
	public static final int REQUEST_TAKE_PIC = 1001;
	
	private String mImagePath = null;
	
	
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		
		findViewById(R.id.btn_choose_pic).setOnClickListener(this);
		findViewById(R.id.btn_take_pic).setOnClickListener(this);
		findViewById(R.id.btn_person_manager).setOnClickListener(this);
		findViewById(R.id.btn_group_manager).setOnClickListener(this);
//		findViewById(R.id.btn_faceset_manager).setOnClickListener(this);
		
		DisplayMetrics dm = new DisplayMetrics();
		getWindowManager().getDefaultDisplay().getMetrics(dm);
		MainApplication.mScreenWidth = dm.widthPixels;
	}
	
	@Override
	protected void onActivityResult(int requestCode, int resultCode, Intent data) {
		super.onActivityResult(requestCode, resultCode, data);
		switch (requestCode) {
			case REQUEST_PICK_PIC :
				if(resultCode == RESULT_OK) {
					if(data != null) {
						Uri uri = data.getData();
						if(uri != null) {
							LogUtil.i(tag, uri);
							LogUtil.e(tag, getImageUrl(uri));
							String image = getImageUrl(uri);
							gotoDetect(image);
						}
					}
				}
				break;
			case REQUEST_TAKE_PIC:
				if(resultCode == RESULT_OK && mImagePath != null) {
					gotoDetect(mImagePath);
					mImagePath = null;
				}
				break;
			default :
				break;
		}
	}
	
	
	private String getImageUrl(Uri uri) {
		ContentResolver cr = getContentResolver();
		Cursor c = cr.query(uri, null, null, null, null);
		if(c != null && c.moveToFirst()) {
			return c.getString(c.getColumnIndex("_data"));
		}
		return null;
	}
	
	private void pickImage() {
		Intent intent = new Intent(Intent.ACTION_PICK);
		intent.setType("image/*");
		startActivityForResult(intent, REQUEST_PICK_PIC);
	}
	
	private void takePic() {
		Intent takePhotoIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
		if(Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState())) {
			mImagePath = MainApplication.APP_PIC_PATH + StringUtil.createImageName();
			takePhotoIntent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(new File(mImagePath)));
			startActivityForResult(takePhotoIntent, REQUEST_TAKE_PIC);
		} else {
			Toast.makeText(this, "没有检测到SDcard，请检查SDcard！", Toast.LENGTH_SHORT).show();
		}
	}
	
	
	private void gotoDetect(String image) {
		Intent intent = new Intent(this, DetectActivity.class);
		intent.putExtra(EXTRA_IMAGE, image);
		startActivity(intent);
	}
	
	private void gotoPersonManager() {
		Intent intent = new Intent(this, PersonListActivity.class);
		intent.putExtra(PersonListActivity.EXTRA_MODE, PersonListActivity.MODE_VIEW);
		startActivity(intent);
	}
	
	private void gotoGroupManager() {
		Intent intent = new Intent(this, GroupListActivity.class);
		intent.putExtra(GroupListActivity.EXTRA_MODE, GroupListActivity.MODE_VIEW);
		startActivity(intent);
	}
	
//	private void gotoFacesetManager() {
//		Intent intent = new Intent(this, FacesetListActivity.class);
//		intent.putExtra(FacesetListActivity.EXTRA_MODE, FacesetListActivity.MODE_VIEW);
//		startActivity(intent);
//	}
	
	@Override
	public void onClick(View v) {
		switch (v.getId()) {
			case R.id.btn_choose_pic:
				pickImage();
				break;
			case R.id.btn_take_pic:
				takePic();
				break;
			case R.id.btn_person_manager:
				gotoPersonManager();
				break;
			case R.id.btn_group_manager:
				gotoGroupManager();
				break;
//			case R.id.btn_faceset_manager:
//				gotoFacesetManager();
//				break;
			default :
				break;
		}
	}
	
} public class MainApplication extends Application {
	
	public static final String APP_KEY = "YOUR-APP_KEY ";
	
	public static final String APP_SECRET = "YOUR-APP_SECRET ";
	
	public static final Client CLIENT = new Client(APP_KEY, APP_SECRET);
	
	public static String APP_ROOT_DIR = Environment.getExternalStorageDirectory().getAbsolutePath() + "/FaceDemo/";
	
	public static String APP_PIC_PATH = APP_ROOT_DIR + "image/";
	
	public static String USER_NAME = "xiaoying";
	
	public static int mScreenWidth = 0;

	@Override
	public void onCreate() {
		super.onCreate();
		
		File file = new File(APP_ROOT_DIR);
		if(!file.exists()) {
			file.mkdirs();
		}
		
		file = new File(APP_PIC_PATH);
		if(!file.exists()) {
			file.mkdirs();
		}
	}
} public class FaceDBUtil {
//	db.execSQL("create table if not exists faces(face_id TEXT PRIMARY KEY, face_data TEXT, img_id TEXT, center_x REAL, center_y REAL, " +
//			"eye_left_x REAL, eye_left_y REAL, eye_right_x REAL, eye_right_y REAL, nose_x REAL, nose_y REAL, " +
//			"mouth_left_x REAL, mouth_left_y REAL, mouth_right_x REAL, mouth_right_y REAL, width REAL, height REAL, " +
//			"age_value INTEGER, age_range INTEGER, gender_value TEXT, gender_confidence REAL, race_value TEXT, " +
//			"race_confidence REAL, tag TEXT)");
	
	/**
	 * 插入一条人脸数据
	 * @param context
	 * @param face
	 * @return
	 */
	public static long insertFace(Context context, Face face) throws SQLiteException {
		SQLiteDatabase db = DBHelper.getInstance(context).getWritableDatabase();
		ContentValues values = new ContentValues();
		setValues(values, face);
		long id = db.insert("faces", null, values);
		db.close();
		return id;
	}
	
	/**
	 * 插入多条人脸数据
	 * @param context
	 * @param faces
	 * @return
	 * @throws SQLiteException
	 */
	public static int insertFaces(Context context, List<Face> faces) throws SQLiteException {
		SQLiteDatabase db = DBHelper.getInstance(context).getWritableDatabase();
		int count = 0;
		ContentValues values = new ContentValues();
		for (Face face : faces) {
			values.clear();
			setValues(values, face);
			db.insert("faces", null, values);
			count++;
		}
		db.close();
		return count;
	}
	
	/**
	 * 根据ID查寻一张脸
	 * @param context
	 * @param faceId
	 * @return
	 * @throws SQLiteException
	 */
	public static Face getFace(Context context, String faceId) throws SQLiteException {
		SQLiteDatabase db = DBHelper.getInstance(context).getReadableDatabase();
		Face face = null;
		Cursor cursor = db.query("faces", null, "face_id = ?", new String [] {faceId, }, null, null, null);
		if(cursor != null) {
			if(cursor.moveToFirst()) {
				face = new Face();
				int [] indexs = getIndexs(cursor);
				getValues(cursor, indexs, face);
			}
			cursor.close();
		}
		db.close();
		return face;
	}
	
	/**
	 * 查询所有的Face
	 * @param context
	 * @return
	 * @throws SQLiteException
	 */
	public static List<Face> getFaces(Context context) throws SQLiteException {
		SQLiteDatabase db = DBHelper.getInstance(context).getReadableDatabase();
		List<Face> faces = new ArrayList<Face>();
		Cursor cursor = db.query("faces", null, null, null, null, null, null);
		if(cursor != null) {
			if(cursor.moveToFirst()) {
				int [] indexs = getIndexs(cursor);
				Face face = null;
				do {
					face = new Face();
					getValues(cursor, indexs, face);
				} while(cursor.moveToNext());
			}
			cursor.close();
		}
		db.close();
		return faces;
	}
	
	/**
	 * 删除指定ID的Face
	 * @param context
	 * @param faceId
	 * @return
	 */
	public static int deleteFace(Context context, String faceId) {
		SQLiteDatabase db = DBHelper.getInstance(context).getWritableDatabase();
		int count = db.delete("faces", "face_id = ?", new String [] {faceId, });
		db.close();
		return count;
	}
	
	/**
	 * 删除指定的多个Face
	 * @param context
	 * @param faces
	 * @return
	 */
	public static int deleteFaces(Context context, List<Face> faces) {
		SQLiteDatabase db = DBHelper.getInstance(context).getWritableDatabase();
		int count = 0;
		for (Face face : faces) {
			count += db.delete("faces", "face_id = ?", new String [] {face.getFace_id(), });
		}
		db.close();
		return count;
	}
	
	/**
	 * 删除faces表下所有的Face
	 * @param context
	 * @return
	 */
	public static int deleteFaces(Context context) {
		SQLiteDatabase db = DBHelper.getInstance(context).getWritableDatabase();
		int count = db.delete("faces", null, null);
		db.close();
		return count;
	}
	
	private static void getValues(Cursor c, int [] indexs, Face face) {
		face.setFace_id(c.getString(indexs[0]));
		face.setFace_data(c.getString(indexs[1]));
		face.setImg_id(c.getString(indexs[2]));
		face.setCenter(new PointF(c.getFloat(indexs[3]), c.getFloat(indexs[4])));
		face.setEye_left(new PointF(c.getFloat(indexs[5]), c.getFloat(indexs[6])));
		face.setEye_right(new PointF(c.getFloat(indexs[7]), c.getFloat(indexs[8])));
		face.setNose(new PointF(c.getFloat(indexs[9]), c.getFloat(indexs[10])));
		face.setMouth_left(new PointF(c.getFloat(indexs[11]), c.getFloat(indexs[12])));
		face.setMouth_right(new PointF(c.getFloat(indexs[13]), c.getFloat(indexs[14])));
		face.setWidth(c.getFloat(indexs[15]));
		face.setHeight(c.getFloat(indexs[16]));
		Face.Age age = new Face.Age();
		age.setValue(c.getInt(indexs[17]));
		age.setRange(c.getInt(indexs[18]));
		Face.Gender gender = new Face.Gender();
		gender.setValue(c.getString(indexs[19]));
		gender.setConfidence(c.getFloat(indexs[20]));
		Face.Race race = new Face.Race();
		race.setValue(c.getString(indexs[21]));
		race.setConfidence(c.getFloat(indexs[22]));
	}
	
	private static int [] getIndexs(Cursor c) throws SQLiteException {
		int [] indexs = new int[22];
		indexs[0] = c.getColumnIndex("face_id");
		indexs[1] = c.getColumnIndex("face_data");
		indexs[2] = c.getColumnIndex("img_id");
		indexs[3] = c.getColumnIndex("center_x");
		indexs[4] = c.getColumnIndex("center_y");
		indexs[5] = c.getColumnIndex("eye_left_x");
		indexs[6] = c.getColumnIndex("eye_left_y");
		indexs[7] = c.getColumnIndex("eye_right_x");
		indexs[8] = c.getColumnIndex("eye_right_y");
		indexs[9] = c.getColumnIndex("nose_x");
		indexs[10] = c.getColumnIndex("nose_y");
		indexs[11] = c.getColumnIndex("mouth_left_x");
		indexs[12] = c.getColumnIndex("mouth_left_y");
		indexs[13] = c.getColumnIndex("mouth_right_x");
		indexs[14] = c.getColumnIndex("mouth_right_y");
		indexs[15] = c.getColumnIndex("width");
		indexs[16] = c.getColumnIndex("height");
		indexs[17] = c.getColumnIndex("age_value");
		indexs[18] = c.getColumnIndex("age_range");
		indexs[19] = c.getColumnIndex("gender_value");
		indexs[20] = c.getColumnIndex("gender_confidence");
		indexs[21] = c.getColumnIndex("race_value");
		indexs[22] = c.getColumnIndex("race_confidence");
		return indexs;
		
	}
	
	private static void setValues(ContentValues values, Face face) {
		values.put("face_id", face.getFace_id());
		values.put("face_data", face.getFace_data());
		values.put("img_id", face.getImg_id());
		PointF center = face.getCenter();
		values.put("center_x", center.x);
		values.put("center_y", center.y);
		PointF eyeLeft = face.getEye_left();
		values.put("eye_left_x", eyeLeft.x);
		values.put("eye_left_y", eyeLeft.y);
		PointF eyeRight = face.getEye_right();
		values.put("eye_right_x", eyeRight.x);
		values.put("eye_right_y", eyeRight.y);
		PointF nose = face.getNose();
		values.put("nose_x", nose.x);
		values.put("nose_y", nose.y);
		PointF mouthLeft = face.getMouth_left();
		values.put("mouth_left_x", mouthLeft.x);
		values.put("mouth_left_y", mouthLeft.y);
		PointF mouthRight = face.getMouth_right();
		values.put("mouth_right_x", mouthRight.x);
		values.put("mouth_right_y", mouthRight.y);
		values.put("width", face.getWidth());
		values.put("height", face.getHeight());
		Face.Age age = face.getAge();
		values.put("age_value", age.value);
		values.put("age_range", age.range);
		Face.Gender gender = face.getGender();
		values.put("gender_value", gender.value);
		values.put("gender_confidence", gender.confidence);
		Face.Race race = face.getRace();
		values.put("race_value", race.value);
		values.put("race_confidence", race.confidence);
	}
} public class FacePersonDBUtil {

	/**
	 * 添加一个face到Persons表中
	 * @param context
	 * @param face
	 * @param personId
	 * @return
	 */
	public static long insertFace(Context context, Face face, String personId) throws SQLiteException {
		SQLiteDatabase db = DBHelper.getInstance(context).getWritableDatabase();
		ContentValues values = new ContentValues();
		setValues(values, face, personId);
		long id = db.insert("face_person", null, values);
		db.close();
		return id;
		
	}
	
	/**
	 * 添加多个Face
	 * @param context
	 * @param faces
	 * @param personId
	 * @return
	 * @throws SQLiteException
	 */
	public static int insertFaces(Context context, List<Face> faces, String personId) throws SQLiteException {
		SQLiteDatabase db = DBHelper.getInstance(context).getWritableDatabase();
		ContentValues values = new ContentValues();
		int count = 0;
		for (Face face : faces) {
			values.clear();
			setValues(values, face, personId);
			db.insert("face_person", null, values);
			count++;
		}
		db.close();
		return count;
	}
	
	/**
	 * 从Persons表中删除一个
	 * @param context
	 * @param face
	 * @param personId
	 * @return
	 */
	public static long deleteFace(Context context, Face face, String personId) throws SQLiteException {
		SQLiteDatabase db = DBHelper.getInstance(context).getWritableDatabase();
		long id = db.delete("face_person", "person_id = ? AND face_id = ?", new String [] {personId, face.getFace_id(), });
		db.close();
		return id;
		
	}
	
	/**
	 * 从Person删除多个Face
	 * @param context
	 * @param faces
	 * @param personId
	 * @return
	 * @throws SQLiteException
	 */
	public static int deleteFaces(Context context, List<Face> faces, String personId) throws SQLiteException {
		SQLiteDatabase db = DBHelper.getInstance(context).getWritableDatabase();
		int count = 0;
		for (Face face : faces) {
			db.delete("face_person", "person_id = ? AND face_id = ?", new String [] {personId, face.getFace_id(), });
			count++;
		}
		db.close();
		return count;
	}
	
	
	public static List<Face> getFacesById(Context context, String personId) throws SQLiteException {
		SQLiteDatabase db = DBHelper.getInstance(context).getReadableDatabase();
		List<Face> faces = new ArrayList<Face>();
		db.close();
		return faces;
	}
	
	public static List<Face> getFacesByName(Context context, String personName) throws SQLiteException {
		SQLiteDatabase db = DBHelper.getInstance(context).getReadableDatabase();
		List<Face> faces =  new ArrayList<Face>();
		db.close();
		return faces;
	}
	
	private static void setValues(ContentValues values, Face face, String personId) {
		values.put("face_id", face.getFace_id());
		values.put("person_id", personId);
	}
} public class ImageDBUtil {
//	img_id TEXT PRIMARY KEY, img TEXT, url TEXT, width INTEGER, height INTEGER
	
	/**
	 * 插入一个Image数据
	 * @param context
	 * @param image
	 * @return
	 * @throws SQLiteException
	 */
	public static long insertImage(Context context, Image image) throws SQLiteException {
		SQLiteDatabase db = DBHelper.getInstance(context).getWritableDatabase();
		ContentValues values = new ContentValues();
		setValue(values, image);
		long id = db.insertOrThrow("images", null, values);
		db.close();
		return id;
	}
	
	/**
	 * 插入多条Image数据
	 * @param context
	 * @param images
	 * @return
	 * @throws SQLiteException
	 */
	public static int insertImages(Context context, List<Image> images) throws SQLiteException {
		SQLiteDatabase db = DBHelper.getInstance(context).getWritableDatabase();
		int count = 0;
		ContentValues values = new ContentValues();
		for (Image image : images) {
			values.clear();
			setValue(values, image);
			db.insertOrThrow("images", null, values);
			count++;
		}
		db.close();
		return count;
	}
	
	public static int insertImageifNeed(Context context, Image image) throws SQLiteException {
		SQLiteDatabase db = DBHelper.getInstance(context).getWritableDatabase();
		if(contains(db, image)) {
			return 0;
		}
		ContentValues values = new ContentValues();
		setValue(values, image);
		db.insertOrThrow("images", null, values);
		db.close();
		return 1;
	}
	
	private static boolean contains(SQLiteDatabase db, Image image) throws SQLiteException {
		boolean contains = false;
		Cursor cursor = db.query("images", null, "img_id = ? and img = ?", 
				new String [] {image.getImageId(), image.getImg(), }, null, null, null);
		if(cursor != null) {
			contains = cursor.moveToFirst();
			cursor.close();
		}
		return contains;
	}
	
	/**
	 * 根据ID查找一张Image
	 * @param context
	 * @param id
	 * @return
	 * @throws SQLiteException
	 */
	public static Image getImage(Context context, String id) throws SQLiteException {
		Image image = null;
		SQLiteDatabase db = DBHelper.getInstance(context).getReadableDatabase();
		Cursor cursor = db.query("images", null, "img_id = ?", new String [] {id, }, null, null, null);
		if(cursor != null) {
			if(cursor.moveToFirst()) {
				image = new Image();
				image.setImageId(cursor.getString(cursor.getColumnIndex("img_id")));
				image.setImg(cursor.getString(cursor.getColumnIndex("img")));
				image.setUrl(cursor.getString(cursor.getColumnIndex("url")));
				image.setWidth(cursor.getInt(cursor.getColumnIndex("width")));
				image.setHeight(cursor.getInt(cursor.getColumnIndex("height")));
			}
			cursor.close();
		}
		db.close();
		return image;
	}
	
	/**
	 * 查找一个Person下相关的Image
	 * @param context
	 * @param person
	 * @return
	 * @throws SQLiteException
	 */
	public static List<Image> getImages(Context context, Person person) throws SQLiteException {
		SQLiteDatabase db = DBHelper.getInstance(context).getReadableDatabase();
		List<Image> images = new ArrayList<Image>();
		String [] culumns = new String [] {"images.img_id as img_id", "images.img as img", "images.url as url", 
				"images.width as width", "images.height as height", };
		Cursor cursor = db.query("images,faces,face_person", 
				culumns, 
				"face_person.face_id = faces.face_id and images.img_id = faces.img_id and face_person.person_id = ?", 
				new String [] {person.getPerson_id(), }	, null, null, null);
		if(cursor != null) {
			String [] names = cursor.getColumnNames();
			for (String string : names) {
				LogUtil.e("DB", string);
			}
			if(cursor.moveToFirst()) {
				Image image = null;
				int id = cursor.getColumnIndex("img_id");
				int img = cursor.getColumnIndex("img");
				int url = cursor.getColumnIndex("url");
				int width = cursor.getColumnIndex("width");
				int height = cursor.getColumnIndex("height");
				do {
					image = new Image();
					image.setImageId(cursor.getString(id));
					image.setImg(cursor.getString(img));
					image.setUrl(cursor.getString(url));
					image.setWidth(cursor.getInt(width));
					image.setHeight(cursor.getInt(height));
					images.add(image);
				} while(cursor.moveToNext());
			}
			cursor.close();
		}
		LogUtil.i("DB", images);
		return images;
	}
	
	/**
	 * 查找所有的Image
	 * @param context
	 * @return
	 * @throws SQLiteException
	 */
	public static List<Image> getImages(Context context) throws SQLiteException {
		List<Image> images = new ArrayList<Image>();
		SQLiteDatabase db = DBHelper.getInstance(context).getReadableDatabase();
		Cursor cursor = db.query("images", null, null, null, null, null, null);
		if(cursor != null) {
			if(cursor.moveToFirst()) {
				Image image = null;
				int idIdex = cursor.getColumnIndex("img_id");
				int imgIndex = cursor.getColumnIndex("img");
				int urlIndex = cursor.getColumnIndex("url");
				int widthIndex = cursor.getColumnIndex("width");
				int heightIndex = cursor.getColumnIndex("height");
				do {
					image = new Image();
					image.setImageId(cursor.getString(idIdex));
					image.setImg(cursor.getString(imgIndex));
					image.setUrl(cursor.getString(urlIndex));
					image.setWidth(cursor.getInt(widthIndex));
					image.setHeight(cursor.getInt(heightIndex));
					images.add(image);
				} while(cursor.moveToNext());
			}
			cursor.close();
		}
		db.close();
		return images;
	}
	
	/**
	 * 根据ID删除某一条记录
	 * @param context
	 * @param id
	 * @return
	 * @throws SQLiteException
	 */
	public static int deleteImage(Context context, String id) throws SQLiteException {
		SQLiteDatabase db = DBHelper.getInstance(context).getWritableDatabase();
		int count = db.delete("images", "img_id = ?", new String [] {id, });
		db.close();
		return count;
	}
	
	/**
	 * 删除指定的Image
	 * @param context
	 * @param images
	 * @return
	 * @throws SQLiteException
	 */
	public static int deleteImages(Context context, List<Image> images) throws SQLiteException {
		SQLiteDatabase db = DBHelper.getInstance(context).getWritableDatabase();
		int count = 0;
		for (Image image : images) {
			count += db.delete("images", "img_id = ?", new String [] {image.getImageId(), });
		}
		db.close();
		return count;
	}
	
	/**
	 * 删除所有记录
	 * @param context
	 * @return
	 * @throws SQLiteException
	 */
	public static int deleteImages(Context context) throws SQLiteException {
		SQLiteDatabase db = DBHelper.getInstance(context).getWritableDatabase();
		int count = db.delete("images", null, null);
		db.close();
		return count;
	}
	
	private static void setValue(ContentValues values, Image image) {
		values.put("img_id", image.getImageId());
		values.put("img", image.getImg());
		values.put("url", image.getUrl());
		values.put("width", image.getWidth());
		values.put("height", image.getHeight());
	}
} public class CreatePersonActivity extends Activity {

	public static final String EXTRA_NEW_PERSON = "new_person";
	
	public static final String EXTRA_OLD_PERSON = "old_person";
	
	public static final String EXTRA_MODE = "mode";
	
	public static final int REQUEST_CHOOSE_GROUP = 1000;
	
	public static final int MODE_CREATE = 1;
	
	public static final int MODE_MODIFY = 2;
	
	private String tag = CreatePersonActivity.class.getSimpleName();
	
	private TitleBar mTitleBar = null;
	
	private ProgressDialog mProgressDialog = null;
	
	private EditText mEtName = null;
	
	private EditText mEtTag = null;
	
	private Button mBtnChoose = null;
	
	private ListView mLvChoosedGroup = null;
	
	private AddGroupAdapter mAdapter = null;
	
	private int mPosition = -1;
	
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_create_person);
		
		Intent intent = getIntent();
		
		if(intent.hasExtra(EXTRA_MODE)) {
			int mode = intent.getIntExtra(EXTRA_MODE, MODE_CREATE);
			initView(mode);
		} else {
			Toast.makeText(this, R.string.sys_err, Toast.LENGTH_SHORT).show();
			finish();
		}
		
		initProgressDialog();
	}
	
	private void initView(final int mode) {
		mTitleBar = (TitleBar) findViewById(R.id.tb_create_person);
		mEtName = (EditText) findViewById(R.id.et_create_person_name);
		mEtTag = (EditText) findViewById(R.id.et_create_person_tag);
		mBtnChoose = (Button) findViewById(R.id.btn_add_to_group);
		mLvChoosedGroup = (ListView) findViewById(R.id.lv_add_to_group_list);
		mAdapter = new AddGroupAdapter(this);
		mLvChoosedGroup.setAdapter(mAdapter);
		if(mode == MODE_CREATE) {
			findViewById(R.id.ll_add_to_group_content).setVisibility(View.VISIBLE);
			mTitleBar.setTitle(R.string.create_pserson);
		} else if(mode == MODE_MODIFY) {
			findViewById(R.id.ll_add_to_group_content).setVisibility(View.GONE);
			mTitleBar.setTitle(R.string.modify_person);
			Intent intent = getIntent();
			if(intent.hasExtra(EXTRA_OLD_PERSON)) {
				mPosition = intent.getIntExtra(PersonListActivity.EXTRA_POSITION, -1);
				Person person = (Person) intent.getSerializableExtra(EXTRA_OLD_PERSON);
				mEtName.setText(person.getPerson_name());
				mEtTag.setText(person.getTag());
			} else {
				Toast.makeText(this, R.string.sys_err, Toast.LENGTH_SHORT).show();
				finish();
			}
		}
		mTitleBar.setLeftButton(R.string.cancel, new View.OnClickListener() {
			@Override
			public void onClick(View v) {
				cancel();
			}
		});
		mTitleBar.setRightButton(R.string.submit, new View.OnClickListener() {
			@Override
			public void onClick(View v) {
				submit(mode);
			}
		});
		mBtnChoose.setOnClickListener(new View.OnClickListener() {
			@Override
			public void onClick(View v) {
				gotoChooseGroup();
			}
		});
	}
	
	private void gotoChooseGroup() {
		Intent intent = new Intent(this, GroupListActivity.class);
		intent.putExtra(GroupListActivity.EXTRA_MODE, GroupListActivity.MODE_CHOOSE);
		startActivityForResult(intent, REQUEST_CHOOSE_GROUP);
	}
	
	private void submit(int mode) {
		if(mode == MODE_CREATE) {
			if(mAdapter.getData().isEmpty()) {
				Toast.makeText(this, R.string.need_chooose_group, Toast.LENGTH_SHORT).show();
			} else {
				PersonCreateReq req = new PersonCreateReq();
				req.setPerson_name(mEtName.getText().toString());
				req.setTag(mEtTag.getText().toString());
				req.setGroup_id(getAddedGroupIds());
				if(getIntent().hasExtra(IdentifyFaceActivity.EXTRA_FACE)) {
					Face face = (Face) getIntent().getSerializableExtra(IdentifyFaceActivity.EXTRA_FACE);
					req.setFace_id(face.getFace_id());
				}
				new CreatePerson().execute(req);
			}
		} else if(mode == MODE_MODIFY) {
			Person person = (Person) getIntent().getSerializableExtra(EXTRA_OLD_PERSON);
			person.setPerson_name(mEtName.getText().toString());
			person.setTag(mEtTag.getText().toString());
			new ModifyPerson().execute(person);
		}
	}
	
	private void cancel() {
		setResult(RESULT_CANCELED);
		finish();
	}
	
	private void initProgressDialog() {
		mProgressDialog = new ProgressDialog(this);
		mProgressDialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);
		mProgressDialog.setCancelable(true);
	}
	
	private void showProgressDialog(CharSequence message) {
		if(mProgressDialog == null) {
			initProgressDialog();
		}
		mProgressDialog.setMessage(message);
		mProgressDialog.show();
	}
	
	private void dismissProgressDialog() {
		if(mProgressDialog != null && mProgressDialog.isShowing()) {
			mProgressDialog.dismiss();
		}
	}
	
	/**
	 * 去除已选的Group
	 * @param newGroups
	 * @param oldGroups
	 */
	private List<Group> handleRepeat(List<Group> groups) {
		List<Group> addedGroup = mAdapter.getData();
		if(addedGroup.isEmpty()) {
			return groups;
		}
		List<Group> result = new ArrayList<Group>(groups);
		for (Group group : groups) {
			for (Group g : addedGroup) {
				if(g.getGroup_id().equals(group.getGroup_id())) {
					result.remove(group);
					break;
				}
			}
		}
		return result;
	}
	
	/**
	 * 获取加入的组ID，多个用逗号隔开
	 * @return
	 */
	private String getAddedGroupIds() {
		List<Group> groups = mAdapter.getData();
		StringBuilder sb = new StringBuilder();
		for(int i = 0; i < groups.size(); i++) {
			if(i > 0) {
				sb.append(",");
			}
			sb.append(groups.get(i).getGroup_id());
		}
		return sb.toString();
	}
	
	@SuppressWarnings("unchecked")
	@Override
	protected void onActivityResult(int requestCode, int resultCode, Intent data) {
		super.onActivityResult(requestCode, resultCode, data);
		if(resultCode == RESULT_OK && requestCode == REQUEST_CHOOSE_GROUP) {
			if(data != null && data.hasExtra(GroupListActivity.EXTRA_GROUP_ARRAY)) {
				mAdapter.addAll(handleRepeat((List<Group>) data.getSerializableExtra(GroupListActivity.EXTRA_GROUP_ARRAY)));
			}
		}
	}
	

	@Override
	public boolean onKeyDown(int keyCode, KeyEvent event) {
		if(keyCode == KeyEvent.KEYCODE_BACK) {
			cancel();
			return true;
		}
		return super.onKeyDown(keyCode, event);
	}
	
	/**
	 * 新建一个Person
	 * @author xiaoying
	 *
	 */
	private class CreatePerson extends AsyncTask<PersonCreateReq, Void, PersonCreateResp> {

		private PersonService mmService = new PersonService(MainApplication.CLIENT);
		
		@Override
		protected void onPreExecute() {
			super.onPreExecute();
			showProgressDialog(getString(R.string.submiting_data));
		}
		
		@Override
		protected PersonCreateResp doInBackground(PersonCreateReq... params) {
			try {
				return mmService.createPerson(params[0]);
			} catch (ClientProtocolException e) {
				e.printStackTrace();
			} catch (ParseException e) {
				e.printStackTrace();
			} catch (IOException e) {
				e.printStackTrace();
			} catch (JSONException e) {
				e.printStackTrace();
			}
			return null;
		}
		
		@Override
		protected void onPostExecute(PersonCreateResp result) {
			super.onPostExecute(result);
			if(result != null) {
				if(result.getError_code() == RespConfig.RESP_OK) {
					LogUtil.w(tag, result);
					Person person = new Person();
					person.setPerson_id(result.getPerson_id());
					person.setPerson_name(result.getPerson_name());
					person.setTag(result.getTag());
					PersonDBUtil.insertPerson(CreatePersonActivity.this, person);
					Intent data = getIntent();
					data.putExtra(EXTRA_NEW_PERSON, person);
					setResult(RESULT_OK, data);
					finish();
				} else {
					Toast.makeText(CreatePersonActivity.this, result.getError(), Toast.LENGTH_SHORT).show();
				}
			} else {
				Toast.makeText(CreatePersonActivity.this, R.string.net_err, Toast.LENGTH_SHORT).show();
			}
			dismissProgressDialog();
		}
		
	}
	
	/**
	 * 功能：修改Person信息
	 * @author xiaoying
	 *
	 */
	private class ModifyPerson extends AsyncTask<Person, Void, PersonSetInfoResp> {
		
		private PersonService mmService = new PersonService(MainApplication.CLIENT);
		
		@Override
		protected void onPreExecute() {
			super.onPreExecute();
			showProgressDialog(getString(R.string.submiting_data));
		}
		
		@Override
		protected PersonSetInfoResp doInBackground(Person... params) {
			Person person = params[0];
			try {
				PersonSetInfoReq req = new PersonSetInfoReq(person.getPerson_id(), true);
				req.setName(person.getPerson_name());
				req.setTag(person.getTag());
				return mmService.setPersonInfo(req);
			} catch (ClientProtocolException e) {
				e.printStackTrace();
			} catch (ParseException e) {
				e.printStackTrace();
			} catch (IOException e) {
				e.printStackTrace();
			} catch (JSONException e) {
				e.printStackTrace();
			}
			return null;
		}
		
		@Override
		protected void onPostExecute(PersonSetInfoResp result) {
			super.onPostExecute(result);
			if(result != null) {
				if(result.getError_code() == RespConfig.RESP_OK) {
					LogUtil.w(tag, result);
					Person person = new Person();
					person.setPerson_id(result.getPerson_id());
					person.setPerson_name(result.getPerson_name());
					person.setTag(result.getTag());
					Intent data = new Intent();
					data.putExtra(EXTRA_NEW_PERSON, person);
					data.putExtra(PersonListActivity.EXTRA_POSITION, mPosition);
					setResult(RESULT_OK, data);
					finish();
				} else {
					Toast.makeText(CreatePersonActivity.this, result.getError(), Toast.LENGTH_SHORT).show();
				}
			} else {
				Toast.makeText(CreatePersonActivity.this, R.string.net_err, Toast.LENGTH_SHORT).show();
			}
			dismissProgressDialog();
		}
	}
} public class PersonListActivity extends Activity {

	public static final int MODE_VIEW = 1;
	
	public static final int MODE_PICK = 2;
	
	public static final int MODE_CHOOSE = 3;
	
	public static final String EXTRA_MODE = "mode";
	
	public static final String EXTRA_PERSON = "person";
	
	public static final String EXTRA_PERSON_ARRAY = "person_array";
	
	public static final String EXTRA_FACE = "face";
	
	public static final String EXTRA_POSITION = "position";
	
	public static final int REQUEST_CREATE_PERSON = 1000;
	
	public static final int REQUEST_MODIFY_PREDON = 1001;
	
	public static final int REQUEST_PICK_GROUP = 1002;
	
	private String tag = PersonListActivity.class.getSimpleName();
	
	private TitleBar mTitleBar = null;
	
	private ListView mListView = null;
	
	private PersonListAdapter mAdapter = null;

	private ProgressDialog mProgressDialog = null;
	
	private int mMode = MODE_VIEW;
	
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_person_list);
	
		mMode = getIntent().getIntExtra(EXTRA_MODE, MODE_VIEW);
		
		initView();
		
		new GetPersons().execute();
	}
	
	private void initView() {
		mTitleBar = (TitleBar) findViewById(R.id.tb_person_list_title);
		mListView = (ListView) findViewById(R.id.lv_person_list);
		
		mTitleBar.setLeftButton(R.string.backe, mLeftClick);
		if(mMode == MODE_VIEW) {
			mTitleBar.setTitle(R.string.person_manager);
//			mTitleBar.setRightButton(R.string.create, new View.OnClickListener() {
//				@Override
//				public void onClick(View v) {
//					gotoCreatePerson();
//				}
//			});
			mTitleBar.setRightButtonVisible(false);
			mAdapter = new PersonListAdapter(this);
			mListView.setOnItemClickListener(mViewItemClick);
			mListView.setOnItemLongClickListener(mItemLongClick);
		} else if(mMode == MODE_PICK) {
			mTitleBar.setTitle(R.string.choose_person);
			mTitleBar.setRightButton(R.string.create, new View.OnClickListener() {
				@Override
				public void onClick(View v) {
					gotoCreatePerson();
				}
			});
//			mTitleBar.setRightButtonVisible(false);
			mAdapter = new PersonListAdapter(this, MODE_PICK);
			mListView.setOnItemClickListener(mPicItemClick);
		} else if(mMode == MODE_CHOOSE) {
			mTitleBar.setTitle(R.string.choose_person);
			mTitleBar.setRightButton(R.string.ok, new View.OnClickListener() {
				@Override
				public void onClick(View v) {
					LogUtil.e(tag, mAdapter.getCheckedItems());
					Intent data = new Intent();
					data.putExtra(EXTRA_PERSON_ARRAY, (Serializable) mAdapter.getCheckedItems());
					setResult(RESULT_OK, data);
					finish();
				}
			});
			mAdapter = new PersonListAdapter(this, MODE_CHOOSE);
			mListView.setOnItemClickListener(mChooseItemClick);
		}
		
		mListView.setAdapter(mAdapter);
		
		initProgressDialog();
	}
	
	private void initProgressDialog() {
		mProgressDialog = new ProgressDialog(this);
		mProgressDialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);
		mProgressDialog.setCancelable(true);
	}
	
	private void showProgressDialog(CharSequence message) {
		if(mProgressDialog == null) {
			initProgressDialog();
		}
		mProgressDialog.setMessage(message);
		mProgressDialog.show();
	}
	
	private void dismissProgressDialog() {
		if(mProgressDialog != null && mProgressDialog.isShowing()) {
			mProgressDialog.dismiss();
		}
	}
	
	private void gotoCreatePerson() {
		Intent intent = new Intent(this, CreatePersonActivity.class);
		intent.putExtra(CreatePersonActivity.EXTRA_MODE, CreatePersonActivity.MODE_CREATE);
		if(getIntent().hasExtra(IdentifyFaceActivity.EXTRA_FACE)) {
			intent.putExtra(IdentifyFaceActivity.EXTRA_FACE, getIntent().getSerializableExtra(IdentifyFaceActivity.EXTRA_FACE));
		}
		startActivityForResult(intent, REQUEST_CREATE_PERSON);
	}
	
	private void gotoPickGroup(int position) {
		Intent intent = new Intent(this, GroupListActivity.class);
		intent.putExtra(GroupListActivity.EXTRA_MODE, GroupListActivity.MODE_PICK);
		intent.putExtra(GroupListActivity.EXTRA_POSITION, position);
		startActivityForResult(intent, REQUEST_PICK_GROUP);
	}
	
	private View.OnClickListener mLeftClick = new View.OnClickListener() {
		@Override
		public void onClick(View v) {
			switch (mMode) {
				case MODE_PICK:
				case MODE_CHOOSE:
					setResult(RESULT_CANCELED);
				default :
					break;
			}
			finish();
		}
	};
	
	/** MODE_VIEW下Item单击事件 */
	private AdapterView.OnItemClickListener mViewItemClick = new AdapterView.OnItemClickListener() {
		@Override
		public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
			gotoPersonDetail(mAdapter.getItem(position));
		}
	};
	
	/** MODE_PICK下Item单击事件 */
	private AdapterView.OnItemClickListener mPicItemClick = new AdapterView.OnItemClickListener() {
		@Override
		public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
			LogUtil.e(tag, mAdapter.getItem(position));
			Intent data = new Intent();
			data.putExtra(EXTRA_PERSON, mAdapter.getItem(position));
			if(getIntent().hasExtra(EXTRA_POSITION)) {
				data.putExtra(EXTRA_POSITION, getIntent().getIntExtra(EXTRA_POSITION, -1));
			}
			if(getIntent().hasExtra(EXTRA_FACE)) {
				data.putExtra(EXTRA_FACE, getIntent().getSerializableExtra(EXTRA_FACE));
			}
			setResult(RESULT_OK, data);
			finish();
		}
	};
	
	/** MODE_CHOOSE下Item单击事件 */
	private AdapterView.OnItemClickListener mChooseItemClick = new AdapterView.OnItemClickListener() {
		@Override
		public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
			mAdapter.setChecked(position, !mAdapter.isChecked(position));
		}
	};
	
	/** Item长按事件(只在MODE_VIEW下) **/
	private AdapterView.OnItemLongClickListener mItemLongClick = new AdapterView.OnItemLongClickListener() {
		@Override
		public boolean onItemLongClick(AdapterView<?> parent, View view, final int position, long id) {
			AlertDialog.Builder builder = new AlertDialog.Builder(PersonListActivity.this)
			.setItems(R.array.person_list_long_click_menu, new DialogInterface.OnClickListener() {
				@Override
				public void onClick(DialogInterface dialog, int which) {
					switch (which) {
					case 0:
						gotoPersonDetail(mAdapter.getItem(position));
						break;
					case 1:
						gotoModifyPerson(mAdapter.getItem(position), position);
						break;
					case 2:
						new DeletePerson(position).execute(mAdapter.getItem(position));
						break;
					case 3:
						gotoPickGroup(position);
						break;
					default:
						break;
					}
				}
			});
			builder.create().show();
			return false;
		}
	};
	
	private void gotoPersonDetail(Person person) {
		Intent intent = new Intent(this, PersonDetailActivity.class);
		intent.putExtra(EXTRA_PERSON, person);
		startActivity(intent);
	}
	
	private void gotoModifyPerson(Person person, int position) {
		Intent intent = new Intent(this, CreatePersonActivity.class);
		intent.putExtra(CreatePersonActivity.EXTRA_OLD_PERSON, person);
		intent.putExtra(CreatePersonActivity.EXTRA_MODE, CreatePersonActivity.MODE_MODIFY);
		intent.putExtra(EXTRA_POSITION, position);
		startActivityForResult(intent, REQUEST_MODIFY_PREDON);
	}
	
	@Override
	protected void onActivityResult(int requestCode, int resultCode, Intent data) {
		if(resultCode == RESULT_OK) {
			switch (requestCode) {
				case REQUEST_CREATE_PERSON :
					if(data != null) {
						mAdapter.add((Person) data.getSerializableExtra(CreatePersonActivity.EXTRA_NEW_PERSON));
						setResult(RESULT_OK, data);
						finish();
					}
					break;
				case REQUEST_MODIFY_PREDON:
					if(data != null) {
						int position = data.getIntExtra(EXTRA_POSITION, -1);
						if(position < 0) {
							Toast.makeText(PersonListActivity.this, R.string.sys_err, Toast.LENGTH_SHORT).show();
							return;
						}
						mAdapter.replace(position, (Person) data.getSerializableExtra(CreatePersonActivity.EXTRA_NEW_PERSON));
					}
					break;
				case REQUEST_PICK_GROUP:
					if(data != null && data.hasExtra(GroupListActivity.EXTRA_GROUP) && data.hasExtra(GroupListActivity.EXTRA_POSITION)) {
						GroupAddPersonReq req = new GroupAddPersonReq();
						req.setGroup_id(((Group) data.getSerializableExtra(GroupListActivity.EXTRA_GROUP)).getGroup_id());
						req.setPerson_id(mAdapter.getItem(data.getIntExtra(GroupListActivity.EXTRA_POSITION, -1)).getPerson_id());
						new AddToGroup().execute(req);
					}
					break;
				default :
					break;
			}
		}
	};
	
	@Override
	public boolean onKeyDown(int keyCode, KeyEvent event) {
		if(keyCode == KeyEvent.KEYCODE_BACK) {
			setResult(RESULT_CANCELED);
			finish();
			return true;
		}
		return super.onKeyDown(keyCode, event);
	}
	
	/**
	 * 获取Person列表
	 * @author xiaoying
	 *
	 */
	private class GetPersons extends AsyncTask<Void, Void, InfoGetPersonListResp> {

		private InfoService mmService = new InfoService(MainApplication.CLIENT);
		
		@Override
		protected void onPreExecute() {
			super.onPreExecute();
			showProgressDialog(getString(R.string.msg_getting_data));
		}
		
		@Override
		protected InfoGetPersonListResp doInBackground(Void... params) {
			
			try {
				return mmService.getPersonList();
			} catch (ClientProtocolException e) {
				e.printStackTrace();
			} catch (ParseException e) {
				e.printStackTrace();
			} catch (IOException e) {
				e.printStackTrace();
			} catch (JSONException e) {
				e.printStackTrace();
			}
			return null;
		}
		
		@Override
		protected void onPostExecute(InfoGetPersonListResp result) {
			super.onPostExecute(result);
			if(result != null) {
				if(result.getError_code() == RespConfig.RESP_OK) {
					List<Person> persons = result.getPerson();
					if(persons != null && !persons.isEmpty()) {
						mAdapter.addAll(persons);
					} else {
						Toast.makeText(PersonListActivity.this, R.string.no_data, Toast.LENGTH_SHORT).show();
					}
				} else {
					Toast.makeText(PersonListActivity.this, result.getError(), Toast.LENGTH_SHORT).show();
				}
			} else {
				Toast.makeText(PersonListActivity.this, R.string.net_err, Toast.LENGTH_SHORT).show();
			}
			dismissProgressDialog();
		}
		
	}
	
	/**
	 * 删除Person请求
	 * @author xiaoying
	 *
	 */
	private class DeletePerson extends AsyncTask<Person, Void, PersonDeleteResp> {
		
		private PersonService mmService = new PersonService(MainApplication.CLIENT);
		
		private int mmPosition = -1;
		
		public DeletePerson(int position) {
			this.mmPosition = position;
		}
		
		@Override
		protected void onPreExecute() {
			super.onPreExecute();
			showProgressDialog(getString(R.string.deleting));
		}

		@Override
		protected PersonDeleteResp doInBackground(Person... params) {
			Person person = params[0];
			try {
				PersonDeleteReq req = new PersonDeleteReq(person.getPerson_id(), true);
				return mmService.deletePerson(req);
			} catch (ClientProtocolException e) {
				e.printStackTrace();
			} catch (ParseException e) {
				e.printStackTrace();
			} catch (IOException e) {
				e.printStackTrace();
			} catch (JSONException e) {
				e.printStackTrace();
			}
			return null;
		}
		
		@Override
		protected void onPostExecute(PersonDeleteResp result) {
			super.onPostExecute(result);
			if(result != null) {
				if(result.getError_code() == RespConfig.RESP_OK) {
					if(result.getDeleted() > 0) {
						mAdapter.remove(mmPosition);
					}
				} else {
					Toast.makeText(PersonListActivity.this, result.getError(), Toast.LENGTH_SHORT).show();
				}
			}
			dismissProgressDialog();
		}
		
	}
	
	/**
	 * 功能：添加Perosn到Group
	 * @author xiaoying
	 *
	 */
	private class AddToGroup extends AsyncTask<GroupAddPersonReq, Void, GroupAddPersonResp> {

		private GroupService mmService = new GroupService(MainApplication.CLIENT);
		
		@Override
		protected void onPreExecute() {
			super.onPreExecute();
			showProgressDialog(getString(R.string.submiting_data));
		}
		
		@Override
		protected GroupAddPersonResp doInBackground(GroupAddPersonReq... params) {
			try {
				return mmService.addPerson(params[0]);
			} catch (ClientProtocolException e) {
				e.printStackTrace();
			} catch (ParseException e) {
				e.printStackTrace();
			} catch (IOException e) {
				e.printStackTrace();
			} catch (JSONException e) {
				e.printStackTrace();
			}
			return null;
		}
		
		@Override
		protected void onPostExecute(GroupAddPersonResp result) {
			super.onPostExecute(result);
			if(result != null) {
				if(result.getError_code() == RespConfig.RESP_OK) {
					if(result.getAdded() > 0) {
						Toast.makeText(PersonListActivity.this, R.string.add_to_succues, Toast.LENGTH_SHORT).show();
					} else {
						Toast.makeText(PersonListActivity.this, R.string.add_to_fail, Toast.LENGTH_SHORT).show();
					}
				} else {
					Toast.makeText(PersonListActivity.this, result.getError(), Toast.LENGTH_SHORT).show();
				}
			} else {
				Toast.makeText(PersonListActivity.this, R.string.net_err, Toast.LENGTH_SHORT).show();
			}
			dismissProgressDialog();
		}
		
	}
} public class BitmapUtil {
	private static String tag = BitmapUtil.class.getSimpleName();

	public static final long MAX_SIZE = 3 * 1024 * 1024;

	public static Bitmap loadBitmap(String path, int reqWidth, int reqHeight) {
		LogUtil.i(tag, FileUtil.getFileSize(path));
		BitmapFactory.Options options = new BitmapFactory.Options();
		options.inJustDecodeBounds = true;
		BitmapFactory.decodeFile(path, options);
		options.inSampleSize = calculateInSampleSize(path, reqWidth, reqHeight);
		LogUtil.e(tag, "inSimpleSize =====>>>>" + options.inSampleSize);
		options.inJustDecodeBounds = false;
		return BitmapFactory.decodeFile(path, options);
	}
	
	public static Bitmap loadBitmap(String path, int inSampleSize) {
		BitmapFactory.Options options = new BitmapFactory.Options();
		options.inSampleSize = inSampleSize;
		LogUtil.e(tag, "inSimpleSize =====>>>>" + options.inSampleSize);
		return BitmapFactory.decodeFile(path, options);
	}

	public static int calculateInSampleSize(String path, int reqWidth, int reqHeight) {
		BitmapFactory.Options options = new BitmapFactory.Options();
		options.inJustDecodeBounds = true;
		BitmapFactory.decodeFile(path, options);
		// Raw height and width of image
		final int height = options.outHeight;
		final int width = options.outWidth;
		LogUtil.e(tag, "Bitmap size++++>>> (" + width + ", " + height + ")");
		int inSampleSize = 1;

		if (height > reqHeight || width > reqWidth) {

			// Calculate ratios of height and width to requested height and
			// width
			final int heightRatio = Math.round((float) height / (float) reqHeight);
			final int widthRatio = Math.round((float) width / (float) reqWidth);

			// Choose the smallest ratio as inSampleSize value, this will
			// guarantee
			// a final image with both dimensions larger than or equal to the
			// requested height and width.
			inSampleSize = heightRatio < widthRatio ? heightRatio : widthRatio;
		}

		return inSampleSize;
	}
} public class FileUtil {

	/**
	 * 获取文件大小
	 * @param path
	 * @return
	 */
	public static long getFileSize(String path) {
		return new File(path).length();
	}
} public class LogUtil {

	private final static boolean isPrint = true;
	
	public static void i(String tag, String msg) {
		if(isPrint) {
			Log.i(tag, msg);
		}
	}
	
	public static void i(String tag, Object msg) {
		if(isPrint) {
			Log.i(tag, msg.toString());
		}
	}
	
	public static void w(String tag, String msg) {
		if(isPrint) {
			Log.w(tag, msg);
		}
	}

	public static void w(String tag, Object msg) {
		if(isPrint) {
			Log.w(tag, msg.toString());
		}
	}
	
	public static void e(String tag, String msg) {
		if(isPrint) {
			Log.e(tag, msg);
		}
	}

	public static void e(String tag, Object msg) {
		if(isPrint) {
			Log.e(tag, msg.toString());
		}
	}
} public class MarkFaceView extends FrameLayout {
	
	private String tag = MarkFaceView.class.getSimpleName();
	/** 显示图片的ImageView */
	private ImageView mImageView = null;
	/** Bitmap显示的左边缘 */
	private float mImageLeft = getLeft();
	/** Bitmap显示的上边缘 */
	private float mImageTop = getTop();
	/** Bitmap显示的右边缘 */
	private float mImageRight = getRight();
	/** Bitmap显示的下边缘 */
	private float mImageBottom = getBottom();
	/** 外框宽度 **/
	private float mOuterBorderWidth = 8f;
	/** 内框宽度 **/
	private float mInnerBorderWidth = 2f;
	/** 内外框距离 **/
	private float mIODist = 5f;
	/** 框透明度 */
	private int mAlpha = 130;
	/** 框颜色 */
	private int mBorderColor = Color.argb(mAlpha, 0x00, 0x9A, 0xD6);
	
	private float mTextSize = 30f;
	/** Bitmap显示和实际的缩放比例 */
	private float mScale = 1.0f;
	/** Bitmap对象，当调用setBitmap(Bitmap bitmap)方法时，或将参数中的bitmap复制到这个对象中，并且是Mutable的 */
	private Bitmap mBitmap = null;
	/** 画布 */
	private Canvas mCanvas = new Canvas();
	
	private Paint mPaint = new Paint();
	/** 人脸信息 */
	private List<Face> mFaces = null;
	/** 在显示出来的界面中，人脸的位置 */
	private List<RectF> mRects = new ArrayList<RectF>();
	
	private MarkFaceView.OnFceClickListener mListener;

	public MarkFaceView(Context context, AttributeSet attrs, int defStyle) {
		super(context, attrs, defStyle);
		initView();
	}

	public MarkFaceView(Context context, AttributeSet attrs) {
		super(context, attrs);
		initView();
	}

	public MarkFaceView(Context context) {
		super(context);
		initView();
	}
	
	private void initView() {
		mImageView = new ImageView(getContext());
		mImageView.setScaleType(ScaleType.CENTER_INSIDE);
		addView(mImageView, new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));
	}

	/**
	 * 设置显示要进行人脸识别的图片
	 * @param bitmap
	 */
	public void setBitmap(final Bitmap bitmap) {
		if(bitmap == null) {
			throw new IllegalArgumentException("Bitmap shut not be null");
		}
		LogUtil.i(tag, "Bitmap size=====>>>(" + bitmap.getWidth() + ", " + bitmap.getHeight() + ")");
		mBitmap = bitmap.copy(Config.ARGB_8888, true);
		mImageView.setImageBitmap(mBitmap);
		mCanvas.setBitmap(mBitmap);
	}
	
	/**
	 * 计算图片显示的位置和与原Bimtap的缩放比例
	 * @param bitmap
	 */
	private void calculatePosition(Bitmap bitmap) {
		LogUtil.e(tag, "Content++++>>>(" + getLeft() + ", " + getTop() + ", " + getRight() + ", " + getBottom() + ")");
		float scaleX = ((float) getWidth()) / bitmap.getWidth();
		float scaleY = ((float) getHeight()) / bitmap.getHeight();
		if(scaleX < scaleY && scaleX < 1) {	//以X为准， 并且Bitmap比显示宽度大
			mImageLeft = 0;
			mImageTop = ((float) (getHeight() - bitmap.getHeight() * scaleX)) / 2;
			mImageRight = getRight();
			mImageBottom = mImageTop + bitmap.getHeight() * scaleX;
			mScale = scaleX;
		} else if(scaleX > scaleY && scaleY < 1){	//以Y为准，并且Bitmap比显示宽度大
			mImageLeft = ((float) (getWidth() - bitmap.getWidth() * scaleY)) / 2;
			mImageTop = 0;
			mImageRight = mImageLeft + bitmap.getWidth() * scaleY;
			mImageBottom = getBottom();
			mScale = scaleY;
		} else {
			mImageLeft = ((float) (getWidth() - bitmap.getWidth())) / 2;
			mImageTop = ((float) (getHeight() - bitmap.getHeight())) / 2;
			mImageRight = mImageLeft + bitmap.getWidth();
			mImageBottom = mImageTop + bitmap.getHeight();
			mScale = 1f;
		}
	}
	
	/**
	 * 标出人脸
	 * @param faces
	 */
	public void markFaces(List<Face> faces) {
		this.mFaces = faces;
		drawRects(mFaces);
	}
	
	/**
	 * 绘制标识边框
	 * @param faces
	 */
	public void drawRects(List<Face> faces) {
		calculatePosition(mBitmap);
		int bmWidth = mBitmap.getWidth();
		int bmHeight = mBitmap.getHeight();
//		float outerBorderWidth = getNeedSize(bmWidth, bmHeight, mOuterBorderWidth);
//		float innerBorderWidth = getNeedSize(bmWidth, bmHeight, mInnerBorderWidth);
		mPaint.setColor(mBorderColor);
		for (Face face : faces) {
//			mPaint.setStrokeWidth(outerBorderWidth);
			drawOuterRect(mCanvas, mPaint, face, bmWidth, bmHeight);
			
//			drawTagBackgroupd(mCanvas, mPaint, face, bmWidth, bmHeight);
//			
//			drawTagText(mCanvas, mPaint, face, bmWidth, bmHeight, "TAG");

//			mPaint.setStrokeWidth(innerBorderWidth);
			drawInerRect(mCanvas, mPaint, face, bmWidth, bmHeight);
			
		}
		mImageView.setImageBitmap(mBitmap);
	}
	
	/**
	 * 绘制外框
	 * @param canvas
	 * @param paint
	 * @param face
	 * @param bmWidth
	 * @param bmHeight
	 */
	private void drawOuterRect(Canvas canvas, Paint paint, Face face, int bmWidth, int bmHeight) {
		PointF center = face.getCenter();
		float width = face.getWidth();
		float height = face.getHeight();
		float left = (bmWidth * (center.x / 100) - bmWidth * (width / 100) / 2) - mOuterBorderWidth / mScale;
		float top = (bmHeight * (center.y / 100) - bmHeight * (height / 100) / 2) - mOuterBorderWidth / mScale;
		float right = (bmWidth * (center.x / 100) + bmWidth * (width / 100) / 2) + mOuterBorderWidth / mScale;
		float bottom = (bmHeight * (center.y / 100) + bmHeight * (height / 100) / 2) + mOuterBorderWidth / mScale;
		RectF rect = new RectF(left, top, right, bottom);
//		mRects.add(new RectF(mImageLeft + (left + paint.getStrokeWidth()) * mScale, 
//				mImageTop + (top + paint.getStrokeWidth()) * mScale, 
//				mImageLeft + (right - paint.getStrokeWidth()) * mScale, 
//				mImageTop + (bottom - paint.getStrokeWidth()) * mScale));
		mRects.add(new RectF(mImageLeft + left * mScale + mOuterBorderWidth, 
				mImageTop + top * mScale + mOuterBorderWidth, 
				mImageLeft + right * mScale - mOuterBorderWidth, 
				mImageTop + bottom * mScale - mOuterBorderWidth));
		mPaint.setColor(mBorderColor);
		mPaint.setStyle(Style.STROKE);
		mPaint.setStrokeWidth(mOuterBorderWidth / mScale);
		canvas.drawRect(rect, paint);
	}
	
	/**
	 * 绘制内框
	 * @param canvas
	 * @param paint
	 * @param face
	 * @param bmWidth
	 * @param bmHeight
	 */
	private void drawInerRect(Canvas canvas, Paint paint, Face face, int bmWidth, int bmHeight) {
		PointF center = face.getCenter();
		float width = face.getWidth();
		float height = face.getHeight();
		float left = (bmWidth * (center.x / 100) - bmWidth * (width / 100) / 2) + mIODist / mScale;
		float top = (bmHeight * (center.y / 100) - bmHeight * (height / 100) / 2) + mIODist / mScale;
		float right = (bmWidth * (center.x / 100) + bmWidth * (width / 100) / 2) - mIODist / mScale;
		float bottom = (bmHeight * (center.y / 100) + bmHeight * (height / 100) / 2) - mIODist / mScale;
		mPaint.setColor(mBorderColor);
		mPaint.setStyle(Style.STROKE);
		mPaint.setStrokeWidth(mInnerBorderWidth / mScale);
		canvas.drawLines(getInerPoints(left, top, right, bottom), paint);
	}
	
	
	private float [] getInerPoints(float left, float top, float right, float bottom) {
		float inerLength = (right - left) / 4;
		return new float [] {
				left, top, left + inerLength, top, 
				left, top, left, top + inerLength, 
				right - inerLength, top, right, top, 
				right, top, right, top + inerLength, 
				left, bottom - inerLength, left, bottom, 
				left, bottom, left + inerLength, bottom,
				right - inerLength, bottom, right, bottom, 
				right, bottom - inerLength, right, bottom,
		};
	}
	
//	private void drawTagBackgroupd(Canvas canvas, Paint paint, Face face, int bmWidth, int bmHeight) {
//		PointF center = face.getCenter();
//		float width = face.getWidth();
//		float height = face.getHeight();
//		float left = (bmWidth * (center.x / 100) - bmWidth * (width / 100) / 2) - paint.getStrokeWidth() * 3 /2;
//		float top = (bmHeight * (center.y / 100) - bmHeight * (height / 100) / 2) - paint.getStrokeWidth() * 3 / 2 - mTextSize / mScale;
//		float right = (bmWidth * (center.x / 100) + bmWidth * (width / 100) / 2) + paint.getStrokeWidth() * 3 / 2;
//		float bottom = (bmHeight * (center.y / 100) - bmHeight * (height / 100) / 2) - paint.getStrokeWidth() * 3 / 2;
//		RectF rect = new RectF(left, top, right, bottom);
////		mRects.add(new RectF(mImageLeft + (left + paint.getStrokeWidth()) * mScale, 
////				mImageTop + (top + paint.getStrokeWidth()) * mScale, 
////				mImageLeft + (right - paint.getStrokeWidth()) * mScale, 
////				mImageTop + (bottom - paint.getStrokeWidth()) * mScale));
//		mPaint.setColor(mBorderColor);
//		mPaint.setStyle(Style.FILL);
//		canvas.drawRect(rect, paint);
//	}
	
//	private void drawTagText(Canvas canvas, Paint paint, Face face, int bmWidth, int bmHeight, String text) {
//		PointF center = face.getCenter();
//		float width = face.getWidth();
//		float height = face.getHeight();
//		float x = (bmWidth * (center.x / 100) - bmWidth * (width / 100) / 2) - paint.getStrokeWidth() / 2;
//		float y = (bmHeight * (center.y / 100) - bmHeight * (height / 100) / 2) - paint.getStrokeWidth() * 3 / 2;
//		mPaint.setColor(Color.BLACK);
//		mPaint.setStyle(Style.FILL_AND_STROKE);
//		mPaint.setStrokeWidth(1f);
//		mPaint.setTextSize(mTextSize / mScale);
//		canvas.drawText(text, x, y, paint);
//	}
//	
//	/**
//	 * 根据Bitmap显示在ImageViwe中的缩放比例，算出在手机显示相应像素的实际像素
//	 * @param bmWidth
//	 * @param bmHeight
//	 * @param real
//	 * @return
//	 */
//	private float getNeedSize(int bmWidth, int bmHeight, float real) {
//		float ivWidth = mImageRight - mImageLeft;
//		float ivHeight = mImageBottom - mImageTop;
//		if(ivWidth > bmWidth && ivHeight > bmHeight) {
//			return real;
//		}
//		float wScale = (float)bmWidth / ivWidth;
//		float hScale = (float) bmHeight / ivHeight;
//		float scale = wScale < hScale ? wScale : hScale;
//		return real * scale;
//	}

	/**
	 * 设置外框宽度
	 * @param width
	 */
	public void setOuterBorderWidth(float width) {
		this.mOuterBorderWidth = width;
	}
	
	/**
	 * 获取外框宽度
	 * @return
	 */
	public float getOuterBorderWidth() {
		return mOuterBorderWidth;
	}
	
	/**
	 * 设置内边框宽度
	 * @param width
	 */
	public void setInnerBorderWidth(float width) {
		this.mInnerBorderWidth = width;
	}
	
	/**
	 * 获取内边框宽度
	 * @return
	 */
	public float getInnerBorderWidth() {
		return mInnerBorderWidth;
	}
	
	/**
	 * 设置人脸点击监听
	 * @param listener
	 */
	public void setOnFaceClickListener(MarkFaceView.OnFceClickListener listener) {
		this.mListener = listener;
	}
	
	/**
	 * 设置边框绘制的透明度
	 * @param alpha
	 */
	public void setBorderAlpha(int alpha) {
		this.mAlpha = alpha;
	}
	
	/**
	 * 获取边框的透明度
	 * @return
	 */
	public int getBorderAlpha() {
		return mAlpha;
	}
	
	/**
	 * 设置边框颜色
	 * @param color
	 */
	public void setBorderColor(int color) {
		mBorderColor = Color.argb(mAlpha, Color.red(color), Color.green(color), Color.blue(color));
	}
	
	/**
	 * 获取边框颜色
	 * @return
	 */
	public int getBorderColor() {
		return mBorderColor;
	}
	
	/**
	 * 设置内外边框的距离
	 * @param dist
	 */
	public void setIODist(float dist) {
		this.mIODist = dist;
	}
	
	/**
	 * 获取内外边框的距离
	 * @return
	 */
	public float getIODist() {
		return mIODist;
	}
	
	@Override
	public boolean onTouchEvent(MotionEvent event) {
		float x = event.getX();
		float y = event.getY();
		switch (event.getAction()) {
			case MotionEvent.ACTION_DOWN :
				x = event.getX();
				y = event.getY();
				for (int i = 0; i < mRects.size(); i++) {
					RectF rect = mRects.get(i);
					if(x > rect.left && x < rect.right && y > rect.top && y < rect.bottom) {
						LogUtil.e(tag, "Clicked in a face++++>>" + i);
						mListener.onFaceClicked(mFaces.get(i), i);
						break;
					}
				}
				break;
			default :
				break;
		}
		return super.onTouchEvent(event);
	}
	
	/**
	 * 功能：实现点击人脸时操作的interface
	 * @author xiaoying
	 *
	 */
	public static interface OnFceClickListener {
		public void onFaceClicked(Face face, int position);
	}
} public class TitleBar extends RelativeLayout {
	
	private Button mBtnLeft = null;
	
	private TextView mTvCenter = null;
	
	private Button mBtnRight = null;
	
	public TitleBar(Context context) {
		super(context);
		initView(context);
	}

	public TitleBar(Context context, AttributeSet attrs, int defStyle) {
		super(context, attrs, defStyle);
		initView(context);
	}

	public TitleBar(Context context, AttributeSet attrs) {
		super(context, attrs);
		initView(context);
	}

	private void initView(Context context) {
		View view = View.inflate(context, R.layout.layout_top_title, null);
		mBtnLeft = (Button) view.findViewById(R.id.btn_top_left);
		mTvCenter = (TextView) view.findViewById(R.id.tv_top_center);
		mBtnRight = (Button) view.findViewById(R.id.btn_top_right);
		addView(view, new FrameLayout.LayoutParams(FrameLayout.LayoutParams.MATCH_PARENT, FrameLayout.LayoutParams.WRAP_CONTENT));
	}
	
	
	public void setTitle(CharSequence text) {
		mTvCenter.setText(text);
	}
	
	public void setTitle(int resid) {
		mTvCenter.setText(resid);
	}
	
	public void setLeftButtonText(CharSequence text) {
		mBtnLeft.setText(text);
	}
	
	public void setLeftButtonText(int resid) {
		mBtnLeft.setText(resid);
	}
	
	public void setLeftButtonIcon(int resid) {
		mBtnLeft.setBackgroundResource(resid);
	}
	
	public void setLeftButtonListener(View.OnClickListener listener) {
		mBtnLeft.setOnClickListener(listener);
	}
	
	public void setLeftButton(CharSequence text, View.OnClickListener listener) {
		setLeftButtonText(text);
		setLeftButtonListener(listener);
	}
	
	public void setLeftButton(int resid, View.OnClickListener listener) {
		setLeftButtonText(resid);
		setLeftButtonListener(listener);
	}

	public void setRightButtonText(CharSequence text) {
		mBtnRight.setText(text);
	}
	
	public void setRightButtonText(int resid) {
		mBtnRight.setText(resid);
	}
	
	public void setRightButtonIcon(int resid) {
		mBtnRight.setBackgroundResource(resid);
	}
	
	public void setRightButtonListener(View.OnClickListener listener) {
		mBtnRight.setOnClickListener(listener);
	}
	
	public void setRightButton(CharSequence text, View.OnClickListener listener) {
		setRightButtonText(text);
		setRightButtonListener(listener);
	}
	
	public void setRightButton(int resid, View.OnClickListener listener) {
		setRightButtonText(resid);
		setRightButtonListener(listener);
	}
	
	public void setLeftButtonVisible(boolean isVisible) {
		mBtnLeft.setVisibility(isVisible ? View.VISIBLE : View.INVISIBLE);
	}
	
	public void setRightButtonVisible(boolean isVisible) {
		mBtnRight.setVisibility(isVisible ? View.VISIBLE : View.INVISIBLE);
	}
	
} public class Client {
	private String appKey;	//APP_KEY
	private String appSecret;	//APP_SECREET
	
	public Client(String appKey, String appSecret) {
		if(StringUtil.isEmpty(appKey) || StringUtil.isEmpty(appSecret)) {
			throw new IllegalArgumentException("APP_KEY and APP_Secret must be not null.");
		}
		this.appKey = appKey;
		this.appSecret = appSecret;
	}
	
	public String getAppKey() {
		return appKey;
	}
	public void setAppKey(String appKey) {
		this.appKey = appKey;
	}
	public String getAppSecret() {
		return appSecret;
	}
	public void setAppSecret(String appSecret) {
		this.appSecret = appSecret;
	}
	@Override
	public String toString() {
		return "Client [appKey=" + appKey + ", appSecret=" + appSecret + "]";
	}
} public class RespConfig {

	public final static int RESP_OK = 0;
	
	public final static int FACESET_MAX_FACE = 10000;
	
} public class Face implements Serializable {
	/**
	 * 
	 */
	private static final long serialVersionUID = 8603825983713166688L;
	// face array 被检测出的人脸的列表
	private String face_id; //被检测出的每一张人脸都在Face++系统中的标识符
	private String face_data; //人脸本地截图的路径，如果有的话，没有为空
	private String img_id; //人脸相关的图片id
	private String url;	//相关图片的url
	
	private float width; // 0~100之间的实数，表示检出的脸的宽度在图片中百分比
	private float height; // 0~100之间的实数，表示检出的脸的高度在图片中百分比
	private PointF center; // 检出的人脸框的中心点坐标, x & y 坐标分别表示在图片中的宽度和高度的百分比(0~100之间的实数)
	private PointF eye_left; // 相应人脸的左眼坐标，x & y 坐标分别表示在图片中的宽度和高度的百分比(0~100之间的实数)
	private PointF eye_right; // 相应人脸的右眼坐标，x & y 坐标分别表示在图片中的宽度和高度的百分比(0~100之间的实数)
	private PointF mouth_left; // 相应人脸的左侧嘴角坐标，x & y 坐标分别表示在图片中的宽度和高度的百分比(0~100之间的实数)
	private PointF mouth_right; // 相应人脸的右侧嘴角坐标，x & y 坐标分别表示在图片中的宽度和高度的百分比(0~100之间的实数)
	private PointF nose; // 相应人脸的鼻尖坐标，x & y 坐标分别表示在图片中的宽度和高度的百分比 (0~100之间的实数)
	
	// attribute object 包含一系列人脸的属性分析结果 gender object 包含性别分析结果，value的值为Male/Female, confidence表示置信度
	private Gender gender;
	// age object 包含年龄分析结果，value的值为一个非负整数表示估计的年龄, range表示估计年龄的正负区间
	private Age age;
	// race object 包含人种分析结果，value的值为Asian/White/Black, confidence表示置信度
	private Race race;
	
	private String tag;	//人脸描述
	
	/**
	 * 被检测出的每一张人脸都在Face++系统中的标识符
	 * @return
	 */
	public String getFace_id() {
		return face_id;
	}

	/**
	 * 被检测出的每一张人脸都在Face++系统中的标识符
	 * @param face_id
	 */
	public void setFace_id(String face_id) {
		this.face_id = face_id;
	}
	
	

	/**
	 * 人脸本地截图的路径，如果有的话，没有为空
	 * @return the face_data
	 */
	public String getFace_data() {
		return face_data;
	}

	/**
	 * 人脸本地截图的路径，如果有的话，没有为空
	 * @param face_data the face_data to set
	 */
	public void setFace_data(String face_data) {
		this.face_data = face_data;
	}

	/**
	 * 人脸相关的图片id
	 * @return
	 */
	public String getImg_id() {
		return img_id;
	}

	/**
	 * 人脸相关的图片id
	 * @param img_id
	 */
	public void setImg_id(String img_id) {
		this.img_id = img_id;
	}
	
	/**
	 * 图片url
	 * @return the url
	 */
	public String getUrl() {
		return url;
	}
	/**
	 * 图片url
	 * @param url the url to set
	 */
	public void setUrl(String url) {
		this.url = url;
	}
	
	/**
	 * 0~100之间的实数，表示检出的脸的宽度在图片中百分比
	 * @return
	 */
	public float getWidth() {
		return width;
	}
	
	/**
	 * 0~100之间的实数，表示检出的脸的宽度在图片中百分比
	 * @param width
	 */
	public void setWidth(float width) {
		this.width = width;
	}
	
	/**
	 * 0~100之间的实数，表示检出的脸的高度在图片中百分比
	 * @return
	 */
	public float getHeight() {
		return height;
	}
	
	/**
	 * 0~100之间的实数，表示检出的脸的高度在图片中百分比
	 * @param height
	 */
	public void setHeight(float height) {
		this.height = height;
	}
	
	/**
	 * 检出的人脸框的中心点坐标, x & y 坐标分别表示在图片中的宽度和高度的百分比(0~100之间的实数)
	 * @return
	 */
	public PointF getCenter() {
		return center;
	}
	
	/**
	 * 检出的人脸框的中心点坐标, x & y 坐标分别表示在图片中的宽度和高度的百分比(0~100之间的实数)
	 * @param center
	 */
	public void setCenter(PointF center) {
		this.center = center;
	}
	/**
	 *  相应人脸的左眼坐标，x & y 坐标分别表示在图片中的宽度和高度的百分比(0~100之间的实数)
	 * @return
	 */
	public PointF getEye_left() {
		return eye_left;
	}
	
	/**
	 *  相应人脸的左眼坐标，x & y 坐标分别表示在图片中的宽度和高度的百分比(0~100之间的实数)
	 * @param eye_left
	 */
	public void setEye_left(PointF eye_left) {
		this.eye_left = eye_left;
	}
	
	/**
	 * 相应人脸的右眼坐标，x & y 坐标分别表示在图片中的宽度和高度的百分比(0~100之间的实数)
	 * @return
	 */
	public PointF getEye_right() {
		return eye_right;
	}
	
	/**
	 * 相应人脸的右眼坐标，x & y 坐标分别表示在图片中的宽度和高度的百分比(0~100之间的实数)
	 * @param eye_right
	 */
	public void setEye_right(PointF eye_right) {
		this.eye_right = eye_right;
	}
	
	/**
	 * 相应人脸的左侧嘴角坐标，x & y 坐标分别表示在图片中的宽度和高度的百分比(0~100之间的实数)
	 * @return
	 */
	public PointF getMouth_left() {
		return mouth_left;
	}
	
	/**
	 * 相应人脸的左侧嘴角坐标，x & y 坐标分别表示在图片中的宽度和高度的百分比(0~100之间的实数)
	 * @param mouth_left
	 */
	public void setMouth_left(PointF mouth_left) {
		this.mouth_left = mouth_left;
	}
	
	/**
	 * 相应人脸的右侧嘴角坐标，x & y 坐标分别表示在图片中的宽度和高度的百分比(0~100之间的实数)
	 * @return
	 */
	public PointF getMouth_right() {
		return mouth_right;
	}
	
	/**
	 * 相应人脸的右侧嘴角坐标，x & y 坐标分别表示在图片中的宽度和高度的百分比(0~100之间的实数)
	 * @param mouth_right
	 */
	public void setMouth_right(PointF mouth_right) {
		this.mouth_right = mouth_right;
	}
	
	/**
	 * 相应人脸的鼻尖坐标，x & y 坐标分别表示在图片中的宽度和高度的百分比 (0~100之间的实数)
	 * @return
	 */
	public PointF getNose() {
		return nose;
	}
	/**
	 * 相应人脸的鼻尖坐标，x & y 坐标分别表示在图片中的宽度和高度的百分比 (0~100之间的实数)
	 * @param nose
	 */
	public void setNose(PointF nose) {
		this.nose = nose;
	}
	

	/**
	 * 性别分析结果
	 * @return
	 */
	public Gender getGender() {
		return gender;
	}
	
	/**
	 * 性别分析结果
	 * @param gender
	 */
	public void setGender(Gender gender) {
		this.gender = gender;
	}
	
	/**
	 * 年龄分析结果
	 * @return
	 */
	public Age getAge() {
		return age;
	}
	
	/**
	 * 年龄分析结果
	 * @param age
	 */
	public void setAge(Age age) {
		this.age = age;
	}
	
	/**
	 * 人种分析结果
	 * @return
	 */
	public Race getRace() {
		return race;
	}
	
	/**
	 * 人种分析结果
	 * @param race
	 */
	public void setRace(Race race) {
		this.race = race;
	}
	
	

	/* (non-Javadoc)
	 * @see java.lang.Object#toString()
	 */
	@Override
	public String toString() {
		return "Face [face_id=" + face_id + ", face_data=" + face_data
				+ ", img_id=" + img_id + ", url=" + url + ", width=" + width
				+ ", height=" + height + ", center=" + center + ", eye_left="
				+ eye_left + ", eye_right=" + eye_right + ", mouth_left="
				+ mouth_left + ", mouth_right=" + mouth_right + ", nose="
				+ nose + ", gender=" + gender + ", age=" + age + ", race="
				+ race + ", tag=" + tag + "]";
	}

	/**
	 * 人脸描述
	 * @return
	 */
	public String getTag() {
		return tag;
	}

	/**
	 * 人脸描述
	 * @param tag
	 */
	public void setTag(String tag) {
		this.tag = tag;
	}

	/**
	 * 性别
	 * @author xiaoying
	 */
	public static class Gender implements Serializable {
		/**
		 * 
		 */
		private static final long serialVersionUID = 3604771785466469504L;
		// gender object 包含性别分析结果，value的值为Male/Female, confidence表示置信度
		public String value; //值为Male/Female
		public float confidence; //置信度
		public String getValue() {
			return value;
		}
		public void setValue(String value) {
			this.value = value;
		}
		public float getConfidence() {
			return confidence;
		}
		public void setConfidence(float confidence) {
			this.confidence = confidence;
		}
		@Override
		public String toString() {
			return "Gender [value=" + value + ", confidence=" + confidence
					+ "]";
		}

	}

	/**
	 * 年龄
	 * @author xiaoying
	 */
	public static class Age implements Serializable {
		/**
		 * 
		 */
		private static final long serialVersionUID = 221737413026253122L;
		// age object 包含年龄分析结果，value的值为一个非负整数表示估计的年龄, range表示估计年龄的正负区间
		public int value;	//一个非负整数表示估计的年龄
		public int range;	//估计年龄的正负区间
		public int getValue() {
			return value;
		}
		public void setValue(int value) {
			this.value = value;
		}
		public int getRange() {
			return range;
		}
		public void setRange(int range) {
			this.range = range;
		}
		@Override
		public String toString() {
			return "Age [value=" + value + ", range=" + range + "]";
		}
		
	}

	/**
	 * 种族
	 * @author xiaoying
	 */
	public static class Race implements Serializable {
		/**
		 * 
		 */
		private static final long serialVersionUID = 888019375173484388L;
		// race object 包含人种分析结果，value的值为Asian/White/Black, confidence表示置信度
		public String value; //值为Asian/White/Black
		public float confidence; //置信度
		public String getValue() {
			return value;
		}
		public void setValue(String value) {
			this.value = value;
		}
		public float getConfidence() {
			return confidence;
		}
		public void setConfidence(float confidence) {
			this.confidence = confidence;
		}
		@Override
		public String toString() {
			return "Race [value=" + value + ", confidence=" + confidence + "]";
		}
		
	}
} public class Group implements Serializable {
	/**
	 * 
	 */
	private static final long serialVersionUID = -5604871764437501922L;
	private String group_id;	//相应group的id
	private String group_name;	//相应group的name
	private String tag;	//group相关的tag
	private int person_count;	//Group包含的Person个数
	private List<Person> person;	//属于该group的person信息
	
	/**
	 * 相应group的id
	 * @return
	 */
	public String getGroup_id() {
		return group_id;
	}
	
	/**
	 * 相应group的id
	 * @param group_id
	 */
	public void setGroup_id(String group_id) {
		this.group_id = group_id;
	}
	
	/**
	 * 相应group的name
	 * @return
	 */
	public String getGroup_name() {
		return group_name;
	}
	
	/**
	 * 相应group的name
	 * @param group_name
	 */
	public void setGroup_name(String group_name) {
		this.group_name = group_name;
	}
	
	/**
	 * group相关的tag
	 * @return
	 */
	public String getTag() {
		return tag;
	}
	
	/**
	 * group相关的tag
	 * @param tag
	 */
	public void setTag(String tag) {
		this.tag = tag;
	}
	
	/**
	 * 
	 * @return the person_count
	 */
	public int getPerson_count() {
		return person_count;
	}

	/**
	 * 
	 * @param person_count the person_count to set
	 */
	public void setPerson_count(int person_count) {
		this.person_count = person_count;
	}

	/**
	 * 属于该group的person信息
	 * @return
	 */
	public List<Person> getPerson() {
		return person;
	}
	
	/**
	 * 属于该group的person信息
	 * @param person
	 */
	public void setPerson(List<Person> person) {
		this.person = person;
	}
	
	/* (non-Javadoc)
	 * @see java.lang.Object#toString()
	 */
	@Override
	public String toString() {
		return "Group [group_id=" + group_id + ", group_name=" + group_name
				+ ", tag=" + tag + ", person_count=" + person_count
				+ ", person=" + person + ", getClass()=" + getClass()
				+ ", hashCode()=" + hashCode() + ", toString()="
				+ super.toString() + "]";
	}
} public class Image implements Serializable {
/**
	 * 
	 */
	private static final long serialVersionUID = -4819969692048074149L;
//	img_id TEXT PRIMARY KEY, img TEXT, url TEXT, width INTEGER, height INTEGER
	private String imageId;
	private String img;
	private String url;
	private int width;
	private int height;
	public String getImageId() {
		return imageId;
	}
	public void setImageId(String imageId) {
		this.imageId = imageId;
	}
	public String getImg() {
		return img;
	}
	public void setImg(String img) {
		this.img = img;
	}
	public String getUrl() {
		return url;
	}
	public void setUrl(String url) {
		this.url = url;
	}
	public int getWidth() {
		return width;
	}
	public void setWidth(int width) {
		this.width = width;
	}
	public int getHeight() {
		return height;
	}
	public void setHeight(int height) {
		this.height = height;
	}
	@Override
	public String toString() {
		return "Image [imageId=" + imageId + ", img=" + img + ", url=" + url
				+ ", width=" + width + ", height=" + height + "]";
	}
} public class Person implements Serializable {
	/**
	 * 
	 */
	private static final long serialVersionUID = -7808261630401601077L;
	private String person_name;	//相应person的name
	private String person_id;	//相应person的id
	private String tag;			//person相关的tag
	
	private List<Face> face;	//添加到Person的Face
	
	private List<Group> group;	//已加入的Group
	
	/**
	 * 相应person的name
	 * @return
	 */
	public String getPerson_name() {
		return person_name;
	}
	
	/**
	 * 相应person的name
	 * @param person_name
	 */
	public void setPerson_name(String person_name) {
		this.person_name = person_name;
	}
	
	/**
	 * 相应person的id
	 * @return
	 */
	public String getPerson_id() {
		return person_id;
	}
	
	/**
	 * 相应person的id
	 * @param person_id
	 */
	public void setPerson_id(String person_id) {
		this.person_id = person_id;
	}
	
	/**
	 * person相关的tag
	 * @return
	 */
	public String getTag() {
		return tag;
	}
	
	/**
	 * person相关的tag
	 * @param tag
	 */
	public void setTag(String tag) {
		this.tag = tag;
	}
	
	/**
	 * 添加到Person的Face
	 * 只返回Face的face_id,tag
	 * @return
	 */
	public List<Face> getFace() {
		return face;
	}

	/**
	 * 添加到Person的Face
	 * 只返回Face的face_id,tag
	 * @param face
	 */
	public void setFace(List<Face> face) {
		this.face = face;
	}

	/**
	 * 已加入的Group
	 * 只返回Group的group_id,group_name,tag
	 * @return
	 */
	public List<Group> getGroup() {
		return group;
	}

	/**
	 * 已加入的Group
	 * 只返回Group的group_id,group_name,tag
	 * @param group
	 */
	public void setGroup(List<Group> group) {
		this.group = group;
	}

	@Override
	public String toString() {
		return "PersonGetInfoResp [person_name=" + person_name + ", person_id="
				+ person_id + ", tag=" + tag + ", face=" + face + ", group="
				+ group + "]";
	}
} public class DetectReq extends BaseRequest {
	
	public static final String DETECT_MODE_NORMAL = "normal";
	public static final String DETECT_MODE_ONEFACE = "oneface";
	
	public static final String ATTRIBUTE_ALL = "all";
	public static final String ATTRIBUTE_NONE = "none";
	public static final String ATTRIBUTE_GENDER = "gender";
	public static final String ATTRIBUTE_AGE = "age";
	public static final String ATTRIBUTE_RACE = "race";
	
	private String url;	//url 或 img[POST]	待检测图片的URL 或者 通过POST方法上传的二进制数据，原始图片大小需要小于3M
	private File img;
	//以下是可选
	private String mode;	//检测模式可以是normal(默认) 或者 oneface 。在oneface模式中，检测器仅找出图片中最大的一张脸。
	private String attribute;	//可以是 all(默认) 或者 none或者由逗号分割的属性列表。目前支持的属性包括：gender, age, race
	private String tag;	//可以为图片中检测出的每一张Face指定一个不包含^@,&=*'"等非法字符且不超过255字节的字符串作为tag，tag信息可以通过 /info/get_face 查询
	private Boolean async = false;	//如果置为true，该API将会以异步方式被调用；也就是立即返回一个session id，稍后可通过/info/get_session查询结果。默认值为false。

	public DetectReq() {
		
	}
	
	public DetectReq(String url) {
		setUrl(url);
	}
	
	public DetectReq(File img) {
		setImg(img);
	}

	/**
	 * 待检测图片的URL
	 * @return
	 */
	public String getUrl() {
		return url;
	}

	/**
	 * 待检测图片的URL,
	 * 与setImg(File img)两者只能选其一
	 */
	public void setUrl(String url) {
		this.url = url;
		this.img = null;
	}

	/**
	 * 通过POST方法上传的二进制数据(图片文件File)
	 * @return
	 */
	public File getImg() {
		return img;
	}

	/**
	 * 通过POST方法上传的二进制数据(图片文件File),原始图片大小需要小于3M
	 * 与setUrl(String url)两者只能选其一
	 * @param img
	 */
	public void setImg(File img) {
		this.img = img;
		this.url = null;
	}

	/**
	 * (可选)
	 * 检测模式可以是normal(默认) 或者 oneface 。在oneface模式中，检测器仅找出图片中最大的一张脸。
	 * @return
	 */
	public String getMode() {
		return mode;
	}

	/**
	 * (可选)
	 * 检测模式可以是normal(默认) 或者 oneface 。在oneface模式中，检测器仅找出图片中最大的一张脸。
	 * @param mode
	 */
	public void setMode(String mode) {
		this.mode = mode;
	}

	/**
	 * (可选)
	 * 可以是 all(默认) 或者 none或者由逗号分割的属性列表。目前支持的属性包括：gender, age, race
	 * @return
	 */
	public String getAttribute() {
		return attribute;
	}

	/**
	 * (可选)
	 * 可以是 all(默认) 或者 none或者由逗号分割的属性列表。目前支持的属性包括：gender, age, race
	 * @param attribute
	 */
	public void setAttribute(String attribute) {
		this.attribute = attribute;
	}

	/**
	 * (可选)
	 * 可以为图片中检测出的每一张Face指定一个不包含^@,&=*'"等非法字符且不超过255字节的字符串作为tag
	 * @return
	 */
	public String getTag() {
		return tag;
	}

	/**
	 * (可选)
	 * 可以为图片中检测出的每一张Face指定一个不包含^@,&=*'"等非法字符且不超过255字节的字符串作为tag
	 */
	public void setTag(String tag) {
		this.tag = tag;
	}

	/**
	 * (可选)
	 * 如果置为true，该API将会以异步方式被调用
	 * @return
	 */
	public Boolean isAsync() {
		return async;
	}

	/**
	 * (可选)
	 * 如果置为true，该API将会以异步方式被调用
	 * @param async
	 */
	public void setAsync(Boolean async) {
		this.async = async;
	}

	@Override
	public String toString() {
		return "DetectFaceReq [url=" + url + ", img=" + img + ", mode=" + mode
				+ ", attribute=" + attribute + ", tag=" + tag + ", async="
				+ async + "]";
	}
} public class PersonAddFaceReq extends BaseRequest {
	
	private String person_name;//相应Person的name
	private String person_id;	//相应Person的id
 	private String face_id;	//	一组用逗号分隔的face_id,表示将这些Face加入到相应Person中。

	public PersonAddFaceReq() {
		
	}
	
	public PersonAddFaceReq(String person, boolean isId) {
		if(isId) {
			setPerson_id(person);
		} else {
			setPerson_name(person);
		}
	}

	/**
	 * 相应Person的name
	 * @return
	 */
	public String getPerson_name() {
		return person_name;
	}

	/**
	 * 相应Person的name
	 * 与setPerson_id(String person_id)只能选其一
	 * @param person_name
	 */
	public void setPerson_name(String person_name) {
		this.person_name = person_name;
	}

	/**
	 * 相应Person的id
	 * @return
	 */
	public String getPerson_id() {
		return person_id;
	}

	/**
	 * 相应Person的id
	 * 与setPerson_name(String person_name)只能选其一
	 * @param person_id
	 */
	public void setPerson_id(String person_id) {
		this.person_id = person_id;
	}

	/**
	 * 一组用逗号分隔的face_id,表示将这些Face加入到相应Person中。
	 * @return
	 */
	public String getFace_id() {
		return face_id;
	}

	/**
	 * 一组用逗号分隔的face_id,表示将这些Face加入到相应Person中。
	 * @param face_id
	 */
	public void setFace_id(String face_id) {
		this.face_id = face_id;
	}

	@Override
	public String toString() {
		return "PersonAddFaceReq [person_name=" + person_name + ", person_id="
				+ person_id + ", face_id=" + face_id + "]";
	}
	
} public class IdentityReq extends BaseRequest {
	private String group_id; //识别候选人组成的Group id
	private String group_name;	//识别候选人组成的Group name
//	可选	
	private String url;	//待识别图片的URL
	private File img;	// 待识别图片通过POST方法上传的二进制数据
	private String mode;	//检测模式可以是normal(默认) 或者 oneface 。在oneface模式中，检测器仅找出图片中最大的一张脸。仅当给出了url或img时，本选项有效。
	private String key_face_id;	//开发者也可以指定一个face_id的列表来表明对这些face进行识别。可以设置此参数key_face_id为一个逗号隔开的face_id列表。
	private Boolean async;	//如果置为true，该API将会以异步方式被调用；也就是立即返回一个session id，稍后可通过/info/get_session查询结果。默认值为false。
	
	public IdentityReq() {
		
	}
	
	public IdentityReq(String group, boolean isId) {
		if(isId) {
			setGroup_id(group);
		} else {
			setGroup_name(group);
		}
	}
	
	/**
	 * 识别候选人组成的Group id
	 * @return the group_id
	 */
	public String getGroup_id() {
		return group_id;
	}
	/**
	 * 识别候选人组成的Group id
	 * 与setGroup_name(String group_name)只能选其一
	 * @param group_id the group_id to set
	 */
	public void setGroup_id(String group_id) {
		this.group_id = group_id;
	}
	/**
	 * 识别候选人组成的Group name
	 * @return the group_name
	 */
	public String getGroup_name() {
		return group_name;
	}
	/**
	 * 识别候选人组成的Group name
	 * 与setGroup_id(String group_id)只能选其一
	 * @param group_name the group_name to set
	 */
	public void setGroup_name(String group_name) {
		this.group_name = group_name;
	}
	/**
	 * (可选)
	 * 待识别图片的URL
	 * @return the url
	 */
	public String getUrl() {
		return url;
	}
	/**
	 * (可选)
	 * 待识别图片的URL
	 * 与setImg(File img)只能选其一
	 * @param url the url to set
	 */
	public void setUrl(String url) {
		this.url = url;
	}
	/**
	 * (可选)
	 * 待识别图片通过POST方法上传的二进制数据
	 * @return the img
	 */
	public File getImg() {
		return img;
	}
	/**
	 * (可选)
	 * 待识别图片通过POST方法上传的二进制数据
	 * 与setUrl(String url)只能选其一
	 * @param img the img to set
	 */
	public void setImg(File img) {
		this.img = img;
	}
	/**
	 * (可选)
	 * 检测模式可以是normal(默认) 或者 oneface 。在oneface模式中，检测器仅找出图片中最大的一张脸。仅当给出了url或img时，本选项有效。
	 * @return the mode
	 */
	public String getMode() {
		return mode;
	}
	/**
	 * (可选)
	 * 检测模式可以是normal(默认) 或者 oneface 。在oneface模式中，检测器仅找出图片中最大的一张脸。仅当给出了url或img时，本选项有效。
	 * @param mode the mode to set
	 */
	public void setMode(String mode) {
		this.mode = mode;
	}
	/**
	 * (可选)
	 * 开发者也可以指定一个face_id的列表来表明对这些face进行识别。可以设置此参数key_face_id为一个逗号隔开的face_id列表。
	 * @return the key_face_id
	 */
	public String getKey_face_id() {
		return key_face_id;
	}
	/**
	 * (可选)
	 * 开发者也可以指定一个face_id的列表来表明对这些face进行识别。可以设置此参数key_face_id为一个逗号隔开的face_id列表。
	 * @param key_face_id the key_face_id to set
	 */
	public void setKey_face_id(String key_face_id) {
		this.key_face_id = key_face_id;
	}
	/**
	 * (可选)
	 * 如果置为true，该API将会以异步方式被调用；也就是立即返回一个session id，稍后可通过/info/get_session查询结果。默认值为false。
	 * @return the async
	 */
	public Boolean getAsync() {
		return async;
	}
	/**
	 * (可选)
	 * 如果置为true，该API将会以异步方式被调用；也就是立即返回一个session id，稍后可通过/info/get_session查询结果。默认值为false。
	 * @param async the async to set
	 */
	public void setAsync(Boolean async) {
		this.async = async;
	}
	
	
} public class TrainIdentityReq extends BaseRequest {
	private String group_id;	//识别候选人组成的Group id
	private String group_name;	//识别候选人组成的Group name
	
	public TrainIdentityReq() {
		
	}
	
	public TrainIdentityReq(String group, boolean isId) {
		if(isId) {
			setGroup_id(group);
		} else {
			setGroup_name(group);
		}
	}
	
	/**
	 * 识别候选人组成的Group id
	 * @return the group_id
	 */
	public String getGroup_id() {
		return group_id;
	}
	/**
	 * 识别候选人组成的Group id
	 * 与setGroup_id(String group_id)只能选其一
	 * @param group_id the group_id to set
	 */
	public void setGroup_id(String group_id) {
		this.group_id = group_id;
		this.group_name = null;
	}
	/**
	 * 识别候选人组成的Group name
	 * @return the group_name
	 */
	public String getGroup_name() {
		return group_name;
	}
	/**
	 * 识别候选人组成的Group name
	 * 与setGroup_name(String group_name)只能选其一
	 * @param group_name the group_name to set
	 */
	public void setGroup_name(String group_name) {
		this.group_name = group_name;
		this.group_id = null;
	}
	/* (non-Javadoc)
	 * @see java.lang.Object#toString()
	 */
	@Override
	public String toString() {
		return "TrainIdentityReq [group_id=" + group_id + ", group_name="
				+ group_name + "]";
	}
	
} public class DetectResp extends BaseResponse {
	private String session_id;
	private String img_id;
	private String url;
	private int img_height;
	private int img_width;
	private List<Face> face;
	public String getSession_id() {
		return session_id;
	}
	public void setSession_id(String session_id) {
		this.session_id = session_id;
	}
	public String getImg_id() {
		return img_id;
	}
	public void setImg_id(String img_id) {
		this.img_id = img_id;
	}
	public String getUrl() {
		return url;
	}
	public void setUrl(String url) {
		this.url = url;
	}
	public int getImg_height() {
		return img_height;
	}
	public void setImg_height(int img_height) {
		this.img_height = img_height;
	}
	public int getImg_width() {
		return img_width;
	}
	public void setImg_width(int img_width) {
		this.img_width = img_width;
	}
	public List<Face> getFace() {
		return face;
	}
	public void setFace(List<Face> face) {
		this.face = face;
	}
	
	@Override
	public String toString() {
		return "DetectResp [session_id=" + session_id + ", img_id="
				+ img_id + ", url=" + url + ", img_height=" + img_height
				+ ", img_width=" + img_width + ", face=" + face + ", error="
				+ error + ", error_code=" + error_code + "]";
	}
} public class PersonAddFaceResp extends BaseResponse {
	private int added; //成功加入的face数量
	private boolean success; //表示操作是否成功
	
	/**
	 * 成功加入的face数量
	 * @return
	 */
	public int getAdded() {
		return added;
	}
	
	/**
	 * 成功加入的face数量
	 * @param added
	 */
	public void setAdded(int added) {
		this.added = added;
	}
	
	/**
	 * 表示操作是否成功
	 * @return
	 */
	public boolean isSuccess() {
		return success;
	}
	
	/**
	 * 表示操作是否成功
	 * @param success
	 */
	public void setSuccess(boolean success) {
		this.success = success;
	}
	/* (non-Javadoc)
	 * @see java.lang.Object#toString()
	 */
	@Override
	public String toString() {
		return "PersonAddFaceResp [added=" + added + ", success=" + success
				+ ", error=" + error + ", error_code=" + error_code + "]";
	}
	
} public class IdentifyResp extends BaseResponse {

	private String session_id;	//相应请求的session标识符，可用于结果查询
	private List<IdentifyFace> face; //人脸的列表
	
	/**
	 * 相应请求的session标识符，可用于结果查询
	 * @return the session_id
	 */
	public String getSession_id() {
		return session_id;
	}

	/**
	 * 相应请求的session标识符，可用于结果查询
	 * @param session_id the session_id to set
	 */
	public void setSession_id(String session_id) {
		this.session_id = session_id;
	}

	/**
	 * 相应请求的session标识符，可用于结果查询
	 * @return the face
	 */
	public List<IdentifyFace> getFace() {
		return face;
	}

	/**
	 * 相应请求的session标识符，可用于结果查询
	 * @param face the face to set
	 */
	public void setFace(List<IdentifyFace> face) {
		this.face = face;
	}
	
	
	

	/* (non-Javadoc)
	 * @see java.lang.Object#toString()
	 */
	@Override
	public String toString() {
		return "IdentityResp [session_id=" + session_id + ", face=" + face
				+ ", error=" + error + ", error_code=" + error_code + "]";
	}




	/**
	 * 功能：人脸识别返回的人脸信息实体类
	 * @author xiaoying
	 *
	 */
	public static class IdentifyFace {
		private Face face;	//人脸信息
		private List<Candidate> candidates;	//识别结果。candidates包含不超过3个人，包含相应person信息与相应的置信度
		
		/**
		 * 人脸信息
		 * @return
		 */
		public Face getFace() {
			return face;
		}
		
		/**
		 * 人脸信息
		 * @param face
		 */
		public void setFace(Face face) {
			this.face = face;
		}

		/**
		 * 识别结果。candidates包含不超过3个人，包含相应person信息与相应的置信度
		 * @return the candidates
		 */
		public List<Candidate> getCandidates() {
			return candidates;
		}
		/**
		 * 识别结果。candidates包含不超过3个人，包含相应person信息与相应的置信度
		 * @param candidates the candidates to set
		 */
		public void setCandidates(List<Candidate> candidates) {
			this.candidates = candidates;
		}

		@Override
		public String toString() {
			return "IdentityFace [face=" + face + ", candidates=" + candidates
					+ "]";
		}
		
	}
	
	/**
	 * 功能：识别结果实体类
	 * @author xiaoying
	 *
	 */
	public static class Candidate implements Serializable {
		/**
		 * 
		 */
		private static final long serialVersionUID = -178216610187842006L;
		private String person_id;	//person的id
		private String person_name;	//person的name
		private String tag;	//person的tag
		private float confidence;	//匹配的置信度
		/**
		 * person的id
		 * @return the person_id
		 */
		public String getPerson_id() {
			return person_id;
		}
		/**
		 * person的id
		 * @param person_id the person_id to set
		 */
		public void setPerson_id(String person_id) {
			this.person_id = person_id;
		}
		/**
		 * person的name
		 * @return the person_name
		 */
		public String getPerson_name() {
			return person_name;
		}
		/**
		 * person的name
		 * @param person_name the person_name to set
		 */
		public void setPerson_name(String person_name) {
			this.person_name = person_name;
		}
		/**
		 * person的tag
		 * @return the tag
		 */
		public String getTag() {
			return tag;
		}
		/**
		 * person的tag
		 * @param tag the tag to set
		 */
		public void setTag(String tag) {
			this.tag = tag;
		}
		/**
		 * 匹配的置信度
		 * @return the confidence
		 */
		public float getConfidence() {
			return confidence;
		}
		/**
		 * 匹配的置信度
		 * @param confidence the confidence to set
		 */
		public void setConfidence(float confidence) {
			this.confidence = confidence;
		}
		/* (non-Javadoc)
		 * @see java.lang.Object#toString()
		 */
		@Override
		public String toString() {
			return "Candidate [person_id=" + person_id + ", person_name="
					+ person_name + ", tag=" + tag + ", confidence="
					+ confidence + "]";
		}
	}
} public static class Candidate implements Serializable {
	/**
	 * 
	 */
	private static final long serialVersionUID = -178216610187842006L;
	private String person_id;	//person的id
	private String person_name;	//person的name
	private String tag;	//person的tag
	private float confidence;	//匹配的置信度
	/**
	 * person的id
	 * @return the person_id
	 */
	public String getPerson_id() {
		return person_id;
	}
	/**
	 * person的id
	 * @param person_id the person_id to set
	 */
	public void setPerson_id(String person_id) {
		this.person_id = person_id;
	}
	/**
	 * person的name
	 * @return the person_name
	 */
	public String getPerson_name() {
		return person_name;
	}
	/**
	 * person的name
	 * @param person_name the person_name to set
	 */
	public void setPerson_name(String person_name) {
		this.person_name = person_name;
	}
	/**
	 * person的tag
	 * @return the tag
	 */
	public String getTag() {
		return tag;
	}
	/**
	 * person的tag
	 * @param tag the tag to set
	 */
	public void setTag(String tag) {
		this.tag = tag;
	}
	/**
	 * 匹配的置信度
	 * @return the confidence
	 */
	public float getConfidence() {
		return confidence;
	}
	/**
	 * 匹配的置信度
	 * @param confidence the confidence to set
	 */
	public void setConfidence(float confidence) {
		this.confidence = confidence;
	}
	/* (non-Javadoc)
	 * @see java.lang.Object#toString()
	 */
	@Override
	public String toString() {
		return "Candidate [person_id=" + person_id + ", person_name="
				+ person_name + ", tag=" + tag + ", confidence="
				+ confidence + "]";
	}
} public class TrainIdentityResp extends BaseResponse {
	private String session_id;	//请求session_id

	/**
	 * //请求session_id
	 * @return the session_id
	 */
	public String getSession_id() {
		return session_id;
	}

	/**
	 * //请求session_id
	 * @param session_id the session_id to set
	 */
	public void setSession_id(String session_id) {
		this.session_id = session_id;
	}

	/* (non-Javadoc)
	 * @see java.lang.Object#toString()
	 */
	@Override
	public String toString() {
		return "TrainIdentityResp [session_id=" + session_id + ", error="
				+ error + ", error_code=" + error_code + "]";
	}
	
} public class FaceService extends BaseService {
	
	public FaceService(Client client) {
		super(client);
	}

	/**
	 * 人脸检测
	 * @param body 人脸检测请求体
	 * @return
	 * @throws ClientProtocolException
	 * @throws IOException
	 * @throws JSONException 
	 * @throws ParseException 
	 */
	public DetectResp detect(DetectReq body) throws ClientProtocolException, IOException, ParseException, JSONException {
		if(StringUtil.isEmpty(body.getUrl()) && body.getImg() == null) {
			throw new IllegalArgumentException("Must set a image url or image file");
		}
		if(body.getImg() != null && !body.getImg().exists()) {
			throw new FileNotFoundException("File " + body.getImg().getPath() + "not found.");
		}
		Map<String, Object> params = new HashMap<String, Object>();
		params.put("api_key", client.getAppKey());
		params.put("api_secret", client.getAppSecret());
		params.put("img", body.getImg());
		params.put("url", body.getUrl());
		params.put("mode", body.getMode());
		params.put("attribute", body.getAttribute());
		params.put("tag", body.getTag());
		params.put("async", body.isAsync());
		return getResponse(params);
	}
	
	private DetectResp getResponse(Map<String, Object> params) throws ClientProtocolException, IOException, ParseException, JSONException {
		HttpResponse resp = HttpUtil.doPost(UrlConfig.PATH_DETECT, params);
		JSONObject json = new JSONObject(EntityUtils.toString(resp.getEntity()));
		Log.i(json.toString());
		DetectResp result = new DetectResp();
		result.setSession_id(json.optString("session_id"));
		result.setImg_id(json.optString("img_id"));
		result.setUrl(json.optString("url"));
		result.setImg_width(json.optInt("img_width"));
		result.setImg_height(json.optInt("img_height"));
		JSONArray faceArray = json.optJSONArray("face");
		List<Face> faces = new ArrayList<Face>();
		if(faceArray != null) {
			JSONObject faceObj = null;
			Face face = null;
			for(int i = 0; i < faceArray.length(); i++) {
				faceObj = faceArray.optJSONObject(i);
				face = new Face();
				face.setFace_id(faceObj.optString("face_id"));
				face.setImg_id(result.getImg_id());
				face.setUrl(result.getUrl());
				face.setTag(faceObj.optString("tag"));
				setAttribute(faceObj.optJSONObject("attribute"), face);
				setPosition(faceObj.optJSONObject("position"), face);
				faces.add(face);
			}
		}
		result.setFace(faces);
		result.setError(json.optString("error"));
		result.setError_code(json.optInt("error_code", RespConfig.RESP_OK));
		return result;
	}
	
	public static void setAttribute(JSONObject attributeObj, Face face) {
		JSONObject ageObj = attributeObj.optJSONObject("age");
		Face.Age age = new Face.Age();
		age.setValue(ageObj.optInt("value"));
		age.setRange(ageObj.optInt("range"));
		face.setAge(age);
		JSONObject genderObj = attributeObj.optJSONObject("gender");
		Face.Gender gender = new Face.Gender();
		gender.setValue(genderObj.optString("value"));
		gender.setConfidence((float)genderObj.optDouble("confidence"));
		face.setGender(gender);
		JSONObject raceObj = attributeObj.optJSONObject("race");
		Face.Race race = new Face.Race();
		race.setValue(raceObj.optString("value"));
		race.setConfidence((float)raceObj.optDouble("confidence"));
		face.setRace(race);
	}
	
	/**
	 * 从JSONObject解析Face的position信息
	 * @param positionObj
	 * @return
	 */
	public static void setPosition(JSONObject positionObj, Face face) {
		JSONObject centerObj = positionObj.optJSONObject("center");
		PointF center = new PointF((float)centerObj.optDouble("x"), (float)centerObj.optDouble("y"));
		face.setCenter(center);
		JSONObject eyeLeftObj = positionObj.optJSONObject("eye_left");
		PointF eyeLeft = new PointF((float)eyeLeftObj.optDouble("x"), (float)eyeLeftObj.optDouble("y"));
		face.setEye_left(eyeLeft);
		JSONObject eyeRightObj = positionObj.optJSONObject("eye_right");
		PointF eyeRight = new PointF((float)eyeRightObj.optDouble("x"), (float)eyeRightObj.optDouble("y"));
		face.setEye_right(eyeRight);
		JSONObject nosehtObj = positionObj.optJSONObject("nose");
		PointF nose = new PointF((float)nosehtObj.optDouble("x"), (float)nosehtObj.optDouble("y"));
		face.setNose(nose);
		JSONObject mouthLeftObj = positionObj.optJSONObject("mouth_left");
		PointF mouthLeft = new PointF((float)mouthLeftObj.optDouble("x"), (float)mouthLeftObj.optDouble("y"));
		face.setMouth_left(mouthLeft);
		JSONObject mouthRightObj = positionObj.optJSONObject("mouth_right");
		PointF mouthRight = new PointF((float)mouthRightObj.optDouble("x"), (float)mouthRightObj.optDouble("y"));
		face.setMouth_right(mouthRight);
		face.setWidth((float)positionObj.optDouble("width"));
		face.setHeight((float)positionObj.optDouble("height"));
	}
} public class InfoService extends BaseService {

	/**
	 * @param client
	 */
	public InfoService(Client client) {
		super(client);
	}
	
	/**
	 * 获取一张image的信息, 包括其中包含的face等信息
	 * @param body
	 * @return
	 * @throws ClientProtocolException
	 * @throws IOException
	 * @throws JSONException 
	 * @throws ParseException 
	 */
	public InfoGetImageResp getImage(InfoGetImageReq body) throws ClientProtocolException, IOException, ParseException, JSONException {
		if(StringUtil.isEmpty(body.getImg_id())) {
			throw new IllegalArgumentException("img_id should not be null");
		}
		Map<String, Object> params = new HashMap<String, Object>();
		params.put("api_key", client.getAppKey());
		params.put("api_secret", client.getAppSecret());
		params.put("img_id", body.getImg_id());
		
		HttpResponse resp = HttpUtil.doPost(UrlConfig.PATH_INFO_GET_IMAGE, params);
		JSONObject json = new JSONObject(EntityUtils.toString(resp.getEntity()));
		Log.i(json.toString());
		InfoGetImageResp result = new InfoGetImageResp();
		result.setImg_id(json.optString("img_id"));
		result.setUrl(json.optString("url"));
		result.setFace(getFaces(json.optJSONArray("face")));
		result.setError(json.optString("error"));
		result.setError_code(json.optInt("error_code", RespConfig.RESP_OK));
		return result;
	}

	/**
	 * 给定一组Face，返回相应的信息(包括源图片, 相关的person等等)。
	 * @param body
	 * @return
	 * @throws ClientProtocolException
	 * @throws IOException
	 * @throws JSONException 
	 * @throws ParseException 
	 */
	public InfoGetFaceResp getFace(InfoGetFaceReq body) throws ClientProtocolException, IOException, ParseException, JSONException {
		if(StringUtil.isEmpty(body.getFace_id())) {
			throw new IllegalArgumentException("img_id should not be null");
		}
		Map<String, Object> params = new HashMap<String, Object>();
		params.put("api_key", client.getAppKey());
		params.put("api_secret", client.getAppSecret());
		params.put("face_id", body.getFace_id());
		
		HttpResponse resp = HttpUtil.doPost(UrlConfig.PATH_INFO_GET_FACE, params);
		JSONObject json = new JSONObject(EntityUtils.toString(resp.getEntity()));
		Log.i(json.toString());
		InfoGetFaceResp result = new InfoGetFaceResp();
		result.setFace_info(getFaceInfo(json.optJSONArray("face_info")));
		result.setError(json.optString("error"));
		result.setError_code(json.optInt("error_code", RespConfig.RESP_OK));
		return result;
	}

	/**
	 * 返回该App中的所有Person
	 * @return
	 * @throws ClientProtocolException
	 * @throws IOException
	 * @throws JSONException 
	 * @throws ParseException 
	 */
	public InfoGetPersonListResp getPersonList() throws ClientProtocolException, IOException, ParseException, JSONException {
		Map<String, Object> params = new HashMap<String, Object>();
		params.put("api_key", client.getAppKey());
		params.put("api_secret", client.getAppSecret());
		
		HttpResponse resp = HttpUtil.doPost(UrlConfig.PATH_INFO_GET_PERSON_LIST, params);
		JSONObject json = new JSONObject(EntityUtils.toString(resp.getEntity()));
		Log.i(json.toString());
		InfoGetPersonListResp result = new InfoGetPersonListResp();
		result.setPerson(getPersons(json.optJSONArray("person")));
		result.setError(json.optString("error"));
		result.setError_code(json.optInt("error_code", RespConfig.RESP_OK));
		return result;
	}

	/**
	 * 返回该App中的所有faceset
	 * @return
	 * @throws ClientProtocolException
	 * @throws IOException
	 * @throws JSONException 
	 * @throws ParseException 
	 */
	public InfoGetFacesetListResp getFacsetList() throws ClientProtocolException, IOException, ParseException, JSONException {
		Map<String, Object> params = new HashMap<String, Object>();
		params.put("api_key", client.getAppKey());
		params.put("api_secret", client.getAppSecret());
		
		HttpResponse resp = HttpUtil.doPost(UrlConfig.PATH_INFO_GET_FACESET_LIST, params);
		JSONObject json = new JSONObject(EntityUtils.toString(resp.getEntity()));
		Log.i(json.toString());
		InfoGetFacesetListResp result = new InfoGetFacesetListResp();
		result.setFaceset(getFacesets(json.optJSONArray("faceset")));
		result.setError(json.optString("error"));
		result.setError_code(json.optInt("error_code", RespConfig.RESP_OK));
		return result;
	}
	
	/**
	 * 返回这个App中的所有Group
	 * @return
	 * @throws ClientProtocolException
	 * @throws IOException
	 * @throws JSONException 
	 * @throws ParseException 
	 */
	public InfoGetGroupListResp getGroupList() throws ClientProtocolException, IOException, ParseException, JSONException {
		Map<String, Object> params = new HashMap<String, Object>();
		params.put("api_key", client.getAppKey());
		params.put("api_secret", client.getAppSecret());
		
		HttpResponse resp = HttpUtil.doPost(UrlConfig.PATH_INFO_GET_GROUP_LIST, params);
		JSONObject json = new JSONObject(EntityUtils.toString(resp.getEntity()));
		Log.i(json.toString());
		InfoGetGroupListResp result = new InfoGetGroupListResp();
		result.setGroup(getGroups(json.optJSONArray("group")));
		result.setError(json.optString("error"));
		result.setError_code(json.optInt("error_code", RespConfig.RESP_OK));
		return result;
	}

	/**
	 * 查获取session相关状态和结果
	 *
	 * 可能的status：INQUEUE(队列中), SUCC(成功) 和FAILED(失败)
	 * 当status是SUCC时，返回结果中还包含session对应的结果
	 * 所有session都将在计算完成72小时之后过期，并被自动清除。
	 * status返回值为SUCC仅表示成功取得运行结果，实际任务成功与否请根据result内容判断
	 * @param sessionId
	 * @return
	 * @throws ClientProtocolException
	 * @throws IOException
	 * @throws JSONException 
	 * @throws ParseException 
	 */
	public InfoGetSessionResp getSesson(String sessionId) throws ClientProtocolException, IOException, ParseException, JSONException {
		Map<String, Object> params = new HashMap<String, Object>();
		params.put("api_key", client.getAppKey());
		params.put("api_secret", client.getAppSecret());
		params.put("session_id", sessionId);
		
		HttpResponse resp = HttpUtil.doPost(UrlConfig.PATH_INFO_GET_SESSION, params);
		JSONObject json = new JSONObject(EntityUtils.toString(resp.getEntity()));
		Log.i(json.toString());
		InfoGetSessionResp result = new InfoGetSessionResp();
		result.setSession_id(json.optString("session_id"));
		result.setCreate_time(json.optInt("create_time"));
		result.setFinish_time(json.optInt("finish_time"));
		result.setStatus(json.optString("status"));
		result.setResult(json.optJSONObject("result"));
		result.setError(json.optString("error"));
		result.setError_code(json.optInt("error_code", RespConfig.RESP_OK));
		return result;
	}

	/**
	 * 查询Quota使用情况简报
	 * @return
	 * @throws ClientProtocolException
	 * @throws IOException
	 * @throws JSONException 
	 * @throws ParseException 
	 */
	public InfoGetQuotaResp getQuota() throws ClientProtocolException, IOException, ParseException, JSONException {
		Map<String, Object> params = new HashMap<String, Object>();
		params.put("api_key", client.getAppKey());
		params.put("api_secret", client.getAppSecret());
		
		HttpResponse resp = HttpUtil.doPost(UrlConfig.PATH_INFO_GET_QUOTA, params);
		JSONObject json = new JSONObject(EntityUtils.toString(resp.getEntity()));
		Log.i(json.toString());
		InfoGetQuotaResp result = new InfoGetQuotaResp();
		result.setTotal(json.optInt("total"));
		result.setUsed(json.optInt("used"));
		result.setExceed(json.optInt("exceed"));
		result.setError(json.optString("error"));
		result.setError_code(json.optInt("error_code", RespConfig.RESP_OK));
		return result;
	}

	/**
	 * 获取该App相关的信息
	 * @return
	 * @throws ClientProtocolException
	 * @throws IOException
	 * @throws JSONException 
	 * @throws ParseException 
	 */
	public InfoGetAppResp getApp() throws ClientProtocolException, IOException, ParseException, JSONException {
		Map<String, Object> params = new HashMap<String, Object>();
		params.put("api_key", client.getAppKey());
		params.put("api_secret", client.getAppSecret());
		
		HttpResponse resp = HttpUtil.doPost(UrlConfig.PATH_INFO_GET_APP, params);
		JSONObject json = new JSONObject(EntityUtils.toString(resp.getEntity()));
		Log.i(json.toString());
		InfoGetAppResp result = new InfoGetAppResp();
		result.setName(json.optString("name"));
		result.setDescription(json.optString("description"));
		result.setError(json.optString("error"));
		result.setError_code(json.optInt("error_code", RespConfig.RESP_OK));
		return result;
	}
	
	
	/**
	 * 解析JSONArray中的FaceInfo
	 * @param faceInfoArray
	 * @return
	 */
	private List<FaceInfo> getFaceInfo(JSONArray faceInfoArray) {
		List<FaceInfo> faceInfos = new ArrayList<FaceInfo>();
		if(faceInfoArray != null) {
			JSONObject faceInfoObj = null;
			FaceInfo faceInfo = null;
			Face face = null;
			for(int i = 0; i < faceInfoArray.length(); i++) {
				faceInfoObj = faceInfoArray.optJSONObject(i);
				faceInfo = new FaceInfo();
				face = new Face();
//				faceInfo.setFace_id(faceInfoObj.optString("face_id"));
//				faceInfo.setImg_id(faceInfoObj.optString("img_id"));
//				faceInfo.setUrl(faceInfoObj.optString("url"));
//				faceInfo.setTag(faceInfoObj.optString("tag"));
				face.setFace_id(faceInfoObj.optString("face_id"));
				face.setImg_id(faceInfoObj.optString("img_id"));
				face.setUrl(faceInfoObj.optString("url"));
				face.setTag(faceInfoObj.optString("tag"));
				FaceService.setAttribute(faceInfoObj.optJSONObject("attribute"), face);
				FaceService.setPosition(faceInfoObj.optJSONObject("position"), face);
//				faceInfo.setAttribute(getAttribute(faceInfoObj.optJSONObject("attribute")));
//				faceInfo.setPosition(FaceService.getPosition(faceInfoObj.optJSONObject("position")));
				faceInfo.setPerson(getPersons(faceInfoObj.optJSONArray("person")));
				faceInfo.setFaceset(getFacesets(faceInfoObj.optJSONArray("faceset")));
				faceInfos.add(faceInfo);
			}
		}
		return faceInfos;
	}
	
	/**
	 * 解析JSONArray中的Face
	 * @param faceArray
	 * @return
	 */
	private List<Face> getFaces(JSONArray faceArray) {
		List<Face> faces = new ArrayList<Face>();
		if(faceArray != null) {
			JSONObject faceObj = null;
			Face face = null;
			for(int i = 0; i < faceArray.length(); i++) {
				faceObj = faceArray.optJSONObject(i);
				face = new Face();
				face.setFace_id(faceObj.optString("face_id"));
				face.setTag(faceObj.optString("tag"));
				FaceService.setPosition(faceObj.optJSONObject("position"), face);
//				face.setPosition(FaceService.getPosition(faceObj.optJSONObject("position")));
				faces.add(face);
			}
		}
		return faces;
	}

	/**
	 * 解析JSONArray中的Faceset
	 * @param facesetArray
	 * @return
	 */
	private List<Faceset> getFacesets(JSONArray facesetArray) {
		List<Faceset> facesets = new ArrayList<Faceset>();
		if(facesetArray != null) {
			JSONObject facesetObj = null;
			Faceset faceset = null;
			for(int i = 0; i < facesetArray.length(); i++) {
				facesetObj = facesetArray.optJSONObject(i);
				faceset = new Faceset();
				faceset.setFaceset_id(facesetObj.optString("faceset_id"));
				faceset.setFaceset_name(facesetObj.optString("faceset_name"));
				faceset.setTag(facesetObj.optString("tag"));
				facesets.add(faceset);
			}
		}
		return facesets;
	}
	
	/**
	 * 解析JSONArray中的Person
	 * @param personArray
	 * @return
	 */
	private List<Person> getPersons(JSONArray personArray) {
		List<Person> persons = new ArrayList<Person>();
		if(personArray != null) {
			JSONObject personObj = null;
			Person person = null;
			for(int i = 0; i < personArray.length(); i++) {
				personObj = personArray.optJSONObject(i);
				person = new Person();
				person.setPerson_id(personObj.optString("person_id"));
				person.setPerson_name(personObj.optString("person_name"));
				person.setTag(personObj.optString("tag"));
				persons.add(person);
		}
		}
		return persons;
	}

	/**
	 * 解析JSONArray中的Group
	 * @param groupArray
	 * @return
	 */
	private List<Group> getGroups(JSONArray groupArray) {
		List<Group> groups = new ArrayList<Group>();
		if(groupArray != null) {
			JSONObject groupObj = null;
			Group group = null;
			for(int i = 0; i < groupArray.length(); i++) {
				groupObj = groupArray.optJSONObject(i);
				group = new Group();
				group.setGroup_id(groupObj.optString("group_id"));
				group.setGroup_name(groupObj.optString("group_name"));
				group.setTag(groupObj.optString("tag"));
				groups.add(group);
			}
		}
		return groups;
	}

//	/**
//	 * 解析JSONArray中的Face.Attribute
//	 * @param attributeObj
//	 * @return
//	 */
//	private Face.Attribute getAttribute(JSONObject attributeObj) {
//		Face.Attribute attribute = new Face.Attribute();
//		JSONObject ageObj = attributeObj.optJSONObject("age");
//		Face.Age age = new Face.Age();
//		age.setValue(ageObj.optInt("value"));
//		age.setRange(ageObj.optInt("range"));
//		attribute.setAge(age);
//		JSONObject genderObj = attributeObj.optJSONObject("gender");
//		Face.Gender gender = new Face.Gender();
//		gender.setValue(genderObj.optString("value"));
//		gender.setConfidence(Float.valueOf(genderObj.optString("confidence")));
//		attribute.setGender(gender);
//		JSONObject raceObj = attributeObj.optJSONObject("race");
//		Face.Race race = new Face.Race();
//		race.setValue(raceObj.optString("value"));
//		race.setConfidence(Float.valueOf(raceObj.optString("confidence")));
//		attribute.setRace(race);
//		return attribute;
//	}
} public class PersonService extends BaseService {

	public PersonService(Client client) {
		super(client);
	}
	
	/**
	 * 创建Person
	 * @param body
	 * @return
	 * @throws ClientProtocolException
	 * @throws IOException
	 * @throws JSONException 
	 * @throws ParseException 
	 */
	public PersonCreateResp createPerson(PersonCreateReq body) throws ClientProtocolException, IOException, ParseException, JSONException {
		Map<String, Object> params = new HashMap<String, Object>();
		params.put("api_key", client.getAppKey());
		params.put("api_secret", client.getAppSecret());
		params.put("person_name", body.getPerson_name());
		params.put("face_id", body.getFace_id());
		params.put("tag", body.getTag());
		params.put("group_id", body.getGroup_id());
		params.put("group_name", body.getGroup_name());
		return getCreateRespose(params);
	}
	
	private PersonCreateResp getCreateRespose(Map<String, Object> params) throws ClientProtocolException, IOException, ParseException, JSONException {
		HttpResponse resp = HttpUtil.doPost(UrlConfig.PATH_PERSON_CREATE, params);
		JSONObject json = new JSONObject(EntityUtils.toString(resp.getEntity()));
		Log.i(json.toString());
		PersonCreateResp result = new PersonCreateResp();
		result.setAdded_group(json.optInt("added_group"));
		result.setAdded_face(json.optInt("added_face"));
		result.setTag(json.optString("tag"));
		result.setPerson_name(json.optString("person_name"));
		result.setPerson_id(json.optString("person_id"));
		result.setError(json.optString("error"));
		result.setError_code(json.optInt("error_code", RespConfig.RESP_OK));
		return result;
	}

	/**
	 * 删除Person
	 * @param body
	 * @return
	 * @throws ClientProtocolException
	 * @throws IOException
	 * @throws JSONException 
	 * @throws ParseException 
	 */
	public PersonDeleteResp deletePerson(PersonDeleteReq body) throws ClientProtocolException, IOException, ParseException, JSONException {
		if(StringUtil.isEmpty(body.getPerson_id()) && StringUtil.isEmpty(body.getPerson_name())) {
			throw new IllegalArgumentException("person_name or person_id must be to set one");
		}
		Map<String, Object> params = new HashMap<String, Object>();
		params.put("api_key", client.getAppKey());
		params.put("api_secret", client.getAppSecret());
		params.put("person_name", body.getPerson_name());
		params.put("person_id", body.getPerson_id());
		
		HttpResponse resp = HttpUtil.doPost(UrlConfig.PATH_PERSON_DELETE, params);
		JSONObject json = new JSONObject(EntityUtils.toString(resp.getEntity()));
		Log.i(json.toString());
		PersonDeleteResp result = new PersonDeleteResp();
		result.setDeleted(json.optInt("deleted"));
		result.setSuccess(json.optBoolean("success"));
		result.setError(json.optString("error"));
		result.setError_code(json.optInt("error_code", RespConfig.RESP_OK));
		return result;
	}
	
	/**
	 * 向Person中添加Face
	 * @param body
	 * @return
	 * @throws ClientProtocolException
	 * @throws IOException
	 * @throws JSONException 
	 * @throws ParseException 
	 */
	public PersonAddFaceResp addFace(PersonAddFaceReq body) throws ClientProtocolException, IOException, ParseException, JSONException {
		if(StringUtil.isEmpty(body.getPerson_id()) && StringUtil.isEmpty(body.getPerson_name())) {
			throw new IllegalArgumentException("person_name or person_id must be to set one");
		}
		if(StringUtil.isEmpty(body.getFace_id())) {
			throw new IllegalArgumentException("face_id must be set");
		}
		Map<String, Object> params = new HashMap<String, Object>();
		params.put("api_key", client.getAppKey());
		params.put("api_secret", client.getAppSecret());
		params.put("person_name", body.getPerson_name());
		params.put("person_id", body.getPerson_id());
		params.put("face_id", body.getFace_id());
		
		HttpResponse resp = HttpUtil.doPost(UrlConfig.PATH_PERSON_ADD_FACE, params);
		JSONObject json = new JSONObject(EntityUtils.toString(resp.getEntity()));
		Log.i(json.toString());
		PersonAddFaceResp result = new PersonAddFaceResp();
		result.setAdded(json.optInt("added"));
		result.setSuccess(json.optBoolean("success"));
		result.setError(json.optString("error"));
		result.setError_code(json.optInt("error_code", RespConfig.RESP_OK));
		return result;
	}
	
	/**
	 * 从Person中删除Face
	 * @param body
	 * @return
	 * @throws ClientProtocolException
	 * @throws IOException
	 * @throws JSONException 
	 * @throws ParseException 
	 */
	public PersonRemoveFaceResp removeFace(PersonRemoveFaceReq body) throws ClientProtocolException, IOException, ParseException, JSONException {
		if(StringUtil.isEmpty(body.getPerson_id()) && StringUtil.isEmpty(body.getPerson_name())) {
			throw new IllegalArgumentException("person_name or person_id must be to set one");
		}
		if(StringUtil.isEmpty(body.getFace_id())) {
			throw new IllegalArgumentException("face_id must be set");
		}
		Map<String, Object> params = new HashMap<String, Object>();
		params.put("api_key", client.getAppKey());
		params.put("api_secret", client.getAppSecret());
		params.put("person_name", body.getPerson_name());
		params.put("person_id", body.getPerson_id());
		params.put("face_id", body.getFace_id());
		
		HttpResponse resp = HttpUtil.doPost(UrlConfig.PATH_PERSON_REMOVE_FACE, params);
		JSONObject json = new JSONObject(EntityUtils.toString(resp.getEntity()));
		Log.i(json.toString());
		PersonRemoveFaceResp result = new PersonRemoveFaceResp();
		result.setRemoved(json.optInt("removed"));
		result.setSuccess(json.optBoolean("success"));
		result.setError(json.optString("error"));
		result.setError_code(json.optInt("error_code", RespConfig.RESP_OK));
		return result;
	}
	
	/**
	 * 修改Person信息
	 * @param body
	 * @return
	 * @throws IOException 
	 * @throws ClientProtocolException 
	 * @throws JSONException 
	 * @throws ParseException 
	 */
	public PersonSetInfoResp setPersonInfo(PersonSetInfoReq body) throws ClientProtocolException, IOException, ParseException, JSONException {
		if(StringUtil.isEmpty(body.getPerson_id()) && StringUtil.isEmpty(body.getPerson_name())) {
			throw new IllegalArgumentException("person_name or person_id must be to set one");
		}
		Map<String, Object> params = new HashMap<String, Object>();
		params.put("api_key", client.getAppKey());
		params.put("api_secret", client.getAppSecret());
		params.put("person_name", body.getPerson_name());
		params.put("person_id", body.getPerson_id());
		params.put("name", body.getName());
		params.put("tag", body.getTag());
		
		HttpResponse resp = HttpUtil.doPost(UrlConfig.PATH_PERSON_SET_INFO, params);
		JSONObject json = new JSONObject(EntityUtils.toString(resp.getEntity()));
		Log.i(json.toString());
		PersonSetInfoResp result = new PersonSetInfoResp();
		result.setPerson_id(json.optString("person_id"));
		result.setPerson_name(json.optString("person_name"));
		result.setTag(json.optString("tag"));
		result.setError(json.optString("error"));
		result.setError_code(json.optInt("error_code", RespConfig.RESP_OK));
		return result;
	}

	/**
	 * 查询Person的信息
	 * @param body
	 * @return
	 * @throws ClientProtocolException
	 * @throws IOException
	 * @throws JSONException 
	 * @throws ParseException 
	 */
	public PersonGetInfoResp getPersonInfo(PersonGetInfoReq body) throws ClientProtocolException, IOException, ParseException, JSONException {
		if(StringUtil.isEmpty(body.getPerson_id()) && StringUtil.isEmpty(body.getPerson_name())) {
			throw new IllegalArgumentException("person_name or person_id must be to set one");
		}
		Map<String, Object> params = new HashMap<String, Object>();
		params.put("api_key", client.getAppKey());
		params.put("api_secret", client.getAppSecret());
		params.put("person_name", body.getPerson_name());
		params.put("person_id", body.getPerson_id());
		
		HttpResponse resp = HttpUtil.doPost(UrlConfig.PATH_PERSON_GET_INFO, params);
		JSONObject json = new JSONObject(EntityUtils.toString(resp.getEntity()));
		Log.i(json.toString());
		PersonGetInfoResp result = new PersonGetInfoResp();
		result.setPerson_id(json.optString("person_id"));
		result.setPerson_name(json.optString("person_name"));
		result.setFace(getFaceInfo(json.optJSONArray("face")));
		result.setGroup(getGroupInfo(json.optJSONArray("group")));
		result.setTag(json.optString("tag"));
		result.setError(json.optString("error"));
		result.setError_code(json.optInt("error_code", RespConfig.RESP_OK));
		return result;
	}
	
	
	private List<Face> getFaceInfo(JSONArray faceArray) {
		List<Face> faces = new ArrayList<Face>();
		if(faceArray != null) {
			JSONObject faceObj = null;
			Face face = null;
			for(int i = 0; i < faceArray.length(); i++) {
				faceObj = faceArray.optJSONObject(i);
				face = new Face();
				face.setFace_id(faceObj.optString("face_id"));
				face.setTag(faceObj.optString("tag"));
				faces.add(face);
			}
		}
		return faces;
	}
	
	private List<Group> getGroupInfo(JSONArray groupArray) {
		List<Group> groups = new ArrayList<Group>();
		if(groupArray != null) {
			JSONObject groupObj = null;
			Group group = null;
			for(int i = 0; i < groupArray.length(); i++) {
				groupObj = groupArray.optJSONObject(i);
				group = new Group();
				group.setGroup_id(groupObj.optString("group_id"));
				group.setGroup_name(groupObj.optString("group_name"));
				group.setTag(groupObj.optString("tag"));
				groups.add(group);
			}
		}
		return groups;
	}
	
} public class RecognitionService extends BaseService {

	/**
	 * @param client
	 */
	public RecognitionService(Client client) {
		super(client);
	}
	
	/**
	 * 计算两个Face的相似性以及五官相似度
	 * @param body
	 * @return
	 * @throws ClientProtocolException
	 * @throws IOException
	 * @throws JSONException 
	 * @throws ParseException 
	 */
	public CompareResp compare(CompareReq body) throws ClientProtocolException, IOException, ParseException, JSONException {
		if(StringUtil.isEmpty(body.getFace_id1()) || StringUtil.isEmpty(body.getFace_id2())) {
			throw new IllegalArgumentException("face_id1 and face_id2 should not be null");
		}
		Map<String, Object> params = new HashMap<String, Object>();
		params.put("api_key", client.getAppKey());
		params.put("api_secret", client.getAppSecret());
		params.put("face_id1", body.getFace_id1());
		params.put("face_id2", body.getFace_id2());
		
		HttpResponse resp = HttpUtil.doPost(UrlConfig.PATH_RECOGNITION_COMPARE, params);
		JSONObject json = new JSONObject(EntityUtils.toString(resp.getEntity()));
		Log.i(json.toString());
		CompareResp result = new CompareResp();
		result.setSession_id(json.optString("session_id"));
		result.setSimilarity((float)json.optDouble("similarity"));
		JSONObject jsObj = json.optJSONObject("component_similarity");
		CompareResp.ComponentSimilarity obj = new CompareResp.ComponentSimilarity();
		obj.setEye((float)jsObj.optDouble("eye"));
		obj.setMouth((float) jsObj.optDouble("mouth"));
		obj.setNose((float) jsObj.optDouble("nose"));
		obj.setEyebrow((float) jsObj.optDouble("eyebrow"));
		result.setComponent_similarity(obj);
		result.setError(json.optString("error"));
		result.setError_code(json.optInt("error_code"));
		return result;
	}

	/**
	 * 给定一个Face和一个Person，返回是否是同一个人的判断以及置信度。
	 * 
	 * 注意，当Person中的信息被修改之后（增加，删除了Face等），为了保证结果与最新数据一致，Person应当被重新train。 
	 * 见 @see {@link TrainService}
	 * 否则调用此API时将使用最后一次train时的数据。
	 * @param body
	 * @return
	 * @throws ClientProtocolException
	 * @throws IOException
	 * @throws JSONException 
	 * @throws ParseException 
	 */
	public VerifyResp verify(VerifyReq body) throws ClientProtocolException, IOException, ParseException, JSONException {
		if(StringUtil.isEmpty(body.getFace_id())) {
			throw new IllegalArgumentException("face_id should not be null");
		}
		if(StringUtil.isEmpty(body.getPerson_id()) && StringUtil.isEmpty(body.getPerson_name())) {
			throw new IllegalArgumentException("person_id or person_name must to be set one");
		}
		Map<String, Object> params = new HashMap<String, Object>();
		params.put("api_key", client.getAppKey());
		params.put("api_secret", client.getAppSecret());
		params.put("face_id", body.getFace_id());
		params.put("person_id", body.getPerson_id());
		params.put("person_name", body.getPerson_name());
		
		HttpResponse resp = HttpUtil.doPost(UrlConfig.PATH_RECOGNITION_VERIFY, params);
		JSONObject json = new JSONObject(EntityUtils.toString(resp.getEntity()));
		Log.i(json.toString());
		VerifyResp result = new VerifyResp();
		result.setSession_id(json.optString("session_id"));
		result.setIs_same_person(json.optBoolean("is_same_person"));
		result.setConfidence((float)json.optDouble("confidence"));
		result.setError(json.optString("error"));
		result.setError_code(json.optInt("error_code", RespConfig.RESP_OK));
		return result;
	}

	/**
	 * 给定一个Face和一个Faceset，在该Faceset内搜索最相似的Face。提示：若搜索集合需要包含超过10000张人脸，可以分成多个faceset分别调用search功能再将结果按confidence顺序合并即可。
	 * 
	 * 注意，当Faceset中的信息被修改之后（增加，删除了Face等），为了保证结果与最新数据一致，Faceset应当被重新train. 
	 * 见 @see {@link TrainService}
	 * 否则调用此API时将使用最后一次train时的数据。
	 * @param body
	 * @return
	 * @throws ClientProtocolException
	 * @throws IOException
	 * @throws JSONException 
	 * @throws ParseException 
	 */
	public SearchResp search(SearchReq body) throws ClientProtocolException, IOException, ParseException, JSONException {
		if(StringUtil.isEmpty(body.getKey_face_id())) {
			throw new IllegalArgumentException("key_face_id should not be null");
		}
		if(StringUtil.isEmpty(body.getFaceset_id()) && StringUtil.isEmpty(body.getFaceset_name())) {
			throw new IllegalArgumentException("faceset_id or faceset_name must to be set one");
		}
		Map<String, Object> params = new HashMap<String, Object>();
		params.put("api_key", client.getAppKey());
		params.put("api_secret", client.getAppSecret());
		params.put("key_face_id", body.getKey_face_id());
		params.put("faceset_id", body.getFaceset_id());
		params.put("faceset_name", body.getFaceset_name());
		
		HttpResponse resp = HttpUtil.doPost(UrlConfig.PATH_RECOGNITION_SEARCH, params);
		JSONObject json = new JSONObject(EntityUtils.toString(resp.getEntity()));
		Log.i(json.toString());
		SearchResp result = new SearchResp();
		result.setSession_id(json.optString("session_id"));
		result.setCandidates(getSearchCanditate(json.optJSONArray("candidate")));
		result.setError(json.optString("error"));
		result.setError_code(json.optInt("error_code", RespConfig.RESP_OK));
		return result;
	}

	public IdentifyResp identity(IdentityReq body) throws ClientProtocolException, IOException, ParseException, JSONException {
		if(StringUtil.isEmpty(body.getGroup_id()) && StringUtil.isEmpty(body.getGroup_name())) {
			throw new IllegalArgumentException("group_id or group_name must to be set one");
		}
		Map<String, Object> params = new HashMap<String, Object>();
		params.put("api_key", client.getAppKey());
		params.put("api_secret", client.getAppSecret());
		params.put("group_id", body.getGroup_id());
		params.put("group_name", body.getGroup_name());
		params.put("url", body.getUrl());
		params.put("img", body.getImg());
		params.put("mode", body.getMode());
		params.put("key_face_id", body.getKey_face_id());
		params.put("async", body.getAsync());
		HttpResponse resp = HttpUtil.doPost(UrlConfig.PATH_RECOGNITION_IDENTIFY, params);
		JSONObject json = new JSONObject(EntityUtils.toString(resp.getEntity()));
		Log.i(json.toString());
		IdentifyResp result = new IdentifyResp();
		result.setSession_id(json.optString("session_id"));
		result.setFace(getIdentityFace(json.optJSONArray("face")));
		result.setError(json.optString("error"));
		result.setError_code(json.optInt("error_code", RespConfig.RESP_OK));
		return result;
	}
	
	/**
	 * 解析JSONArray中canditate返回结果
	 * @param candidateArray
	 * @return
	 */
	private List<SearchResp.Candidate> getSearchCanditate(JSONArray candidateArray) {
		List<SearchResp.Candidate> candidates = new ArrayList<SearchResp.Candidate>();
		if(candidateArray != null) {
			JSONObject candidateObj = null;
			SearchResp.Candidate candidate = null;
			for(int i = 0; i < candidateArray.length(); i++ ) {
				candidateObj = candidateArray.optJSONObject(i);
				candidate = new SearchResp.Candidate();
				candidate.setFace_id(candidateObj.optString("face_id"));
				candidate.setTag(candidateObj.optString("tag"));
				candidate.setSimilarity((float) candidateObj.optDouble("similarity"));
				candidates.add(candidate);
			}
		}
		return candidates;
	}
	
	/**
	 * 解析JSONArray识别返回的Face信息
	 * @param faceArray
	 * @return
	 */
	public List<IdentifyResp.IdentifyFace> getIdentityFace(JSONArray faceArray) {
		List<IdentifyResp.IdentifyFace> faces = new ArrayList<IdentifyResp.IdentifyFace>();
		if(faceArray != null) {
			JSONObject faceObj = null;
			IdentifyResp.IdentifyFace iFace = null;
			Face face = null;
			for(int i = 0; i < faceArray.length(); i++) {
				faceObj = faceArray.optJSONObject(i);
				iFace = new IdentifyResp.IdentifyFace();
				face = new Face();
				face.setFace_id(faceObj.optString("face_id"));
				FaceService.setPosition(faceObj.optJSONObject("position"), face);
				iFace.setCandidates(getIdentityCanditate(faceObj.optJSONArray("candidate")));
//				iFace.setPosition(FaceService.getPosition(faceObj.optJSONObject("position")));
				iFace.setFace(face);
				faces.add(iFace);
			}
		}
		return faces;
	}

	/**
	 * 解析JSONArray识别返回的Face信息下的candidate信息，包括Person id，name，tag和confidence置信度
	 * @param candidateArray
	 * @return
	 */
	private List<IdentifyResp.Candidate> getIdentityCanditate(JSONArray candidateArray) {
		List<IdentifyResp.Candidate> candidates = new ArrayList<IdentifyResp.Candidate>();
		if(candidateArray != null) {
			JSONObject candidateObj = null;
			IdentifyResp.Candidate candidate = null;
			for(int i = 0; i < candidateArray.length(); i++) {
				candidateObj = candidateArray.optJSONObject(i);
				candidate = new IdentifyResp.Candidate();
				candidate.setPerson_id(candidateObj.optString("person_id"));
				candidate.setPerson_name(candidateObj.optString("person_name"));
				candidate.setTag(candidateObj.optString("tag"));
				candidate.setConfidence((float) candidateObj.optDouble("confidence"));
				candidates.add(candidate);
			}
		}
		return candidates;
	}
	
} public class TrainService extends BaseService {

	/**
	 * @param client
	 */
	public TrainService(Client client) {
		super(client);
	}
	
	/**
	 * 针对verify功能对一个person进行训练。请注意:
	 *
	 * 在一个person内进行verify之前，必须先对该person进行Train
	 * 当一个person内的数据被修改后(例如增删Person相关的Face等)，为使这些修改生效，person应当被重新Train
	 * Train所花费的时间较长, 因此该调用是异步的，仅返回session_id。
	 * 训练的结果可以通过/info/get_session查询。当训练完成时，返回值中将包含{"success": true}
	 * @param body
	 * @return
	 * @throws ClientProtocolException
	 * @throws IOException
	 * @throws JSONException 
	 * @throws ParseException 
	 */
	public TrainVerifyResp trainVerify(TrainVerifyReq body) throws ClientProtocolException, IOException, ParseException, JSONException {
		if(StringUtil.isEmpty(body.getPerson_id()) && StringUtil.isEmpty(body.getPerson_name())) {
			throw new IllegalArgumentException("person_name or person_id must be to set one");
		}
		Map<String, Object> params = new HashMap<String, Object>();
		params.put("api_key", client.getAppKey());
		params.put("api_secret", client.getAppSecret());
		params.put("person_name", body.getPerson_name());
		params.put("person_id", body.getPerson_id());
		
		HttpResponse resp = HttpUtil.doPost(UrlConfig.PATH_TRAIN_VERIFY, params);
		JSONObject json = new JSONObject(EntityUtils.toString(resp.getEntity()));
		Log.i(json.toString());
		TrainVerifyResp result = new TrainVerifyResp();
		result.setSession_id(json.optString("session_id"));
		result.setError(json.optString("error"));
		result.setError_code(json.optInt("error_code", RespConfig.RESP_OK));
		return result;
	}

	/**
	 * 针对search功能对一个faceset进行训练。请注意:
	 * 
	 * 在一个faceset内进行search之前，必须先对该faceset进行Train
	 * 当一个faceset内的数据被修改后(例如增删Face等)，为使这些修改生效，faceset应当被重新Train
	 * Train所花费的时间较长, 因此该调用是异步的，仅返回session_id。
	 * 训练的结果可以通过 /info/get_session 查询。当训练完成时，返回值中将包含{"success": true}
	 * @param body
	 * @return
	 * @throws ClientProtocolException
	 * @throws IOException
	 * @throws JSONException 
	 * @throws ParseException 
	 */
	public TrainSearchResp trainSearch(TrainSearchReq body) throws ClientProtocolException, IOException, ParseException, JSONException {
		if(StringUtil.isEmpty(body.getFaceset_id()) && StringUtil.isEmpty(body.getFaceset_name())) {
			throw new IllegalArgumentException("faceset_id or faceset_name must be to set one");
		}
		Map<String, Object> params = new HashMap<String, Object>();
		params.put("api_key", client.getAppKey());
		params.put("api_secret", client.getAppSecret());
		params.put("faceset_id", body.getFaceset_id());
		params.put("faceset_name", body.getFaceset_name());
		
		HttpResponse resp = HttpUtil.doPost(UrlConfig.PATH_TRAIN_SEARCH, params);
		JSONObject json = new JSONObject(EntityUtils.toString(resp.getEntity()));
		Log.i(json.toString());
		TrainSearchResp result = new TrainSearchResp();
		result.setSession_id(json.optString("session_id"));
		result.setError(json.optString("error"));
		result.setError_code(json.optInt("error_code", RespConfig.RESP_OK));
		return result;
	}

	/**
	 * 针对identify功能对一个Group进行训练。请注意:
	 * 
	 * 在一个Group内进行identify之前，必须先对该Group进行Train
	 * 当一个Group内的数据被修改后(例如增删Person, 增删Person相关的Face等)，为使这些修改生效，Group应当被重新Train
	 * Train所花费的时间较长, 因此该调用是异步的，仅返回session_id。
	 * 训练的结果可以通过 /info/get_session 查询。当训练完成时，返回值中将包含{"success": true}
	 * @param body
	 * @return
	 * @throws ClientProtocolException
	 * @throws IOException
	 * @throws JSONException 
	 * @throws ParseException 
	 */
	public TrainIdentityResp trainIdentity(TrainIdentityReq body) throws ClientProtocolException, IOException, ParseException, JSONException {
		if(StringUtil.isEmpty(body.getGroup_id()) && StringUtil.isEmpty(body.getGroup_name())) {
			throw new IllegalArgumentException("group_id or group_name must be to set one");
		}
		Map<String, Object> params = new HashMap<String, Object>();
		params.put("api_key", client.getAppKey());
		params.put("api_secret", client.getAppSecret());
		params.put("group_id", body.getGroup_id());
		params.put("group_name", body.getGroup_name());
		
		HttpResponse resp = HttpUtil.doPost(UrlConfig.PATH_TRAIN_IDENTIFY, params);
		JSONObject json = new JSONObject(EntityUtils.toString(resp.getEntity()));
		Log.i(json.toString());
		TrainIdentityResp result = new TrainIdentityResp();
		result.setSession_id(json.optString("session_id"));
		result.setError(json.optString("error"));
		result.setError_code(json.optInt("error_code", RespConfig.RESP_OK));
		return result;
	}

}
import java.io.File;
import java.io.IOException;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import org.apache.http.ParseException;
import org.apache.http.client.ClientProtocolException;
import org.json.JSONException;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.ProgressDialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.graphics.Bitmap;
import android.os.AsyncTask;
import android.os.Bundle;
import android.util.DisplayMetrics;
import android.view.KeyEvent;
import android.view.View;
import android.widget.Toast;
import com.xiaoying.facedemo.MainActivity;
import com.xiaoying.facedemo.MainApplication;
import com.xiaoying.facedemo.R;
import com.xiaoying.facedemo.db.util.FaceDBUtil;
import com.xiaoying.facedemo.db.util.FacePersonDBUtil;
import com.xiaoying.facedemo.db.util.ImageDBUtil;
import com.xiaoying.facedemo.person.CreatePersonActivity;
import com.xiaoying.facedemo.person.PersonListActivity;
import com.xiaoying.facedemo.utils.BitmapUtil;
import com.xiaoying.facedemo.utils.FileUtil;
import com.xiaoying.facedemo.utils.LogUtil;
import com.xiaoying.facedemo.widget.MarkFaceView;
import com.xiaoying.facedemo.widget.TitleBar;
import com.xiaoying.faceplusplus.api.cliet.Client;
import com.xiaoying.faceplusplus.api.config.RespConfig;
import com.xiaoying.faceplusplus.api.entity.Face;
import com.xiaoying.faceplusplus.api.entity.Group;
import com.xiaoying.faceplusplus.api.entity.Image;
import com.xiaoying.faceplusplus.api.entity.Person;
import com.xiaoying.faceplusplus.api.entity.request.face.DetectReq;
import com.xiaoying.faceplusplus.api.entity.request.person.PersonAddFaceReq;
import com.xiaoying.faceplusplus.api.entity.request.recognition.IdentityReq;
import com.xiaoying.faceplusplus.api.entity.request.train.TrainIdentityReq;
import com.xiaoying.faceplusplus.api.entity.response.face.DetectResp;
import com.xiaoying.faceplusplus.api.entity.response.person.PersonAddFaceResp;
import com.xiaoying.faceplusplus.api.entity.response.recognition.IdentifyResp;
import com.xiaoying.faceplusplus.api.entity.response.recognition.IdentifyResp.Candidate;
import com.xiaoying.faceplusplus.api.entity.response.train.TrainIdentityResp;
import com.xiaoying.faceplusplus.api.service.FaceService;
import com.xiaoying.faceplusplus.api.service.InfoService;
import com.xiaoying.faceplusplus.api.service.PersonService;
import com.xiaoying.faceplusplus.api.service.RecognitionService;
import com.xiaoying.faceplusplus.api.service.TrainService;
/*
 * 文件名：DetectActivity.java
 * 版权：<版权>
 * 描述：<描述>
 * 创建人：xiaoying
 * 创建时间：2013-5-17
 * 修改人：xiaoying
 * 修改时间：2013-5-17
 * 版本：v1.0
 */
package com.xiaoying.facedemo.detect;





/**
 * 功能：人脸识别的Activity
 * @author xiaoying
 *
 */
public class DetectActivity extends Activity {
	
	public static final int REQUEST_PICK_PERSON = 1000;
	
	public static final int REQUEST_CREATE_PERSON = 1001;
	
	private String tag = DetectActivity.class.getSimpleName();
	
	private TitleBar mTitleBar = null;
	
	private MarkFaceView mMarkView = null;
	
	private ProgressDialog mProgressDialog = null;
	
	private Bitmap mBitmap = null;
	
	private String mBitmapPath = null;
	
	private Image mImage = new Image();
	
//	private List<Face> mFaces = new ArrayList<Face>();
	
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		
		setContentView(R.layout.activity_detect);
		
		initView();
		
		initData();
		
		DisplayMetrics m = new DisplayMetrics();
		getWindowManager().getDefaultDisplay().getMetrics(m);
		
		mBitmap = BitmapUtil.loadBitmap(mBitmapPath, m.widthPixels, m.heightPixels);
		LogUtil.w(tag, "Bitmap size++++>>>(" + mBitmap.getWidth() + ", " + mBitmap.getHeight()  + ")");
		mMarkView.setBitmap(mBitmap);
		
		initProgressDialog();
	}
	
	
	private void initView() {
		mTitleBar = (TitleBar) findViewById(R.id.tb_title);
		mMarkView = (MarkFaceView) findViewById(R.id.mfv_mark_face);
		mTitleBar.setTitle(R.string.detect_face);
		mTitleBar.setLeftButton(R.string.backe, new View.OnClickListener() {
			
			@Override
			public void onClick(View v) {
				finish();
			}
		});
		
		mTitleBar.setRightButton(R.string.upload_detect, new View.OnClickListener() {
			
			@Override
			public void onClick(View v) {
				File file = new File(mBitmapPath);
				if(FileUtil.getFileSize(mBitmapPath) < 3 * 1024 * 1024) {