package org.apache.fineract.ui.online.customers.customerprofile;

import android.Manifest;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.os.Bundle;
import android.provider.MediaStore;
import android.support.annotation.NonNull;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.ImageView;

import org.apache.fineract.R;
import org.apache.fineract.ui.base.FineractBaseActivity;
import org.apache.fineract.ui.base.Toaster;
import org.apache.fineract.ui.online.customers.customerprofile.editcustomerprofilebottomsheet
        .EditCustomerProfileBottomSheet;
import org.apache.fineract.ui.refreshcallback.RefreshProfileImage;
import org.apache.fineract.utils.CheckSelfPermissionAndRequest;
import org.apache.fineract.utils.ConstantKeys;
import org.apache.fineract.utils.ImageLoaderUtils;
import org.apache.fineract.utils.Utils;

import java.io.ByteArrayOutputStream;

import butterknife.BindView;
import butterknife.ButterKnife;

/**
 * @author Rajan Maurya
 *         On 06/08/17.
 */
public class CustomerProfileActivity extends FineractBaseActivity
        implements CustomerProfileContract.View, RefreshProfileImage {

    @BindView(R.id.iv_customer_picture)
    ImageView ivCustomerProfile;

    private String customerIdentifier;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_customer_profile);
        ButterKnife.bind(this);

        customerIdentifier = getIntent().getExtras().getString(ConstantKeys.CUSTOMER_IDENTIFIER);

        loadCustomerPortrait();

        showBackButton();
        setToolbarTitle(getString(R.string.customer_image));
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.menu_customer_profile, menu);
        Utils.setToolbarIconColor(this, menu, R.color.white);
        return super.onCreateOptionsMenu(menu);
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()) {
            case R.id.menu_customer_profile_edit:
                EditCustomerProfileBottomSheet profileBottomSheet =
                        new EditCustomerProfileBottomSheet();
                profileBottomSheet.setCustomerIdentifier(customerIdentifier);
                profileBottomSheet.setRefreshProfileImage(this);
                profileBottomSheet.show(getSupportFragmentManager(),
                        getString(R.string.customer_image));
                return true;
            case R.id.menu_customer_profile_share:
                checkCameraPermission();
                return true;
            default:
                return super.onOptionsItemSelected(item);
        }
    }

    public void shareImage() {
        Uri bitmapUri = getImageUri(this, getBitmapFromView(ivCustomerProfile));
        Intent shareIntent = new Intent(Intent.ACTION_SEND);
        shareIntent.setType("image/jpg");
        shareIntent.putExtra(Intent.EXTRA_STREAM, bitmapUri);
        startActivity(Intent.createChooser(shareIntent,
                getString(R.string.share_customer_profile)));
    }

    public static Bitmap getBitmapFromView(ImageView view) {
        Bitmap returnedBitmap = Bitmap.createBitmap(view.getWidth(),
                view.getHeight(), Bitmap.Config.ARGB_8888);
        Canvas canvas = new Canvas(returnedBitmap);
        Drawable bgDrawable = view.getBackground();
        if (bgDrawable != null) {
            bgDrawable.draw(canvas);
        } else {
            canvas.drawColor(Color.WHITE);
        }
        view.draw(canvas);
        return returnedBitmap;
    }

    public Uri getImageUri(Context inContext, Bitmap inImage) {
        ByteArrayOutputStream bytes = new ByteArrayOutputStream();
        inImage.compress(Bitmap.CompressFormat.JPEG, 100, bytes);
        String path = MediaStore.Images.Media.insertImage(inContext.getContentResolver(),
                inImage, customerIdentifier, null);
        return Uri.parse(path);
    }

    @Override
    public void checkCameraPermission() {
        if (CheckSelfPermissionAndRequest.checkSelfPermission(this,
                Manifest.permission.WRITE_EXTERNAL_STORAGE)) {
            shareImage();
        } else {
            requestPermission();
        }
    }

    @Override
    public void requestPermission() {
        CheckSelfPermissionAndRequest.requestPermission(
                this, Manifest.permission.WRITE_EXTERNAL_STORAGE,
                ConstantKeys.PERMISSION_REQUEST_WRITE_EXTERNAL_STORAGE,
                getResources().getString(
                        R.string.dialog_message_write_permission_for_share_denied_prompt),
                getResources().getString(
                        R.string.dialog_message_write_permission_for_share_never_ask_again),
                ConstantKeys.PERMISSIONS_WRITE_EXTERNAL_STORAGE_STATUS);
    }

    @Override
    public void loadCustomerPortrait() {
        ImageLoaderUtils imageLoaderUtils = new ImageLoaderUtils(this);
        imageLoaderUtils.loadImage(imageLoaderUtils.buildCustomerPortraitImageUrl(
                customerIdentifier), ivCustomerProfile, R.drawable.mifos_logo_new);
    }

    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions,
            @NonNull int[] grantResults) {
        switch (requestCode) {
            case ConstantKeys.PERMISSIONS_REQUEST_CAMERA: {
                if (grantResults.length > 0
                        && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                    shareImage();
                } else {
                    Toaster.show(findViewById(android.R.id.content),
                            getString(R.string.permission_denied_write));
                }
            }
        }
    }

    @Override
    public void refreshUI() {
        loadCustomerPortrait();
    }

    @Override
    public void showNoInternetConnection() {
    }

    @Override
    public void showError(String message) {
    }
}
