/*
 * Copyright (c) 2015. Ncomz. All Rights Reserved
 */

package com.ntels.kneet.v3.view;

import android.app.Activity;
import android.content.ComponentName;
import android.content.Intent;
import android.content.pm.ActivityInfo;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.content.res.Configuration;
import android.database.Cursor;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Matrix;
import android.media.ExifInterface;
import android.net.Uri;
import android.os.Bundle;
import android.os.Environment;
import android.provider.MediaStore;
import android.view.LayoutInflater;
import android.view.View;

import com.ntels.kneet.v3.R;
import com.ntels.kneet.v3.common.AppConfig;
import com.ntels.kneet.v3.common.Constants;
import com.ntels.kneet.v3.common.util.Dlog;
import com.ntels.kneet.v3.common.util.Util;
import com.ntels.kneet.v3.common.widget.CustomActivity;
import com.ntels.kneet.v3.view.dialog.CustomDialog;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.List;
public class Image_Select extends CustomActivity implements View.OnClickListener,
                                                            CustomDialog.OnMsgAlterToResult {

    /** Buttons for selector dialog */

    public  Activity  act;
    public  AppConfig appConfig;
    private Intent    intent;
    private Util         util           = new Util();
    private CustomDialog customDialog   = new CustomDialog();
    private boolean      mCropRequested = false;

    private final int REQ_CODE_PICK_GALLERY = 900001;
    private final int REQ_CODE_PICK_CAMERA  = 900002;
    private final int REQ_CODE_PICK_CROP    = 900003;

    /**
     * <PRE>
     * 1. MethodName: onCreate
     * 2. ClassName :
     * 3. Comment   : onCreate
     * 4. Developer : 최진오
     * 5. Created   : 2015. 10.
     * </PRE>
     *
     * @param savedInstanceState
     */
    @Override protected void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);
        act = Image_Select.this;
        appConfig = (AppConfig) act.getApplicationContext();
        customDialog.setOnMsgAlterToResultEvent(this);
        // 세로로 고정 역방향 세로는 가능
        setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT);
        View viewToLoad = LayoutInflater.from(act).inflate(R.layout.image_select, null);
        this.setContentView(viewToLoad);

        if ( savedInstanceState != null ) {
            mCropRequested = savedInstanceState.getBoolean(Constants.EXTRA_CROP_TYPE, false);
        } else {
            Intent intent = getIntent();
            mCropRequested = intent.getBooleanExtra(Constants.EXTRA_CROP_TYPE, false);
        }

        Dlog.v("mCropRequested = " + mCropRequested);
        startSelectImage();
    }

    @Override public void onConfigurationChanged(Configuration newConfig) {

        super.onConfigurationChanged(newConfig);
    }
    /**
     * Call this to start!
     */
    public void startSelectImage() {

        if ( !checkWriteExternalPermission() ) {
            //            showAlert("we need android.permission.WRITE_EXTERNAL_STORAGE");
            return;
        }
        if ( !checkSDisAvailable() ) {
            //            showAlert("Check External Storage.");
            return;
        }
        //        if (findViewById(R.id.ivImageSelected) == null) {
        //            showAlert("Your layout should have ImageView name as ivImageSelected.");
        //            return;
        //        }

        util.getView(act, R.id.llPic1).setOnClickListener(this);
        util.getView(act, R.id.llPic2).setOnClickListener(this);
        util.getView(act, R.id.llCancel).setOnClickListener(this);
    }

    public File getSelectedImageFile() {

        return getTempImageFile();
    }

    /**
     * crop 이 필요한 경우 설정함. 설정하지 않으면 crop 하지 않음.
     *
     * @param width
     * crop size width.
     * @param height
     * crop size height.
     */
    private int mCropAspectWidth = 1, mCropAspectHeight = 1;

    public void setCropOption(int aspectX, int aspectY) {

        mCropRequested = true;
        mCropAspectWidth = aspectX;
        mCropAspectHeight = aspectY;
    }

    /**
     * 사용할 이미지의 최대 크기 설정. 가로, 세로 지정한 크기보다 작은 사이즈로 이미지 크기를 조절함. default size :
     * 500
     *
     * @param sizePixel
     * 기본 500
     */
    private int mImageSizeBoundary = 500;

    public void setImageSizeBoundary(int sizePixel) {

        mImageSizeBoundary = sizePixel;
    }

    private boolean checkWriteExternalPermission() {

        String permission = "android.permission.WRITE_EXTERNAL_STORAGE";
        int res = checkCallingOrSelfPermission(permission);
        return (res == PackageManager.PERMISSION_GRANTED);
    }

    private boolean checkSDisAvailable() {

        String state = Environment.getExternalStorageState();
        return state.equals(Environment.MEDIA_MOUNTED);
    }

    private File getTempImageFile() {

        File path = new File(Environment.getExternalStorageDirectory() + "/Android/data/" + getPackageName() + "/temp/");
        if ( !path.exists() ) {
            path.mkdirs();
        }
        File file = new File(path, "tempimage.png");
        return file;
    }

    @Override public void onClick(View v) {

        switch (v.getId()) {
            case R.id.llPic1:
                intent = new Intent(Intent.ACTION_PICK);
                intent.setType(android.provider.MediaStore.Images.Media.CONTENT_TYPE);
                intent.setData(android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
                util.callActivityForResultNoAnim(act, intent, REQ_CODE_PICK_GALLERY);
                break;
            case R.id.llPic2:
                intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
                intent.putExtra(android.provider.MediaStore.EXTRA_OUTPUT, Uri.fromFile(getTempImageFile()));
                intent.putExtra("return-data", true);
                util.callActivityForResultNoAnim(act, intent, REQ_CODE_PICK_CAMERA);
                break;
            case R.id.llCancel:
                onBackPressed();
                break;
            default:
                break;
        }
    }

    @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) {

        Dlog.v("requestCode = " + requestCode);
        Dlog.v("resultCode = " + resultCode);
        Dlog.v("data = " + data);
        if ( requestCode == REQ_CODE_PICK_GALLERY && resultCode == Activity.RESULT_OK ) {
            // 갤러리의 경우 곧바로 data 에 uri가 넘어옴.
            Uri uri = data.getData();
            copyUriToFile(uri, getTempImageFile());
            correctCameraOrientation(getTempImageFile());
            Dlog.v("getTempImageFile = " + getTempImageFile());
            Dlog.v("mCropRequested = " + mCropRequested);
            if ( mCropRequested ) {
                cropImage();
            } else {
                doFinalProcess();
            }
        } else if ( requestCode == REQ_CODE_PICK_CAMERA && resultCode == Activity.RESULT_OK ) {
            // 카메라의 경우 file 로 결과물이 돌아옴.
            // 카메라 회전 보정.
            correctCameraOrientation(getTempImageFile());
            Dlog.v("mCropRequested = " + mCropRequested);
            if ( mCropRequested ) {
                cropImage();
            } else {
                doFinalProcess();
            }
        } else if ( requestCode == REQ_CODE_PICK_CROP && resultCode == Activity.RESULT_OK ) {
            // crop 한 결과는 file로 돌아옴.
            doFinalProcess();
        } else {
            super.onActivityResult(requestCode, resultCode, data);
        }
    }

    private void doFinalProcess() {
        // sample size 를 적용하여 bitmap load.
        Bitmap bitmap = loadImageWithSampleSize(getTempImageFile());

        // image boundary size 에 맞도록 이미지 축소.
        bitmap = resizeImageWithinBoundary(bitmap);

        // 결과 file 을 얻어갈 수 있는 메서드 제공.
        saveBitmapToFile(bitmap);

        intent = new Intent();
        intent.putExtra(Constants.EXTRA_IMAGE_FILE_NAME, getSelectedImageFile().toString());
        setResult(RESULT_OK, intent);
        finish();
    }

    private void saveBitmapToFile(Bitmap bitmap) {

        File target = getTempImageFile();
        try {
            FileOutputStream fos = new FileOutputStream(target, false);
            bitmap.compress(Bitmap.CompressFormat.PNG, 100, fos);
            fos.close();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /** 이미지 사이즈 수정 후, 카메라 rotation 정보가 있으면 회전 보정함. */
    private void correctCameraOrientation(File imgFile) {

        Bitmap bitmap = loadImageWithSampleSize(imgFile);
        try {
            ExifInterface exif = new ExifInterface(imgFile.getAbsolutePath());
            int exifOrientation = exif.getAttributeInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_NORMAL);
            int exifRotateDegree = exifOrientationToDegrees(exifOrientation);
            bitmap = rotateImage(bitmap, exifRotateDegree);
            saveBitmapToFile(bitmap);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    private Bitmap rotateImage(Bitmap bitmap, int degrees) {

        if ( degrees != 0 && bitmap != null ) {
            Matrix m = new Matrix();
            m.setRotate(degrees, (float) bitmap.getWidth() / 2, (float) bitmap.getHeight() / 2);
            try {
                Bitmap converted = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), m, true);
                if ( bitmap != converted ) {
                    bitmap.recycle();
                    bitmap = converted;
                }
            } catch (OutOfMemoryError ex) {
            }
        }
        return bitmap;
    }

    /**
     * EXIF정보를 회전각도로 변환하는 메서드
     *
     * @param exifOrientation EXIF 회전각
     *
     * @return 실제 각도
     */
    private int exifOrientationToDegrees(int exifOrientation) {

        if ( exifOrientation == ExifInterface.ORIENTATION_ROTATE_90 ) {
            return 90;
        } else if ( exifOrientation == ExifInterface.ORIENTATION_ROTATE_180 ) {
            return 180;
        } else if ( exifOrientation == ExifInterface.ORIENTATION_ROTATE_270 ) {
            return 270;
        }
        return 0;
    }

    /** 원하는 크기의 이미지로 options 설정. */
    private Bitmap loadImageWithSampleSize(File file) {

        BitmapFactory.Options options = new BitmapFactory.Options();
        options.inJustDecodeBounds = true;
        BitmapFactory.decodeFile(file.getAbsolutePath(), options);
        int width = options.outWidth;
        int height = options.outHeight;
        int longSide = Math.max(width, height);
        int sampleSize = 1;
        if ( longSide > mImageSizeBoundary ) {
            sampleSize = longSide / mImageSizeBoundary;
        }
        options.inJustDecodeBounds = false;
        options.inSampleSize = sampleSize;
        options.inPurgeable = true;
        options.inDither = false;

        Bitmap bitmap = BitmapFactory.decodeFile(file.getAbsolutePath(), options);
        return bitmap;
    }

    /**
     * mImageSizeBoundary 크기로 이미지 크기 조정. mImageSizeBoundary 보다 작은 경우 resize하지
     * 않음.
     */
    private Bitmap resizeImageWithinBoundary(Bitmap bitmap) {

        int width = bitmap.getWidth();
        int height = bitmap.getHeight();

        if ( width > height ) {
            if ( width > mImageSizeBoundary ) {
                bitmap = resizeBitmapWithWidth(bitmap, mImageSizeBoundary);
            }
        } else {
            if ( height > mImageSizeBoundary ) {
                bitmap = resizeBitmapWithHeight(bitmap, mImageSizeBoundary);
            }
        }
        return bitmap;
    }

    private Bitmap resizeBitmapWithHeight(Bitmap source, int wantedHeight) {

        if ( source == null )
            return null;

        int width = source.getWidth();
        int height = source.getHeight();

        float resizeFactor = wantedHeight * 1f / height;

        int targetWidth, targetHeight;
        targetWidth = (int) (width * resizeFactor);
        targetHeight = (int) (height * resizeFactor);

        Bitmap resizedBitmap = Bitmap.createScaledBitmap(source, targetWidth, targetHeight, true);

        return resizedBitmap;
    }

    private Bitmap resizeBitmapWithWidth(Bitmap source, int wantedWidth) {

        if ( source == null )
            return null;

        int width = source.getWidth();
        int height = source.getHeight();

        float resizeFactor = wantedWidth * 1f / width;

        int targetWidth, targetHeight;
        targetWidth = (int) (width * resizeFactor);
        targetHeight = (int) (height * resizeFactor);

        Bitmap resizedBitmap = Bitmap.createScaledBitmap(source, targetWidth, targetHeight, true);

        return resizedBitmap;
    }

    private String getPath(Uri uri) {

        String[] projection = {MediaStore.Images.Media.DATA};
        Cursor cursor = managedQuery(uri, projection, null, null, null);
        int column_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
        cursor.moveToFirst();
        return cursor.getString(column_index);
    }

    private void copyUriToFile(Uri srcUri, File target) {

        try {
            InputStream is;
            if ( srcUri.toString().startsWith("content://com.google.android.gallery3d") ) {
                is = getContentResolver().openInputStream(Uri.parse(getPath(srcUri)));
                Bitmap bmp = MediaStore.Images.Media.getBitmap(getContentResolver(), Uri.parse(getPath(srcUri)));
                FileOutputStream fileStream = new FileOutputStream(target);
                bmp.compress(Bitmap.CompressFormat.PNG, 100, fileStream);
                fileStream.close();
            } else {
                //                is = new URL(srcUri.toString()).openStream();
                is = getContentResolver().openInputStream(srcUri);
            }
            OutputStream os = new FileOutputStream(target);

            final int buffer_size = 1024;
            try {
                byte[] bytes = new byte[buffer_size];
                for (; ; ) {
                    int count = is.read(bytes, 0, buffer_size);
                    if ( count == -1 )
                        break;
                    os.write(bytes, 0, count);
                }
            } catch (Exception ex) {
            }
            os.close();
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }

    private void cropImage() {

        intent = new Intent("com.android.camera.action.CROP");
        intent.setType("image/*");
        List<ResolveInfo> cropToolLists = getPackageManager().queryIntentActivities(intent, 0);
        int size = cropToolLists.size();
        if ( size == 0 ) {
            // crop 을 처리할 앱이 없음. 곧바로 처리.
            doFinalProcess();
        } else {
            intent.setData(Uri.fromFile(getTempImageFile()));
            intent.putExtra("scale", true);
            intent.putExtra("aspectX", mCropAspectWidth);
            intent.putExtra("aspectY", mCropAspectHeight);
            intent.putExtra("scaleUpIfNeeded", true);
            intent.putExtra("noFaceDetection", true);
            intent.putExtra("output", Uri.fromFile(getTempImageFile()));
            Intent i = new Intent(intent);
            ResolveInfo res = cropToolLists.get(0);
            i.setComponent(new ComponentName(res.activityInfo.packageName, res.activityInfo.name));
            util.callActivityForResultNoAnim(act, i, REQ_CODE_PICK_CROP);
        }
    }

    @Override public void resultCustomDialogResponse(int iMsgID, int iBtnResult) {

        switch (iMsgID) {
            default:
                break;
        }
    }
}