package de.beyondsoft.ownchat.page.profile;

import de.beyondsoft.ownchat.R;
import de.beyondsoft.ownchat.data.AppPrefsConstants;
import de.beyondsoft.ownchat.data.api.common.ErrorHandlingResponseConverter;
import de.beyondsoft.ownchat.data.api.services.ProfileService;
import de.beyondsoft.ownchat.data.prefs.StringPreference;
import de.beyondsoft.ownchat.di.scopes.ActivityScope;
import de.beyondsoft.ownchat.model.User;
import de.beyondsoft.ownchat.page.mvp.MVPAbstractPresenter;
import de.beyondsoft.ownchat.utils.Constants;
import de.beyondsoft.ownchat.utils.FileUtils;
import de.beyondsoft.ownchat.utils.SystemUtils;
import de.beyondsoft.ownchat.utils.rx.RxUtils;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.net.Uri;
import android.support.annotation.NonNull;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;

import javax.inject.Inject;
import javax.inject.Named;

import okhttp3.MediaType;
import okhttp3.MultipartBody;
import okhttp3.RequestBody;
import rx.Subscription;

/**
 * Created by imarneanu on 2/22/17.
 */
@ActivityScope
class ProfilePresenter extends MVPAbstractPresenter<ProfileView> implements ProfileView.Callback {

    @Inject
    SystemUtils mSystemUtils;

    @Inject
    ProfileService mProfileService;

    @Inject
    @SuppressWarnings("WeakerAccess")
    @Named(AppPrefsConstants.LOGIN_TOKEN)
    StringPreference mToken;

    @Inject
    Context mContext;

    @Inject
    ProfilePresenter() {
    }

    @Override
    protected void afterAttachView(@NonNull ProfileView view) {
        super.afterAttachView(view);
        view.setCallback(this);
    }

    @Override
    protected void beforeDetachView(@NonNull ProfileView view) {
        view.setCallback(null);
        super.beforeDetachView(view);
    }

    /**
     * Get logged in user profile.
     */

    @Override
    public void getProfile() {
        Subscription subscription = mProfileService.getProfile()
                .compose(RxUtils.provideDefaultTransformer())
                .flatMap(new ErrorHandlingResponseConverter<>())
                .map(profileResponse -> profileResponse.response.user)
                .subscribe(this::getProfileSuccess, this::profileError);
        addSubscription(subscription);
    }

    /**
     * Update phoneNumber for the logged in user.
     */

    @Override
    public void updateProfile(String phoneNumber) {
        Subscription subscription = mProfileService.updateProfile(phoneNumber)
                .compose(RxUtils.provideDefaultTransformer())
                .flatMap(new ErrorHandlingResponseConverter<>())
                .map(profileResponse -> profileResponse.response.user)
                .subscribe(this::profileSuccess, this::profileError);
        addSubscription(subscription);
    }

    /**
     * Upload image for the current user.
     */

    @Override
    public void uploadImage(Uri uri) {
        if (mSystemUtils.isNetworkUnavailable()) {
            getView().showError(R.string.error_no_internet_connection);
            return;
        }

        File file = getView().getFile(uri);

        String tmpFileLocation = mContext.getExternalFilesDir(null) + "/tmp_" + file.getName();

        String mimeType = FileUtils.getMimeType(mContext, uri);

        if((mimeType.equals(Constants.MIME_TYPE_JPEG) || mimeType.equals(Constants.MIME_TYPE_PNG)) && (file.length() > (1000L * 1024L))) {
            try {
                BitmapFactory.Options options = new BitmapFactory.Options();

                Bitmap bitmapToScale = BitmapFactory.decodeFile(file.getPath(), options);

                int originalWidth = options.outWidth;
                int originalHeight = options.outHeight;

                int newHeight, newWidth;
                double aspectRatio = ((double) originalWidth) / ((double) originalHeight);

                if(originalHeight > originalWidth) {
                    aspectRatio = ((double) originalHeight) / ((double) originalWidth);
                    newWidth = 1080;
                    newHeight = (int) (newWidth * aspectRatio);
                } else {
                    newHeight = 1080;
                    newWidth = (int) (newHeight * aspectRatio);
                }

                Bitmap bitmap = Bitmap.createScaledBitmap(bitmapToScale, newWidth, newHeight, false);
                File tmpFile = new File(tmpFileLocation);
                tmpFile.createNewFile();

                ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
                bitmap.compress(Bitmap.CompressFormat.JPEG, 80, outputStream);
                FileOutputStream fileOutputStream = new FileOutputStream(tmpFile);
                fileOutputStream.write(outputStream.toByteArray());
                bitmap.recycle();
                fileOutputStream.flush();
                fileOutputStream.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

        File scaledImage = new File(tmpFileLocation);
        boolean scaledImageExists = scaledImage.exists();

        RequestBody requestBody = RequestBody.create(MediaType.parse("image/*"), scaledImageExists ? scaledImage : file);
        MultipartBody.Part part = MultipartBody.Part.createFormData("picture", file.getName(), requestBody);

        final Subscription subscription = mProfileService.uploadProfileImage(part)
                .compose(RxUtils.provideDefaultTransformer())
                .map(uploadImageResponse -> uploadImageResponse.response.picture)
                .subscribe(this::uploadImageSuccess, this::profileError);

        addSubscription(subscription);
    }

    private void profileError(Throwable throwable) {
        if (mSystemUtils.isNetworkUnavailable()) {
            getView().showError(R.string.error_no_internet_connection);
            return;
        }

        getView().showError(R.string.error_something_went_wrong);
    }

    private void getProfileSuccess(User user) {
        getView().setProfile(user);
    }

    private void profileSuccess(User user) {
        getView().setProfile(user);
        getView().showError(R.string.profile_updated);
    }

    private void uploadImageSuccess(String imageResponse) {
        getView().refreshImage(imageResponse);
        getView().showError(R.string.profile_updated);
    }

}
