/*
 *  Copyright (C) 2004-2020 Savoir-faire Linux Inc.
 *
 *  Author: Adrien Béraud <adrien.beraud@savoirfairelinux.com>
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 3 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */
package cx.ring.fragments;

import android.Manifest;
import android.animation.LayoutTransition;
import android.animation.ValueAnimator;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.ActivityNotFoundException;
import android.content.ClipData;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.content.SharedPreferences;
import android.content.pm.PackageManager;
import android.graphics.Typeface;
import android.content.res.Resources;
import android.os.Bundle;
import android.os.Environment;
import android.os.IBinder;
import android.provider.MediaStore;
import android.text.Editable;
import android.text.TextUtils;
import android.text.TextWatcher;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.view.WindowManager;
import android.view.inputmethod.EditorInfo;
import android.widget.ImageView;
import android.widget.RelativeLayout;
import android.widget.Spinner;
import android.widget.TextView;
import android.widget.Toast;

import com.google.android.material.snackbar.Snackbar;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.ActionBar;
import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.view.menu.MenuBuilder;
import androidx.appcompat.view.menu.MenuPopupHelper;
import androidx.appcompat.widget.PopupMenu;
import androidx.appcompat.widget.Toolbar;
import androidx.core.view.ViewCompat;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentManager;
import androidx.recyclerview.widget.DefaultItemAnimator;

import java.io.File;
import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import cx.ring.BuildConfig;
import cx.ring.R;
import cx.ring.adapters.ConversationAdapter;
import cx.ring.adapters.NumberAdapter;
import cx.ring.application.JamiApplication;
import cx.ring.client.CallActivity;
import cx.ring.client.ContactDetailsActivity;
import cx.ring.client.ConversationActivity;
import cx.ring.client.HomeActivity;
import cx.ring.contacts.AvatarFactory;
import cx.ring.conversation.ConversationPresenter;
import cx.ring.conversation.ConversationView;
import cx.ring.databinding.FragConversationBinding;
import cx.ring.interfaces.Colorable;
import cx.ring.model.Account;
import cx.ring.model.CallContact;
import cx.ring.model.Conversation;
import cx.ring.model.Interaction;
import cx.ring.model.DataTransfer;
import cx.ring.model.Phone;
import cx.ring.model.Error;
import cx.ring.model.Uri;
import cx.ring.mvp.BaseSupportFragment;
import cx.ring.services.LocationSharingService;
import cx.ring.services.NotificationService;
import cx.ring.services.NotificationServiceImpl;
import cx.ring.utils.ActionHelper;
import cx.ring.utils.AndroidFileUtils;
import cx.ring.utils.ContentUriHandler;
import cx.ring.utils.DeviceUtils;
import cx.ring.utils.ConversationPath;
import cx.ring.utils.MediaButtonsHelper;
import cx.ring.views.AvatarDrawable;
import io.reactivex.Completable;
import io.reactivex.Single;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.disposables.CompositeDisposable;

import static android.app.Activity.RESULT_OK;

public class ConversationFragment extends BaseSupportFragment<ConversationPresenter> implements
        MediaButtonsHelper.MediaButtonsHelperCallback,
        ConversationView, SharedPreferences.OnSharedPreferenceChangeListener {
    private static final String TAG = ConversationFragment.class.getSimpleName();

    public static final int REQ_ADD_CONTACT = 42;

    public static final String KEY_CONTACT_RING_ID = BuildConfig.APPLICATION_ID + ".CONTACT_RING_ID";
    public static final String KEY_ACCOUNT_ID = BuildConfig.APPLICATION_ID + ".ACCOUNT_ID";
    public static final String KEY_PREFERENCE_PENDING_MESSAGE = "pendingMessage";
    public static final String KEY_PREFERENCE_CONVERSATION_COLOR = "color";
    public static final String EXTRA_SHOW_MAP = "showMap";

    private static final int REQUEST_CODE_FILE_PICKER = 1000;
    private static final int REQUEST_PERMISSION_CAMERA = 1001;
    private static final int REQUEST_CODE_TAKE_PICTURE = 1002;
    private static final int REQUEST_CODE_SAVE_FILE = 1003;
    private static final int REQUEST_CODE_CAPTURE_AUDIO = 1004;
    private static final int REQUEST_CODE_CAPTURE_VIDEO = 1005;

    private ServiceConnection locationServiceConnection = null;

    private FragConversationBinding binding;
    private MenuItem mAudioCallBtn = null;
    private MenuItem mVideoCallBtn = null;

    private View currentBottomView = null;
    private ConversationAdapter mAdapter = null;
    private int marginPx;
    private int marginPxTotal;
    private final ValueAnimator animation = new ValueAnimator();

    private SharedPreferences mPreferences;

    private File mCurrentPhoto = null;
    private String mCurrentFileAbsolutePath = null;
    private final CompositeDisposable mCompositeDisposable = new CompositeDisposable();
    private int mSelectedPosition;

    private boolean mIsBubble;

    private AvatarDrawable mConversationAvatar;
    private final Map<String, AvatarDrawable> mParticipantAvatars = new HashMap<>();
    private final Map<String, AvatarDrawable> mSmallParticipantAvatars = new HashMap<>();
    private int mapWidth, mapHeight;

    public AvatarDrawable getConversationAvatar(String uri) {
        return mParticipantAvatars.get(uri);
    }
    public AvatarDrawable getSmallConversationAvatar(String uri) {
        synchronized (mSmallParticipantAvatars) {
            return mSmallParticipantAvatars.get(uri);
        }
    }

    private static int getIndex(Spinner spinner, Uri myString) {
        for (int i = 0, n = spinner.getCount(); i < n; i++)
            if (((Phone) spinner.getItemAtPosition(i)).getNumber().equals(myString)) {
                return i;
            }
        return 0;
    }

    @Override
    public void refreshView(final List<Interaction> conversation) {
        if (conversation == null) {
            return;
        }
        if (binding != null)
            binding.pbLoading.setVisibility(View.GONE);
        if (mAdapter != null) {
            mAdapter.updateDataset(conversation);
        }
        requireActivity().invalidateOptionsMenu();
    }

    @Override
    public void scrollToEnd() {
        if (mAdapter.getItemCount() > 0) {
            binding.histList.scrollToPosition(mAdapter.getItemCount() - 1);
        }
    }

    private static void setBottomPadding(@NonNull View view, int padding) {
        view.setPadding(
                view.getPaddingLeft(),
                view.getPaddingTop(),
                view.getPaddingRight(),
                padding);
    }

    private void updateListPadding() {
        if (currentBottomView != null && currentBottomView.getHeight() != 0) {
            setBottomPadding(binding.histList, currentBottomView.getHeight() + marginPxTotal);
            RelativeLayout.LayoutParams params = (RelativeLayout.LayoutParams) binding.mapCard.getLayoutParams();
            params.bottomMargin = currentBottomView.getHeight() + marginPxTotal;
            binding.mapCard.setLayoutParams(params);
        }
    }

    @Nullable
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        ((JamiApplication) getActivity().getApplication()).getInjectionComponent().inject(this);
        Resources res = getResources();
        marginPx = res.getDimensionPixelSize(R.dimen.conversation_message_input_margin);
        mapWidth = res.getDimensionPixelSize(R.dimen.location_sharing_minmap_width);
        mapHeight = res.getDimensionPixelSize(R.dimen.location_sharing_minmap_height);
        marginPxTotal = marginPx;

        binding = FragConversationBinding.inflate(inflater, container, false);
        binding.setPresenter(this);

        animation.setDuration(150);
        animation.addUpdateListener(valueAnimator -> setBottomPadding(binding.histList, (Integer)valueAnimator.getAnimatedValue()));

        ViewCompat.setOnApplyWindowInsetsListener(binding.histList, (v, insets) -> {
            marginPxTotal = marginPx + insets.getSystemWindowInsetBottom();
            updateListPadding();
            insets.consumeSystemWindowInsets();
            return insets;
        });
        View layout = binding.conversationLayout;

        // remove action bar height for tablet layout
        if (DeviceUtils.isTablet(getContext())) {
            layout.setPadding(layout.getPaddingLeft(), 0, layout.getPaddingRight(), layout.getPaddingBottom());
        }

        int paddingTop = layout.getPaddingTop();
        ViewCompat.setOnApplyWindowInsetsListener(layout, (v, insets) -> {
            v.setPadding(
                    v.getPaddingLeft(),
                    paddingTop + insets.getSystemWindowInsetTop(),
                    v.getPaddingRight(),
                    v.getPaddingBottom());
            insets.consumeSystemWindowInsets();
            return insets;
        });

        binding.ongoingcallPane.setVisibility(View.GONE);
        binding.msgInputTxt.setMediaListener(contentInfo -> startFileSend(AndroidFileUtils
                .getCacheFile(requireContext(), contentInfo.getContentUri())
                .flatMapCompletable(this::sendFile)
                .doFinally(contentInfo::releasePermission)));
        binding.msgInputTxt.setOnEditorActionListener((v, actionId, event) -> actionSendMsgText(actionId));
        binding.msgInputTxt.setOnFocusChangeListener((view, hasFocus) -> {
            if (hasFocus)  {
                Fragment fragment = getChildFragmentManager().findFragmentById(R.id.mapLayout);
                if (fragment != null) {
                    ((LocationSharingFragment) fragment).hideControls();
                }
            }
        });
        binding.msgInputTxt.addTextChangedListener(new TextWatcher() {
            @Override
            public void beforeTextChanged(CharSequence s, int start, int count, int after) {
            }

            @Override
            public void onTextChanged(CharSequence s, int start, int before, int count) {
            }

            @Override
            public void afterTextChanged(Editable s) {
                String message = s.toString();
                boolean hasMessage = !TextUtils.isEmpty(message);
                presenter.onComposingChanged(hasMessage);
                if (hasMessage) {
                    binding.msgSend.setVisibility(View.VISIBLE);
                    binding.emojiSend.setVisibility(View.GONE);
                } else {
                    binding.msgSend.setVisibility(View.GONE);
                    binding.emojiSend.setVisibility(View.VISIBLE);
                }
                if (mPreferences != null) {
                    if (hasMessage)
                        mPreferences.edit().putString(KEY_PREFERENCE_PENDING_MESSAGE, message).apply();
                    else
                        mPreferences.edit().remove(KEY_PREFERENCE_PENDING_MESSAGE).apply();
                }
            }
        });

        setHasOptionsMenu(true);
        return binding.getRoot();
    }

    @Override
    public void onViewCreated(@NonNull View view, Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);
        if (mPreferences != null) {
            String pendingMessage = mPreferences.getString(KEY_PREFERENCE_PENDING_MESSAGE, null);
            if (!TextUtils.isEmpty(pendingMessage)) {
                binding.msgInputTxt.setText(pendingMessage);
                binding.msgSend.setVisibility(View.VISIBLE);
                binding.emojiSend.setVisibility(View.GONE);
            }
        }

        binding.msgInputTxt.addOnLayoutChangeListener((v, left, top, right, bottom, oldLeft, oldTop, oldRight, oldBottom) -> {
            if (oldBottom == 0 && oldTop == 0) {
                updateListPadding();
            } else {
                if (animation.isStarted())
                    animation.cancel();
                animation.setIntValues(binding.histList.getPaddingBottom(), (currentBottomView == null ? 0 : currentBottomView.getHeight()) + marginPxTotal);
                animation.start();
            }
        });

        DefaultItemAnimator animator = (DefaultItemAnimator) binding.histList.getItemAnimator();
        if (animator != null)
            animator.setSupportsChangeAnimations(false);
        binding.histList.setAdapter(mAdapter);

        if (presenter.isRecordingBlocked()) {
            getActivity().getWindow().setFlags(WindowManager.LayoutParams.FLAG_SECURE, WindowManager.LayoutParams.FLAG_SECURE);
        }
    }

    @Override
    public void setConversationColor(int color) {
        Colorable activity = (Colorable) getActivity();
        if (activity != null)
            activity.setColor(color);
        mAdapter.setPrimaryColor(color);
    }

    @Override
    public void onDestroyView() {
        if (mPreferences != null)
            mPreferences.unregisterOnSharedPreferenceChangeListener(this);
        animation.removeAllUpdateListeners();
        binding.histList.setAdapter(null);
        mCompositeDisposable.clear();
        if (locationServiceConnection != null) {
            try {
                requireContext().unbindService(locationServiceConnection);
            } catch (Exception e) {
                Log.w(TAG, "Error unbinding service: " + e.getMessage());
            }
        }
        mAdapter = null;
        super.onDestroyView();
        binding = null;
    }

    @Override
    public boolean onContextItemSelected(@NonNull MenuItem item) {
        if (mAdapter.onContextItemSelected(item))
            return true;
        return super.onContextItemSelected(item);
    }

    public void updateAdapterItem() {
        if (mSelectedPosition != -1) {
            mAdapter.notifyItemChanged(mSelectedPosition);
            mSelectedPosition = -1;
        }
    }

    public void sendMessageText() {
        String message = binding.msgInputTxt.getText().toString();
        clearMsgEdit();
        presenter.sendTextMessage(message);
    }

    public void sendEmoji() {
        presenter.sendTextMessage(binding.emojiSend.getText().toString());
    }

    @SuppressLint("RestrictedApi")
    public void expandMenu(View v) {
        Context context = requireContext();
        PopupMenu popup = new PopupMenu(context, v);
        popup.inflate(R.menu.conversation_share_actions);
        popup.setOnMenuItemClickListener(item -> {
            switch(item.getItemId()) {
                case R.id.conv_send_audio:
                    sendAudioMessage();
                    break;
                case R.id.conv_send_video:
                    sendVideoMessage();
                    break;
                case R.id.conv_send_file:
                    presenter.selectFile();
                    break;
                case R.id.conv_share_location:
                    shareLocation();
                    break;
            }
            return false;
        });
        MenuPopupHelper menuHelper = new MenuPopupHelper(context, (MenuBuilder) popup.getMenu(), v);
        menuHelper.setForceShowIcon(true);
        menuHelper.show();
    }

    public void shareLocation() {
        presenter.shareLocation();
    }

    public void closeLocationSharing(boolean isSharing) {
        RelativeLayout.LayoutParams params = (RelativeLayout.LayoutParams) binding.mapCard.getLayoutParams();
        if (params.width != mapWidth) {
            params.width = mapWidth;
            params.height = mapHeight;
            binding.mapCard.setLayoutParams(params);
        }
        if (!isSharing)
            hideMap();
    }

    public void openLocationSharing() {
        binding.conversationLayout.getLayoutTransition().enableTransitionType(LayoutTransition.CHANGING);
        RelativeLayout.LayoutParams params = (RelativeLayout.LayoutParams) binding.mapCard.getLayoutParams();
        if (params.width != ViewGroup.LayoutParams.MATCH_PARENT) {
            params.width = ViewGroup.LayoutParams.MATCH_PARENT;
            params.height = ViewGroup.LayoutParams.MATCH_PARENT;
            binding.mapCard.setLayoutParams(params);
        }
    }

    @Override
    public void startShareLocation(String accountId, String conversationId) {
        showMap(accountId, conversationId, true);
    }

    /**
     * Used to update with the past adapter position when a long click was registered
     */
    public void updatePosition(int position) {
        mSelectedPosition = position;
    }

    @Override
    public void showMap(String accountId, String contactId, boolean open)  {
        if (binding.mapCard.getVisibility() == View.GONE) {
            Log.w(TAG, "showMap " + accountId + " " + contactId);

            FragmentManager fragmentManager = getChildFragmentManager();
            LocationSharingFragment fragment = LocationSharingFragment.newInstance(accountId, contactId, open);
            fragmentManager.beginTransaction()
                    .add(R.id.mapLayout, fragment, "map")
                    .commit();
            binding.mapCard.setVisibility(View.VISIBLE);
        }
        if (open) {
            Fragment fragment = getChildFragmentManager().findFragmentById(R.id.mapLayout);
            if (fragment != null) {
                ((LocationSharingFragment) fragment).showControls();
            }
        }
    }

    @Override
    public void hideMap() {
        if (binding.mapCard.getVisibility() != View.GONE) {
            binding.mapCard.setVisibility(View.GONE);

            FragmentManager fragmentManager = getChildFragmentManager();
            Fragment fragment = fragmentManager.findFragmentById(R.id.mapLayout);

            if (fragment != null) {
                fragmentManager.beginTransaction()
                        .remove(fragment)
                        .commit();
            }
        }
    }

    public void sendAudioMessage() {
        if (!presenter.getDeviceRuntimeService().hasAudioPermission()) {
            requestPermissions(new String[]{Manifest.permission.RECORD_AUDIO}, REQUEST_CODE_CAPTURE_AUDIO);
        } else {
            Context ctx = requireContext();
            Intent intent = new Intent(MediaStore.Audio.Media.RECORD_SOUND_ACTION);

            if (intent.resolveActivity(ctx.getPackageManager()) != null) {
                try {
                    mCurrentPhoto = AndroidFileUtils.createAudioFile(ctx);
                } catch (IOException ex) {
                    Log.e(TAG, "takePicture: error creating temporary file", ex);
                    return;
                }
                startActivityForResult(intent, REQUEST_CODE_CAPTURE_AUDIO);
            } else {
                Toast.makeText(getActivity(), "Can't find audio recorder app", Toast.LENGTH_SHORT).show();
            }
        }
    }

    public void sendVideoMessage() {
        if (!presenter.getDeviceRuntimeService().hasVideoPermission()) {
            requestPermissions(new String[]{Manifest.permission.CAMERA}, REQUEST_CODE_CAPTURE_VIDEO);
        } else {
            Context context = requireContext();
            Intent intent = new Intent(MediaStore.ACTION_VIDEO_CAPTURE);
            intent.putExtra("android.intent.extras.CAMERA_FACING", android.hardware.Camera.CameraInfo.CAMERA_FACING_FRONT);
            intent.putExtra("android.intent.extras.LENS_FACING_FRONT", 1);
            intent.putExtra("android.intent.extra.USE_FRONT_CAMERA", true);
            if (intent.resolveActivity(context.getPackageManager()) != null) {
                try {
                    mCurrentPhoto = AndroidFileUtils.createVideoFile(context);
                } catch (IOException ex) {
                    Log.e(TAG, "takePicture: error creating temporary file", ex);
                    return;
                }
                intent.putExtra(MediaStore.EXTRA_OUTPUT, ContentUriHandler.getUriForFile(context, ContentUriHandler.AUTHORITY_FILES, mCurrentPhoto));
                startActivityForResult(intent, REQUEST_CODE_CAPTURE_VIDEO);
            } else {
                Toast.makeText(getActivity(), "Can't find video recorder app", Toast.LENGTH_SHORT).show();
            }
        }
    }

    public void takePicture() {
        if (!presenter.getDeviceRuntimeService().hasVideoPermission()) {
            requestPermissions(new String[]{Manifest.permission.CAMERA}, REQUEST_CODE_TAKE_PICTURE);
            return;
        }
        Context c = getContext();
        if (c == null)
            return;
        try {
            File photoFile = AndroidFileUtils.createImageFile(c);
            Log.i(TAG, "takePicture: trying to save to " + photoFile);
            android.net.Uri photoURI = ContentUriHandler.getUriForFile(c, ContentUriHandler.AUTHORITY_FILES, photoFile);
            Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE).putExtra(MediaStore.EXTRA_OUTPUT, photoURI)
                    .putExtra("android.intent.extras.CAMERA_FACING", 1)
                    .putExtra("android.intent.extras.LENS_FACING_FRONT", 1)
                    .putExtra("android.intent.extra.USE_FRONT_CAMERA", true);
            mCurrentPhoto = photoFile;
            startActivityForResult(takePictureIntent, REQUEST_CODE_TAKE_PICTURE);
        } catch (Exception e) {
            Toast.makeText(c, "Error taking picture: " + e.getLocalizedMessage(), Toast.LENGTH_SHORT).show();
        }
    }

    @Override
    public void askWriteExternalStoragePermission() {
        requestPermissions(new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, JamiApplication.PERMISSIONS_REQUEST);
    }

    @Override
    public void openFilePicker() {
        Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
        intent.addCategory(Intent.CATEGORY_OPENABLE);
        intent.setType("*/*");

        startActivityForResult(intent, REQUEST_CODE_FILE_PICKER);
    }

    private Completable sendFile(File file) {
        return Completable.fromAction(() -> presenter.sendFile(file));
    }

    private void startFileSend(Completable op) {
        setLoading(true);
        op.observeOn(AndroidSchedulers.mainThread())
                .doFinally(() -> setLoading(false))
                .subscribe(() -> {}, e -> {
                    Log.e(TAG, "startFileSend: not able to create cache file", e);
                    displayErrorToast(Error.INVALID_FILE);
                });
    }

    @Override
    public void onActivityResult(int requestCode, int resultCode, @Nullable Intent resultData) {
        Log.w(TAG, "onActivityResult: " + requestCode + " " + resultCode + " " + resultData);
        android.net.Uri uri = resultData == null ? null : resultData.getData();
        if (requestCode == REQUEST_CODE_FILE_PICKER) {
            if (resultCode == RESULT_OK && uri != null) {
                startFileSend(AndroidFileUtils.getCacheFile(requireContext(), uri)
                        .observeOn(AndroidSchedulers.mainThread())
                        .flatMapCompletable(this::sendFile));
            }
        } else if (requestCode == REQUEST_CODE_TAKE_PICTURE
                || requestCode == REQUEST_CODE_CAPTURE_AUDIO
                || requestCode == REQUEST_CODE_CAPTURE_VIDEO)
        {
            if (resultCode != RESULT_OK) {
                mCurrentPhoto = null;
                return;
            }
            Log.w(TAG, "onActivityResult: mCurrentPhoto " + mCurrentPhoto.getAbsolutePath() + " " + mCurrentPhoto.exists() + " " + mCurrentPhoto.length());
            Single<File> file = null;
            if (mCurrentPhoto == null || !mCurrentPhoto.exists() || mCurrentPhoto.length() == 0) {
                if (uri != null) {
                    file = AndroidFileUtils.getCacheFile(requireContext(), uri);
                }
            } else {
                file = Single.just(mCurrentPhoto);
            }
            mCurrentPhoto = null;
            if (file == null) {
                Toast.makeText(getActivity(), "Can't find picture", Toast.LENGTH_SHORT).show();
                return;
            }
            startFileSend(file.flatMapCompletable(this::sendFile));
        }
        // File download trough SAF
        else if (requestCode == ConversationFragment.REQUEST_CODE_SAVE_FILE) {
            if (resultCode == RESULT_OK &&  uri != null) {
                writeToFile(uri);
            }
        }
    }

    private void writeToFile(android.net.Uri data) {
        File input = new File(mCurrentFileAbsolutePath);
        if (requireContext().getContentResolver() != null)
            mCompositeDisposable.add(AndroidFileUtils.copyFileToUri(requireContext().getContentResolver(), input, data).
                    observeOn(AndroidSchedulers.mainThread()).
                    subscribe(() -> Toast.makeText(getContext(), R.string.file_saved_successfully, Toast.LENGTH_SHORT).show(),
                            error -> Toast.makeText(getContext(), R.string.generic_error, Toast.LENGTH_SHORT).show()));
    }

    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        for (int i = 0, n = permissions.length; i < n; i++) {
            boolean granted = grantResults[i] == PackageManager.PERMISSION_GRANTED;
            switch (permissions[i]) {
                case Manifest.permission.CAMERA:
                    presenter.cameraPermissionChanged(granted);
                    if (granted) {
                        if (requestCode == REQUEST_CODE_CAPTURE_VIDEO) {
                            sendVideoMessage();
                        } else if (requestCode == REQUEST_CODE_TAKE_PICTURE) {
                            takePicture();
                        }
                    }
                    return;
                case Manifest.permission.RECORD_AUDIO:
                    if (granted) {
                        if (requestCode == REQUEST_CODE_CAPTURE_AUDIO) {
                            sendAudioMessage();
                        }
                    }
                    return;
                default:
                    break;
            }
        }
    }

    @Override
    public void addElement(Interaction element) {
        mAdapter.add(element);
        scrollToEnd();
    }

    @Override
    public void updateElement(Interaction element) {
        mAdapter.update(element);
    }

    @Override
    public void removeElement(Interaction element) {
        mAdapter.remove(element);
    }

    @Override
    public void setComposingStatus(Account.ComposingStatus composingStatus) {
        mAdapter.setComposingStatus(composingStatus);
        if (composingStatus == Account.ComposingStatus.Active)
            scrollToEnd();
    }

    @Override
    public void setLastDisplayed(Interaction interaction) {
        mAdapter.setLastDisplayed(interaction);
    }

    @Override
    public void shareFile(File path) {
        Context c = getContext();
        if (c == null)
            return;
        android.net.Uri fileUri = null;
        try {
            fileUri = ContentUriHandler.getUriForFile(c, ContentUriHandler.AUTHORITY_FILES, path);
        } catch (IllegalArgumentException e) {
            Log.e("File Selector", "The selected file can't be shared: " + path.getName());
        }
        if (fileUri != null) {
            Intent sendIntent = new Intent();
            sendIntent.setAction(Intent.ACTION_SEND);
            sendIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
            String type = c.getContentResolver().getType(fileUri);
            sendIntent.setDataAndType(fileUri, type);
            sendIntent.putExtra(Intent.EXTRA_STREAM, fileUri);
            startActivity(Intent.createChooser(sendIntent, null));
        }
    }

    @Override
    public void openFile(File path) {
        Context c = getContext();
        if (c == null)
            return;
        android.net.Uri fileUri = null;
        try {
            fileUri = ContentUriHandler.getUriForFile(c, ContentUriHandler.AUTHORITY_FILES, path);
        } catch (IllegalArgumentException e) {
            Log.e("File Selector", "The selected file can't be shared: " + path.getName());
        }
        if (fileUri != null) {
            Intent sendIntent = new Intent();
            sendIntent.setAction(Intent.ACTION_VIEW);
            sendIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
            String type = c.getContentResolver().getType(fileUri);
            sendIntent.setDataAndType(fileUri, type);
            sendIntent.putExtra(Intent.EXTRA_STREAM, fileUri);
            //startActivity(Intent.createChooser(sendIntent, null));
            try {
                startActivity(sendIntent);
            } catch (ActivityNotFoundException e) {
                Snackbar.make(getView(), R.string.conversation_open_file_error, Snackbar.LENGTH_LONG).show();
                Log.e("File Loader", "File of unknown type, could not open: " + path.getName());
            }
        }
    }

    boolean actionSendMsgText(int actionId) {
        switch (actionId) {
            case EditorInfo.IME_ACTION_SEND:
                sendMessageText();
                return true;
        }
        return false;
    }

    public void onClick() {
        presenter.clickOnGoingPane();
    }

    @Override
    public void onPause() {
        super.onPause();
        presenter.pause();
    }

    @Override
    public void onResume() {
        super.onResume();
        presenter.resume(mIsBubble);
    }

    @Override
    public void onDestroy() {
        mCompositeDisposable.dispose();
        super.onDestroy();
    }

    @Override
    public void onCreateOptionsMenu(@NonNull Menu menu, @NonNull MenuInflater inflater) {
        if (!isVisible()) {
            return;
        }
        inflater.inflate(R.menu.conversation_actions, menu);
        mAudioCallBtn = menu.findItem(R.id.conv_action_audiocall);
        mVideoCallBtn = menu.findItem(R.id.conv_action_videocall);
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()) {
            case android.R.id.home:
                startActivity(new Intent(getActivity(), HomeActivity.class));
                return true;
            case R.id.conv_action_audiocall:
                presenter.goToCall(true);
                return true;
            case R.id.conv_action_videocall:
                presenter.goToCall(false);
                return true;
            case R.id.conv_contact_details:
                presenter.openContact();
                return true;
            default:
                return super.onOptionsItemSelected(item);
        }
    }

    @Override
    protected void initPresenter(ConversationPresenter presenter) {
        ConversationPath path = ConversationPath.fromBundle(getArguments());
        mIsBubble = getArguments().getBoolean(NotificationServiceImpl.EXTRA_BUBBLE);
        if (path == null)
            return;

        Uri contactUri = path.getConversationUri();
        mAdapter = new ConversationAdapter(this, presenter);
        presenter.init(contactUri, path.getAccountId());
        try {
            mPreferences = requireActivity().getSharedPreferences(path.getAccountId() + "_" + contactUri.getRawRingId(), Context.MODE_PRIVATE);
            mPreferences.registerOnSharedPreferenceChangeListener(this);
            presenter.setConversationColor(mPreferences.getInt(KEY_PREFERENCE_CONVERSATION_COLOR, getResources().getColor(R.color.color_primary_light)));
        } catch (Exception e) {
            Log.e(TAG, "Can't load conversation preferences");
        }

        if (locationServiceConnection == null) {
            locationServiceConnection = new ServiceConnection() {
                @Override
                public void onServiceConnected(ComponentName name, IBinder service) {
                    Log.w(TAG, "onServiceConnected");
                    LocationSharingService.LocalBinder binder = (LocationSharingService.LocalBinder) service;
                    LocationSharingService locationService = binder.getService();
                    ConversationPath path = new ConversationPath(presenter.getPath());
                    if (locationService.isSharing(path)) {
                        showMap(path.getAccountId(), contactUri.getUri(), false);
                    }
                    try {
                        requireContext().unbindService(locationServiceConnection);
                    } catch (Exception e) {
                        Log.w(TAG, "Error unbinding service", e);
                    }
                }

                @Override
                public void onServiceDisconnected(ComponentName name) {
                    Log.w(TAG, "onServiceDisconnected");
                    locationServiceConnection = null;
                }
            };

            Log.w(TAG, "bindService");
            requireContext().bindService(new Intent(requireContext(), LocationSharingService.class), locationServiceConnection, 0);
        }
    }

    @Override
    public void onSharedPreferenceChanged(SharedPreferences prefs, String key) {
        switch (key) {
            case KEY_PREFERENCE_CONVERSATION_COLOR:
                presenter.setConversationColor(prefs.getInt(KEY_PREFERENCE_CONVERSATION_COLOR, getResources().getColor(R.color.color_primary_light)));
                break;
        }
    }

    @Override
    public void displayContact(final CallContact contact) {
        mCompositeDisposable.clear();
        mCompositeDisposable.add(AvatarFactory.getAvatar(requireContext(), contact)
                .doOnSuccess(d -> {
                    mConversationAvatar = (AvatarDrawable) d;
                    mParticipantAvatars.put(contact.getPrimaryNumber(),
                            new AvatarDrawable((AvatarDrawable) d));
                })
                .flatMapObservable(d -> contact.getUpdatesSubject())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(c -> {
                    mConversationAvatar.update(c);
                    String uri = contact.getPrimaryNumber();
                    AvatarDrawable ad = mParticipantAvatars.get(uri);
                    if (ad != null)
                        ad.update(c);
                    setupActionbar(contact);
                    mAdapter.setPhoto();
                }));
        mCompositeDisposable.add(AvatarFactory.getAvatar(requireContext(), contact, false)
                .doOnSuccess(d -> mSmallParticipantAvatars.put(contact.getPrimaryNumber(), new AvatarDrawable((AvatarDrawable) d)))
                .flatMapObservable(d -> contact.getUpdatesSubject())
                .subscribe(c -> {
                    synchronized (mSmallParticipantAvatars) {
                        String uri = contact.getPrimaryNumber();
                        AvatarDrawable ad = mSmallParticipantAvatars.get(uri);
                        if (ad != null)
                            ad.update(c);
                    }
                }));
    }

    @Override
    public void displayOnGoingCallPane(final boolean display) {
        binding.ongoingcallPane.setVisibility(display ? View.VISIBLE : View.GONE);
    }

    @Override
    public void displayNumberSpinner(final Conversation conversation, final Uri number) {
        binding.numberSelector.setVisibility(View.VISIBLE);
        binding.numberSelector.setAdapter(new NumberAdapter(getActivity(),
                conversation.getContact(), false));
        binding.numberSelector.setSelection(getIndex(binding.numberSelector, number));
    }

    @Override
    public void hideNumberSpinner() {
        binding.numberSelector.setVisibility(View.GONE);
    }

    @Override
    public void clearMsgEdit() {
        binding.msgInputTxt.setText("");
    }

    @Override
    public void goToHome() {
        if (getActivity() instanceof ConversationActivity) {
            getActivity().finish();
        }
    }

    @Override
    public void goToAddContact(CallContact callContact) {
        startActivityForResult(ActionHelper.getAddNumberIntentForContact(callContact), REQ_ADD_CONTACT);
    }

    @Override
    public void goToCallActivity(String conferenceId) {
        startActivity(new Intent(Intent.ACTION_VIEW)
                .setClass(requireActivity().getApplicationContext(), CallActivity.class)
                .putExtra(NotificationService.KEY_CALL_ID, conferenceId));
    }

    @Override
    public void goToContactActivity(String accountId, String contactId) {
        startActivity(new Intent(Intent.ACTION_VIEW, ConversationPath.toUri(accountId, contactId),
                requireActivity().getApplicationContext(), ContactDetailsActivity.class));
    }

    @Override
    public void goToCallActivityWithResult(String accountId, String contactRingId, boolean audioOnly) {
        Intent intent = new Intent(CallActivity.ACTION_CALL)
                .setClass(requireActivity().getApplicationContext(), CallActivity.class)
                .putExtra(KEY_ACCOUNT_ID, accountId)
                .putExtra(CallFragment.KEY_AUDIO_ONLY, audioOnly)
                .putExtra(KEY_CONTACT_RING_ID, contactRingId);
        startActivityForResult(intent, HomeActivity.REQUEST_CODE_CALL);
    }

    private void setupActionbar(CallContact contact) {
        if (!isVisible()) {
            return;
        }

        ActionBar actionBar = ((AppCompatActivity) requireActivity()).getSupportActionBar();
        if (actionBar == null) {
            return;
        }

        Context context = actionBar.getThemedContext();
        String displayName = contact.getDisplayName();
        String identity = contact.getRingUsername();

        Activity activity = getActivity();
        if (activity instanceof HomeActivity) {
            Toolbar toolbar = getActivity().findViewById(R.id.main_toolbar);
            TextView title = toolbar.findViewById(R.id.contact_title);
            TextView subtitle = toolbar.findViewById(R.id.contact_subtitle);
            ImageView logo = toolbar.findViewById(R.id.contact_image);

            if (!((HomeActivity) activity).isConversationSelected()) {
                title.setText("");
                subtitle.setText("");
                logo.setImageDrawable(null);
                return;
            }

            logo.setVisibility(View.VISIBLE);
            title.setText(displayName);
            title.setTextSize(15);
            title.setTypeface(null, Typeface.NORMAL);

            if (identity != null && !identity.equals(displayName)) {
                subtitle.setText(identity);

                RelativeLayout.LayoutParams params = (RelativeLayout.LayoutParams) title.getLayoutParams();
                params.addRule(RelativeLayout.ALIGN_TOP, R.id.contact_image);
                title.setLayoutParams(params);
            } else {
                subtitle.setText("");

                RelativeLayout.LayoutParams params = (RelativeLayout.LayoutParams) title.getLayoutParams();
                params.removeRule(RelativeLayout.ALIGN_TOP);
                params.addRule(RelativeLayout.CENTER_VERTICAL, RelativeLayout.TRUE);
                title.setLayoutParams(params);
            }

            logo.setImageDrawable(mConversationAvatar);
        } else {
            if (identity != null && !identity.equals(displayName)) {
                actionBar.setSubtitle(identity);
            }
            actionBar.setTitle(displayName);
            int targetSize = (int) (AvatarFactory.SIZE_AB * context.getResources().getDisplayMetrics().density);
            mConversationAvatar.setInSize(targetSize);
            actionBar.setLogo(null);
            actionBar.setLogo(mConversationAvatar);
        }
    }

    public void blockContactRequest() {
        presenter.onBlockIncomingContactRequest();
    }

    public void refuseContactRequest() {
        presenter.onRefuseIncomingContactRequest();
    }

    public void acceptContactRequest() {
        presenter.onAcceptIncomingContactRequest();
    }

    public void addContact() {
        presenter.onAddContact();
    }

    @Override
    public void onPrepareOptionsMenu(@NonNull Menu menu) {
        super.onPrepareOptionsMenu(menu);
        boolean visible = binding.cvMessageInput.getVisibility() == View.VISIBLE;
        if (mAudioCallBtn != null)
            mAudioCallBtn.setVisible(visible);
        if (mVideoCallBtn != null)
            mVideoCallBtn.setVisible(visible);
    }

    @Override
    public void switchToUnknownView(String contactDisplayName) {
        binding.cvMessageInput.setVisibility(View.GONE);
        binding.unknownContactPrompt.setVisibility(View.VISIBLE);
        binding.trustRequestPrompt.setVisibility(View.GONE);
        binding.tvTrustRequestMessage.setText(String.format(getString(R.string.message_contact_not_trusted), contactDisplayName));
        binding.trustRequestMessageLayout.setVisibility(View.VISIBLE);
        currentBottomView = binding.unknownContactPrompt;
        requireActivity().invalidateOptionsMenu();
        updateListPadding();
    }

    @Override
    public void switchToIncomingTrustRequestView(String contactDisplayName) {
        binding.cvMessageInput.setVisibility(View.GONE);
        binding.unknownContactPrompt.setVisibility(View.GONE);
        binding.trustRequestPrompt.setVisibility(View.VISIBLE);
        binding.tvTrustRequestMessage.setText(String.format(getString(R.string.message_contact_not_trusted_yet), contactDisplayName));
        binding.trustRequestMessageLayout.setVisibility(View.VISIBLE);
        currentBottomView = binding.trustRequestPrompt;
        requireActivity().invalidateOptionsMenu();
        updateListPadding();
    }

    @Override
    public void switchToConversationView() {
        binding.cvMessageInput.setVisibility(View.VISIBLE);
        binding.unknownContactPrompt.setVisibility(View.GONE);
        binding.trustRequestPrompt.setVisibility(View.GONE);
        binding.trustRequestMessageLayout.setVisibility(View.GONE);
        currentBottomView = binding.cvMessageInput;
        requireActivity().invalidateOptionsMenu();
        updateListPadding();
    }

    @Override
    public void positiveMediaButtonClicked() {
        presenter.clickOnGoingPane();
    }

    @Override
    public void negativeMediaButtonClicked() {
        presenter.clickOnGoingPane();
    }

    @Override
    public void toggleMediaButtonClicked() {
        presenter.clickOnGoingPane();
    }

    private void setLoading(boolean isLoading) {
        if (binding == null)
            return;
        if (isLoading) {
            binding.btnTakePicture.setVisibility(View.GONE);
            binding.pbDataTransfer.setVisibility(View.VISIBLE);
        } else {
            binding.btnTakePicture.setVisibility(View.VISIBLE);
            binding.pbDataTransfer.setVisibility(View.GONE);
        }
    }

    public void handleShareIntent(Intent intent) {
        Log.w(TAG, "handleShareIntent " + intent);

        String action = intent.getAction();
        if (Intent.ACTION_SEND.equals(action) || Intent.ACTION_SEND_MULTIPLE.equals(action)) {
            String type = intent.getType();
            if (type == null) {
                Log.w(TAG, "Can't share with no type");
                return;
            }
            if (type.startsWith("text/plain")) {
                binding.msgInputTxt.setText(intent.getStringExtra(Intent.EXTRA_TEXT));
            } else {
                android.net.Uri uri = intent.getData();
                ClipData clip = intent.getClipData();
                if (uri == null && clip != null && clip.getItemCount() > 0)
                    uri = clip.getItemAt(0).getUri();
                if (uri == null)
                    return;
                startFileSend(AndroidFileUtils.getCacheFile(requireContext(), uri).flatMapCompletable(this::sendFile));
            }
        } else if (Intent.ACTION_VIEW.equals(action)) {
            ConversationPath path = ConversationPath.fromIntent(intent);
            if (path != null && intent.getBooleanExtra(EXTRA_SHOW_MAP, false)) {
                shareLocation();
            }
        }
    }

    /**
     * Creates an intent using Android Storage Access Framework
     * This intent is then received by applications that can handle it like
     * Downloads or Google drive
     * @param file DataTransfer of the file that is going to be stored
     * @param currentFileAbsolutePath absolute path of the file we want to save
     */
    public void startSaveFile(DataTransfer file, String currentFileAbsolutePath){
        //Get the current file absolute path and store it
        mCurrentFileAbsolutePath = currentFileAbsolutePath;

        try {
            //Use Android Storage File Access to download the file
            Intent downloadFileIntent = new Intent(Intent.ACTION_CREATE_DOCUMENT);
            downloadFileIntent.setType(AndroidFileUtils.getMimeTypeFromExtension(file.getExtension()));
            downloadFileIntent.addCategory(Intent.CATEGORY_OPENABLE);
            downloadFileIntent.putExtra(Intent.EXTRA_TITLE,file.getDisplayName());

            startActivityForResult(downloadFileIntent, ConversationFragment.REQUEST_CODE_SAVE_FILE);
        } catch (Exception e) {
            Log.i(TAG, "No app detected for saving files.");
            File directory = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS);
            if (!directory.exists()) {
                directory.mkdirs();
            }
            writeToFile(android.net.Uri.fromFile(new File(directory, file.getDisplayName())));
        }
    }

    @Override
    public void displayNetworkErrorPanel() {
        if (binding != null) {
            binding.errorMsgPane.setVisibility(View.VISIBLE);
            binding.errorMsgPane.setOnClickListener(null);
            binding.errorMsgPane.setText(R.string.error_no_network);
        }
    }

    @Override
    public void setReadIndicatorStatus(boolean show) {
        if (mAdapter != null) {
            mAdapter.setReadIndicatorStatus(show);
        }
    }

    @Override
    public void hideErrorPanel() {
        if (binding != null) {
            binding.errorMsgPane.setVisibility(View.GONE);
        }
    }

}
