content: /*
   * Copyright 2013 Chris Banes
   *
   * Licensed under the Apache License, Version 2.0 (the "License");
   * you may not use this file except in compliance with the License.
   * You may obtain a copy of the License at
   *
   *     http://www.apache.org/licenses/LICENSE-2.0
   *
   * Unless required by applicable law or agreed to in writing, software
   * distributed under the License is distributed on an "AS IS" BASIS,
   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   * See the License for the specific language governing permissions and
   * limitations under the License.
   */
  package com.zhaojian.jolly.model;
  
  import java.io.File;
  import java.io.FileNotFoundException;
  import java.util.HashMap;
  import java.util.List;
  
  import android.accounts.Account;
  import android.content.ContentResolver;
  import android.content.Context;
  import android.content.res.Resources;
  import android.graphics.Bitmap;
  import android.graphics.BitmapFactory;
  import android.graphics.RectF;
  import android.location.Location;
  import android.net.Uri;
  import android.os.Environment;
  import android.provider.MediaStore.Images.Thumbnails;
  import android.text.TextUtils;
  
  import com.zhaojian.jolly.selectphotos.SelectPhotoApplication;
  import com.zhaojian.jolly.utils.Utils;
  
  public class PhotoUpload {
  
  	private static final HashMap<Uri, PhotoUpload> SELECTION_CACHE = new HashMap<Uri, PhotoUpload>();
  
  	public static final int STATE_UPLOAD_COMPLETED = 5;
  	public static final int STATE_UPLOAD_ERROR = 4;
  	public static final int STATE_UPLOAD_IN_PROGRESS = 3;
  	public static final int STATE_UPLOAD_WAITING = 2;
  	public static final int STATE_SELECTED = 1;
  	public static final int STATE_NONE = 0;
  
  	public static final String FIELD_STATE = "state";
  	static final String FIELD_URI = "uri";
  	static final String FIELD_COMPLETED_DETECTION = "tag_detection";
  	static final String FIELD_USER_ROTATION = "user_rotation";
  	static final String FIELD_FILTER = "filter";
  	static final String FIELD_CROP_L = "crop_l";
  	static final String FIELD_CROP_T = "crop_t";
  	static final String FIELD_CROP_R = "crop_r";
  	static final String FIELD_CROP_B = "crop_b";
  	static final String FIELD_ACCOUNT_ID = "acc_id";
  	static final String FIELD_TARGET_ID = "target_id";
  	static final String FIELD_QUALITY = "quality";
  	static final String FIELD_RESULT_POST_ID = "r_post_id";
  	static final String FIELD_CAPTION = "caption";
  	static final String FIELD_TAGS_JSON = "tags";
  	static final String FIELD_PLACE_NAME = "place_name";
  	static final String FIELD_PLACE_ID = "place_id";
  
  	static final String LOG_TAG = "PhotoUpload";
  	static final float CROP_THRESHOLD = 0.01f; // 1%
  	static final int MINI_THUMBNAIL_SIZE = 300;
  	static final float MIN_CROP_VALUE = 0.0f;
  	static final float MAX_CROP_VALUE = 1.0f;
  
  	public static PhotoUpload getSelection(Uri uri) {
  		// Check whether we've already got a Selection cached
  		PhotoUpload item = SELECTION_CACHE.get(uri);
  
  		if (null == item) {
  			item = new PhotoUpload(uri);
  			SELECTION_CACHE.put(uri, item);
  		}
  
  		return item;
  	}
  
  	public static void clearCache() {
  		SELECTION_CACHE.clear();
  	}
  
  	public static void populateCache(List<PhotoUpload> uploads) {
  		for (PhotoUpload upload : uploads) {
  			SELECTION_CACHE.put(upload.getOriginalPhotoUri(), upload);
  		}
  	}
  
  	public static PhotoUpload getSelection(Uri baseUri, long id) {
  		return getSelection(Uri.withAppendedPath(baseUri, String.valueOf(id)));
  	}
  
  	private static boolean checkCropValues(float left, float top, float right,
  			float bottom) {
  		return Math.max(left, top) >= (MIN_CROP_VALUE + CROP_THRESHOLD)
  				|| Math.min(right, bottom) <= (MAX_CROP_VALUE - CROP_THRESHOLD);
  	}
  
  	private static float santizeCropValue(float value) {
  		return Math.min(1f, Math.max(0f, value));
  	}
  
  	/**
  	 * Uri and Database Key
  	 */
  	private Uri mFullUri;
  	private String mFullUriString;
  
  	/**
  	 * Edit Variables
  	 */
  	private boolean mCompletedDetection;
  	private int mUserRotation;
  	private float mCropLeft;
  	private float mCropTop;
  	private float mCropRight;
  	private float mCropBottom;
  
  	/**
  	 * Upload Variables
  	 */
  	private String mAccountId;
  	private String mTargetId;
  	private String mResultPostId;
  	private int mState;
  	private String mCaption;
  	String tagJson;
  	private String mPlaceName;
  	private String mPlaceId;
  
  	private Account mAccount;
  	private int mProgress;
  	private Bitmap mBigPictureNotificationBmp;
  
  	private boolean mNeedsSaveFlag = false;
  
  	PhotoUpload() {
  		// NO-Arg for Ormlite
  	}
  
  	private PhotoUpload(Uri uri) {
  		mFullUri = uri;
  		mFullUriString = uri.toString();
  		reset();
  	}
  
  	public boolean beenCropped() {
  		return checkCropValues(mCropLeft, mCropTop, mCropRight, mCropBottom);
  	}
  
  	@Override
  	public boolean equals(Object obj) {
  		if (obj instanceof PhotoUpload) {
  			return getOriginalPhotoUri().equals(
  					((PhotoUpload) obj).getOriginalPhotoUri());
  		}
  		return false;
  	}
  
  	public boolean isValid(Context context) {
  		final String path = Utils.getPathFromContentUri(
  				context.getContentResolver(), getOriginalPhotoUri());
  		if (null != path) {
  			File file = new File(path);
  			return file.exists();
  		}
  		return false;
  	}
  
  	public Account getAccount() {
  		return mAccount;
  	}
  
  	public Bitmap getBigPictureNotificationBmp() {
  		return mBigPictureNotificationBmp;
  	}
  
  	public String getCaption() {
  		return mCaption;
  	}
  
  	public RectF getCropValues() {
  		return new RectF(mCropLeft, mCropTop, mCropRight, mCropBottom);
  	}
  
  	public RectF getCropValues(final int width, final int height) {
  		return new RectF(mCropLeft * width, mCropTop * height, mCropRight
  				* width, mCropBottom * height);
  	}
  
  	public Bitmap getDisplayImage(Context context) {
  		try {
  			final int size = SelectPhotoApplication.getInstanse()
  					.getSmallestScreenDimension();
  			Bitmap bitmap = Utils.decodeImage(context.getContentResolver(),
  					getOriginalPhotoUri(), size);
  			bitmap = Utils.rotate(bitmap, getExifRotation(context));
  			return bitmap;
  		} catch (FileNotFoundException e) {
  			e.printStackTrace();
  			return null;
  		}
  	}
  
  	public String getDisplayImageKey() {
  		return "dsply_" + getOriginalPhotoUri();
  	}
  
  	public Location getExifLocation(Context context) {
  		final String filePath = Utils.getPathFromContentUri(
  				context.getContentResolver(), getOriginalPhotoUri());
  		if (null != filePath) {
  			return Utils.getExifLocation(filePath);
  		}
  		return null;
  	}
  
  	public int getExifRotation(Context context) {
  		return Utils.getOrientationFromContentUri(context.getContentResolver(),
  				getOriginalPhotoUri());
  	}
  
  	public Uri getOriginalPhotoUri() {
  		if (null == mFullUri && !TextUtils.isEmpty(mFullUriString)) {
  			mFullUri = Uri.parse(mFullUriString);
  		}
  		return mFullUri;
  	}
  
  	public String getPlaceId() {
  		return mPlaceId;
  	}
  
  	public String getResultPostId() {
  		return mResultPostId;
  	}
  
  	public Bitmap getThumbnailImage(Context context) {
  		if (ContentResolver.SCHEME_CONTENT.equals(getOriginalPhotoUri()
  				.getScheme())) {
  			return getThumbnailImageFromMediaStore(context);
  		}
  
  		final Resources res = context.getResources();
  		int size = MINI_THUMBNAIL_SIZE;
  
  		try {
  			Bitmap bitmap = Utils.decodeImage(context.getContentResolver(),
  					getOriginalPhotoUri(), size);
  			// bitmap = Utils.rotate(bitmap, getExifRotation(context));
  			return bitmap;
  		} catch (FileNotFoundException e) {
  			e.printStackTrace();
  			return null;
  		}
  	}
  
  	public String getThumbnailImageKey() {
  		return "thumb_" + getOriginalPhotoUri();
  	}
  
  	public int getTotalRotation(Context context) {
  		return (getExifRotation(context) + getUserRotation()) % 360;
  	}
  
  	public int getUploadProgress() {
  		return mProgress;
  	}
  
  	public File getUploadSaveFile() {
  		File dir = new File(
  				Environment
  						.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES),
  				"photup");
  		if (!dir.exists()) {
  			dir.mkdirs();
  		}
  
  		return new File(dir, System.currentTimeMillis() + ".jpg");
  	}
  
  	public int getUploadState() {
  		return mState;
  	}
  
  	public String getUploadTargetId() {
  		return mTargetId;
  	}
  
  	public int getUserRotation() {
  		return mUserRotation % 360;
  	}
  
  	@Override
  	public int hashCode() {
  		return getOriginalPhotoUri().hashCode();
  	}
  
  	public boolean hasPlace() {
  		return null != mPlaceId && null != mPlaceName;
  	}
  
  	public void populateFromAccounts(HashMap<String, Account> accounts) {
  		if (null == mAccount && !TextUtils.isEmpty(mAccountId)) {
  			mAccount = accounts.get(mAccountId);
  		}
  	}
  
  	public Bitmap processBitmap(Bitmap bitmap, final boolean fullSize,
  			final boolean modifyOriginal) {
  
  		return bitmap;
  
  	}
  
  	public boolean requiresFaceDetectPass() {
  		return !mCompletedDetection;
  	}
  
  	public boolean requiresProcessing(final boolean fullSize) {
  		return getUserRotation() != 0 || (fullSize && beenCropped());
  	}
  
  	public boolean requiresSaving() {
  		return mNeedsSaveFlag;
  	}
  
  	public void reset() {
  		mState = STATE_NONE;
  		mUserRotation = 0;
  		mCaption = null;
  		mCropLeft = mCropTop = MIN_CROP_VALUE;
  		mCropRight = mCropBottom = MAX_CROP_VALUE;
  		mCompletedDetection = false;
  
  		setRequiresSaveFlag();
  	}
  
  	public void resetSaveFlag() {
  		mNeedsSaveFlag = false;
  	}
  
  	public void rotateClockwise() {
  		mUserRotation += 90;
  		setRequiresSaveFlag();
  	}
  
  	public void setCaption(String caption) {
  		if (TextUtils.isEmpty(caption)) {
  			mCaption = null;
  		} else {
  			mCaption = caption;
  		}
  
  		setRequiresSaveFlag();
  	}
  
  	public void setCropValues(RectF cropValues) {
  		if (checkCropValues(cropValues.left, cropValues.top, cropValues.right,
  				cropValues.bottom)) {
  
  			mCropLeft = santizeCropValue(cropValues.left);
  			mCropTop = santizeCropValue(cropValues.top);
  			mCropRight = santizeCropValue(cropValues.right);
  			mCropBottom = santizeCropValue(cropValues.bottom);
  
  		} else {
  
  			mCropLeft = mCropTop = MIN_CROP_VALUE;
  			mCropRight = mCropBottom = MAX_CROP_VALUE;
  		}
  
  		setRequiresSaveFlag();
  	}
  
  	public void setResultPostId(String resultPostId) {
  		mResultPostId = resultPostId;
  		setRequiresSaveFlag();
  	}
  
  	public void setUploadProgress(int progress) {
  		if (progress != mProgress) {
  			mProgress = progress;
  		}
  	}
  
  	public void setUploadState(final int state) {
  		if (mState != state) {
  			mState = state;
  
  			switch (state) {
  			case STATE_UPLOAD_ERROR:
  			case STATE_UPLOAD_COMPLETED:
  				mBigPictureNotificationBmp = null;
  				break;
  			case STATE_SELECTED:
  			case STATE_UPLOAD_WAITING:
  				mProgress = -1;
  				break;
  			}
  
  			setRequiresSaveFlag();
  		}
  	}
  
  	@Override
  	public String toString() {
  		StringBuffer sb = new StringBuffer();
  		String caption = getCaption();
  		if (null != caption) {
  			sb.append(caption).append(" ");
  		}
  
  		if (hasPlace()) {
  			sb.append("(").append(mPlaceName).append(")");
  		}
  
  		return sb.toString();
  	}
  
  	private Bitmap getThumbnailImageFromMediaStore(Context context) {
  		Resources res = context.getResources();
  
  		final int kind = Thumbnails.MINI_KIND;
  
  		BitmapFactory.Options opts = new BitmapFactory.Options();
  		opts = new BitmapFactory.Options();
  
  		try {
  			final long id = Long.parseLong(getOriginalPhotoUri()
  					.getLastPathSegment());
  			Bitmap bitmap = Thumbnails.getThumbnail(
  					context.getContentResolver(), id, kind, opts);
  			bitmap = Utils.rotate(bitmap, getExifRotation(context));
  			return bitmap;
  		} catch (Exception e) {
  			return null;
  		}
  	}
  
  	private void setRequiresSaveFlag() {
  		mNeedsSaveFlag = true;
  	}
  }
  