package net.studymongolian.chimee;

import java.lang.ref.WeakReference;


import net.studymongolian.mongollibrary.ImeContainer;
import net.studymongolian.mongollibrary.MongolAlertDialog;
import net.studymongolian.mongollibrary.MongolCode;
import net.studymongolian.mongollibrary.MongolEditText;
import net.studymongolian.mongollibrary.MongolFont;
import net.studymongolian.mongollibrary.MongolInputMethodManager;
import net.studymongolian.mongollibrary.MongolMenu;
import net.studymongolian.mongollibrary.MongolMenuItem;
import net.studymongolian.mongollibrary.MongolToast;
import net.studymongolian.mongollibrary.MongolTypefaceSpan;

import android.annotation.SuppressLint;
import android.content.ComponentName;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.pm.ActivityInfo;
import android.content.pm.PackageManager;
import android.graphics.Bitmap;
import android.graphics.Color;
import android.graphics.Typeface;
import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Bundle;
import androidx.annotation.NonNull;
import androidx.fragment.app.DialogFragment;
import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.Toolbar;
import android.text.Editable;
import android.text.SpannableStringBuilder;
import android.text.Spanned;
import android.text.TextUtils;
import android.text.style.ForegroundColorSpan;
import android.util.Log;
import android.view.Gravity;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;

import android.view.MotionEvent;
import android.view.ScaleGestureDetector;
import android.view.View;
import android.view.inputmethod.InputMethodManager;
import android.widget.FrameLayout;

public class MainActivity extends AppCompatActivity
        implements ImeContainer.OnNonSystemImeListener,
        ImeDataSourceHelper.DataSourceHelperListener,
        MongolEditText.ContextMenuCallback,
        ColorChooserDialogFragment.ColorDialogListener,
        FontChooserDialogFragment.FontDialogListener {

    private static final int SHARE_REQUEST = 0;
    private static final int SETTINGS_REQUEST = 1;
    private static final int FAVORITE_MESSAGE_REQUEST = 2;
    private static final int PHOTO_REQUEST_CODE = 3;
    private static final int OPEN_REQUEST = 4;
    private static final int SAVE_REQUEST = 5;

    private static final int MENU_MARGIN_DP = 4;
    private static final String WECHAT_PACKAGE_NAME = "com.tencent.mm";
    private static final String BAINU_PACKAGE_NAME = "com.zuga.im";
    private static final String BAINU_DOWNLOAD_SITE = "http://www.zuga-tech.net";


    private enum ShareType {
        WeChat,
        Bainu,
        Other
    }

    private enum ImePickerAction {
        NONE,
        CHOOSING,
        CHOSEN
    }

    InputWindow inputWindow;
    CustomImeContainer imeContainer;
    FrameLayout showKeyboardButton;
    String lastSentMessage = "";
    private ScaleGestureDetector mScaleDetector;
    private float mScaleFactor = 1.f;
    private ImePickerAction mImePickerState = ImePickerAction.NONE;


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        setupToolbar();
        disableRotationForSmallerDevices();
        addGestureDetectorToTopLayout();
        setupKeyboardInput();
        setupKeyboardButton();
        setupInputWindow();
        setSavedDraft();
    }

    private void setupToolbar() {
        Toolbar myToolbar = findViewById(R.id.my_toolbar);
        setSupportActionBar(myToolbar);
    }

    private void disableRotationForSmallerDevices() {
        if (getResources().getBoolean(R.bool.portrait_only)) {
            setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
        }
    }

    private void setupKeyboardInput() {
        imeContainer = findViewById(R.id.imeContainer);
        inputWindow = findViewById(R.id.resizingScrollView);
        MongolEditText editText = inputWindow.getEditText();
        MongolInputMethodManager mimm = new MongolInputMethodManager();
        mimm.addEditor(editText);
        mimm.setIme(imeContainer);
        imeContainer.showSystemKeyboardsOption(getString(R.string.keyboard_show_system_keyboards));
        ImeDataSourceHelper helper = new ImeDataSourceHelper(this);
        helper.startDatabaseUpgradeIfNeeded();
        imeContainer.setDataSource(helper);
        imeContainer.setOnNonSystemImeListener(this);
        getSavedKeyboard();
    }

    private void getSavedKeyboard() {
        SharedPreferences settings = getSharedPreferences(SettingsActivity.PREFS_NAME, MODE_PRIVATE);
        String userKeyboard = settings.getString(SettingsActivity.MONGOLIAN_KEYBOARD_KEY,
                SettingsActivity.MONGOLIAN_KEYBOARD_DEFAULT);
        if (userKeyboard.equals(SettingsActivity.MONGOLIAN_QWERTY_KEYBOARD)) {
            imeContainer.requestNewKeyboard(CustomImeContainer.MONGOL_QWERTY_KEYBOARD_INDEX);
        }
    }

    private void setupKeyboardButton() {
        showKeyboardButton = findViewById(R.id.showKeyboardButton);
        showKeyboardButton.setOnLongClickListener(showKeyboardButtonLongClickListener);
    }

    private void setupInputWindow() {
        MongolEditText editText = inputWindow.getEditText();
        setSavedColors();
        setSavedFont();
        editText.requestFocus();
        editText.setContextMenuCallbackListener(this);
    }

    private void setSavedColors() {
        SharedPreferences settings = getSharedPreferences(SettingsActivity.PREFS_NAME, MODE_PRIVATE);
        int bgColor = settings.getInt(SettingsActivity.BGCOLOR_KEY,
                SettingsActivity.BGCOLOR_DEFAULT);
        int textColor = settings.getInt(SettingsActivity.TEXTCOLOR_KEY,
                SettingsActivity.TEXTCOLOR_DEFAULT);
        inputWindow.setBackgroundColor(bgColor);
        inputWindow.setTextColor(textColor);
    }

    private void setSavedFont() {
        SharedPreferences settings = getSharedPreferences(SettingsActivity.PREFS_NAME, MODE_PRIVATE);
        String font = settings.getString(SettingsActivity.FONT_KEY, SettingsActivity.FONT_DEFAULT);
        Typeface typeface = MongolFont.get(font, getApplicationContext());
        inputWindow.setTypeface(typeface);
    }

    private void setSavedDraft() {
        MongolEditText editText = inputWindow.getEditText();
        if (editText.getText().length() == 0) {
            SharedPreferences settings = getSharedPreferences(SettingsActivity.PREFS_NAME, MODE_PRIVATE);
            String savedText = settings.getString(SettingsActivity.DRAFT_KEY, SettingsActivity.DRAFT_DEFAULT);
            editText.setText(savedText);
            int cursorPosition = settings.getInt(SettingsActivity.CURSOR_POSITION_KEY, SettingsActivity.CURSOR_POSITION_DEFAULT);
            if (cursorPosition == 0)
                cursorPosition = savedText.length();
            editText.setSelection(cursorPosition);
        }
    }

    @Override
    public MongolMenu getMongolEditTextContextMenu(MongolEditText met) {

        MongolMenu menu = new MongolMenu(this);
        CharSequence selected = met.getSelectedText();

        // copy, cut
        if (selected.length() > 0) {
            menu.add(new MongolMenuItem(getString(net.studymongolian.mongollibrary.R.string.copy), R.drawable.ic_keyboard_copy_32dp));
            menu.add(new MongolMenuItem(getString(net.studymongolian.mongollibrary.R.string.cut), R.drawable.ic_keyboard_cut_32dp));
        }

        // paste
        menu.add(new MongolMenuItem(getString(net.studymongolian.mongollibrary.R.string.paste), R.drawable.ic_keyboard_paste_32dp));

        // select all
        if (selected.length() < met.getText().length()) {
            menu.add(new MongolMenuItem(getString(net.studymongolian.mongollibrary.R.string.select_all), R.drawable.ic_keyboard_select_all_32dp));
        }

        // color
        menu.add(new MongolMenuItem(getString(R.string.menu_item_color), R.drawable.ic_color_black_32dp));

        // font
        menu.add(new MongolMenuItem(getString(R.string.menu_item_font), R.drawable.ic_font_black_32dp));

        menu.setOnMenuItemClickListener(contextMenuItemClickListener);
        return menu;
    }

    MongolMenu.OnMenuItemClickListener contextMenuItemClickListener = new MongolMenu.OnMenuItemClickListener() {
        @Override
        public boolean onMenuItemClick(MongolMenuItem item) {
            String name = item.getTitle().toString();

            String copy = getString(net.studymongolian.mongollibrary.R.string.copy);
            String cut = getString(net.studymongolian.mongollibrary.R.string.cut);
            String paste = getString(net.studymongolian.mongollibrary.R.string.paste);
            String selectAll = getString(net.studymongolian.mongollibrary.R.string.select_all);
            String color = getString(R.string.menu_item_color);
            String font = getString(R.string.menu_item_font);
            MongolEditText editText = inputWindow.getEditText();

            if (name.equals(copy)) {
                editText.copySelectedText();
            } else if (name.equals(cut)) {
                editText.cutSelectedText();
            } else if (name.equals(paste)) {
                editText.pasteText();
            } else if (name.equals(selectAll)) {
                editText.selectAll();
            } else if (name.equals(color)) {
                openColorChooserDialog();
            } else if (name.equals(font)) {
                openFontChooserDialog();
            } else {
                return false;
            }
            return true;
        }


    };

    private void openColorChooserDialog() {
        int bgColor = getInputWindowBackgroundColor();
        int fgColor = getSelectedTextColor();
        DialogFragment dialog = ColorChooserDialogFragment.newInstance(bgColor, fgColor);
        dialog.show(getSupportFragmentManager(), "ColorChooserDialogFragment");

    }

    private int getInputWindowBackgroundColor() {
        int bgColor = Color.WHITE;
        Drawable background = inputWindow.getBackground();
        if (background instanceof ColorDrawable)
            bgColor = ((ColorDrawable) background).getColor();
        return bgColor;
    }

    private int getSelectedTextColor() {
        MongolEditText editText = inputWindow.getEditText();

        if (editText.hasSelection()) {
            Editable text = editText.getText();
            ForegroundColorSpan[] spans = text.getSpans(0, text.length(), ForegroundColorSpan.class);
            if (spans.length > 0)
                return spans[0].getForegroundColor();
        }

        return editText.getTextColor();
    }

    private void openFontChooserDialog() {
        DialogFragment dialog = new FontChooserDialogFragment();
        dialog.show(getSupportFragmentManager(), "FontChooserDialogFragment");
    }

    @SuppressLint("ClickableViewAccessibility")
    private void addGestureDetectorToTopLayout() {
        FrameLayout topLayout = findViewById(R.id.flTop);
        mScaleDetector = new ScaleGestureDetector(this, new ScaleListener());
        topLayout.setOnTouchListener(touchListener);
    }

    View.OnTouchListener touchListener = new View.OnTouchListener() {
        @SuppressLint("ClickableViewAccessibility")
        @Override
        public boolean onTouch(View v, MotionEvent event) {
            mScaleDetector.onTouchEvent(event);
            return true;
        }
    };

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        MenuInflater inflater = getMenuInflater();
        inflater.inflate(R.menu.main_menu, menu);
        return true;
    }

    @Override
    public void onStop() {
        super.onStop();

        // in case user accidentally closes app
        saveInputWindowDraftToSharedPreferences();
    }

    private void saveInputWindowDraftToSharedPreferences() {
        SharedPreferences settings = getSharedPreferences(SettingsActivity.PREFS_NAME, MODE_PRIVATE);
        SharedPreferences.Editor editor = settings.edit();
        String text = inputWindow.getText().toString();
        int cursorPosition = inputWindow.getEditText().getSelectionStart();
        editor.putString(SettingsActivity.DRAFT_KEY, text);
        editor.putInt(SettingsActivity.CURSOR_POSITION_KEY, cursorPosition);
        editor.apply();
    }

    @Override
    public void onWindowFocusChanged(boolean hasFocus) {
        super.onWindowFocusChanged(hasFocus);
        if (mImePickerState == ImePickerAction.CHOOSING) {
            mImePickerState = ImePickerAction.CHOSEN;
        } else if (mImePickerState == ImePickerAction.CHOSEN) {
            showSystemKeyboard();
            mImePickerState = ImePickerAction.NONE;
        }
    }

    // ImeDataSourceHelper.DataSourceHelperListener methods

    @Override
    public CustomImeContainer getImeContainer() {
        return imeContainer;
    }

    @Override
    public Context getContext() {
        return this;
    }


    // ImeContainer.OnNonSystemImeListener methods

    @Override
    public void onSystemKeyboardRequest() {
        hideInAppKeyboard();
        showSystemKeyboard();
    }

    @Override
    public void onHideKeyboardRequest() {
        hideInAppKeyboard();
    }

    public void onShowKeyboardButtonClick(View view) {
        showInAppKeyboard();
        hideSystemKeyboard();
    }

    private View.OnLongClickListener showKeyboardButtonLongClickListener = new View.OnLongClickListener() {
        @Override
        public boolean onLongClick(View v) {
            showSystemKeyboardChooser();
            return true;
        }
    };

    private void hideInAppKeyboard() {
        imeContainer.setVisibility(View.GONE);
        showKeyboardButton.setVisibility(View.VISIBLE);
    }

    private void showInAppKeyboard() {
        imeContainer.setVisibility(View.VISIBLE);
        showKeyboardButton.setVisibility(View.INVISIBLE);
    }

    private void showSystemKeyboard() {
        InputMethodManager im = (InputMethodManager) getSystemService(INPUT_METHOD_SERVICE);
        if (im == null) return;
        im.showSoftInput(inputWindow.getEditText(), 0);
    }

    private void hideSystemKeyboard() {
        InputMethodManager im = (InputMethodManager) getSystemService(INPUT_METHOD_SERVICE);
        if (im == null) return;
        im.hideSoftInputFromWindow(inputWindow.getWindowToken(), 0);
    }

    private void showSystemKeyboardChooser() {
        InputMethodManager im = (InputMethodManager) getSystemService(INPUT_METHOD_SERVICE);
        if (im == null) return;
        im.showInputMethodPicker();
        mImePickerState = ImePickerAction.CHOOSING;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()) {
            case R.id.main_action_share:
                shareActionBarItemClick();
                return true;
            case R.id.main_action_photo:
                photoActionBarItemClick();
                return true;
            case R.id.main_action_favorite:
                favoriteActionBarItemClick();
                return true;
            case R.id.main_action_overflow:
                overflowMenuItemClick();
                return true;
            default:
                return super.onOptionsItemSelected(item);
        }
    }

    private void shareActionBarItemClick() {

        // check WeChat and Bainu
        boolean shouldShowWeChat = isPackageInstalled(WECHAT_PACKAGE_NAME);
        boolean shouldShowBainu = isPackageInstalled(BAINU_PACKAGE_NAME)
                || shouldShowBainuIcon();
        if (!shouldShowWeChat && !shouldShowBainu) {
            shareTo(ShareType.Other);
            return;
        }

        // create menu
        MongolMenu menu = new MongolMenu(this);
        final MongolMenuItem weChat = new MongolMenuItem(getString(R.string.menu_item_share_wechat), R.drawable.ic_wechat_black_24dp);
        final MongolMenuItem bainu = new MongolMenuItem(getString(R.string.menu_item_share_bainu), R.drawable.ic_bainu_black_24dp);
        final MongolMenuItem other = new MongolMenuItem(getString(R.string.menu_item_share_other), R.drawable.ic_more_vert_black_24dp);
        if (shouldShowWeChat)
            menu.add(weChat);
        if (shouldShowBainu)
            menu.add(bainu);
        menu.add(other);
        menu.setOnMenuItemClickListener(new MongolMenu.OnMenuItemClickListener() {
            public boolean onMenuItemClick(MongolMenuItem item) {
                if (item == weChat) {
                    shareTo(ShareType.WeChat);
                } else if (item == bainu) {
                    shareTo(ShareType.Bainu);
                } else {
                    shareTo(ShareType.Other);
                }
                return true;
            }
        });

        // show menu
        int[] location = new int[2];
        View shareButton = findViewById(R.id.main_action_share);
        shareButton.getLocationInWindow(location);
        int gravity = Gravity.NO_GRAVITY;
        int marginPx = convertMarginDpToPx();
        int xOffset = location[0];
        int yOffset = location[1] + marginPx;
        menu.showAtLocation(shareButton, gravity, xOffset, yOffset);
    }

    private boolean shouldShowBainuIcon() {
        SharedPreferences settings = getSharedPreferences(SettingsActivity.PREFS_NAME, MODE_PRIVATE);
        return settings.getBoolean(SettingsActivity.SHOW_BAINU_BUTTON_KEY, true);
    }

    private boolean isPackageInstalled(String packageName) {
        PackageManager pm = getApplicationContext().getPackageManager();
        try {
            return pm.getApplicationInfo(packageName, 0).enabled;
        } catch (PackageManager.NameNotFoundException e) {
            return false;
        }
    }

    public void shareTo(ShareType shareDestination) {

        CharSequence message = inputWindow.getText();

        if (TextUtils.isEmpty(message)) {
            notifyUserOfEmptyMessage();
            return;
        }

        saveMessageToHistory(message);

        switch (shareDestination) {
            case WeChat:
                shareToWeChat();
                break;
            case Bainu:
                shareToBainu();
                break;
            case Other:
                shareToSystemApp();
                break;
        }
    }

    private void clearInputWindow() {
        inputWindow.getEditText().setText("");
        saveInputWindowDraftToSharedPreferences();
    }

    private void photoActionBarItemClick() {

        if (TextUtils.isEmpty(inputWindow.getText().toString().trim())) {
            MongolToast.makeText(this, R.string.input_window_empty,
                    MongolToast.LENGTH_SHORT).show();
            return;
        }

        Intent intent = new Intent();
        intent.setType("image/*");
        intent.setAction(Intent.ACTION_GET_CONTENT);
        intent.addCategory(Intent.CATEGORY_OPENABLE);
        startActivityForResult(intent, PHOTO_REQUEST_CODE);
    }


    private void favoriteActionBarItemClick() {

        Intent intent = new Intent(this, FavoriteActivity.class);
        String text = inputWindow.getText().toString();
        intent.putExtra(FavoriteActivity.CURRENT_MESSAGE_KEY, text);
        startActivityForResult(intent, FAVORITE_MESSAGE_REQUEST);
    }

    private void overflowMenuItemClick() {
        View overflowMenuButton = findViewById(R.id.main_action_overflow);
        MongolMenu menu = new MongolMenu(this);
        final MongolMenuItem open = new MongolMenuItem(getString(R.string.menu_item_open), R.drawable.ic_folder_open_black_24dp);
        final MongolMenuItem save = new MongolMenuItem(getString(R.string.menu_item_save), R.drawable.ic_save_black_24dp);
        final MongolMenuItem settings = new MongolMenuItem(getString(R.string.menu_item_settings), R.drawable.ic_settings_black_24dp);
        if (inputWindow.hasUnsavedContent()) {
            menu.add(save);
        } else {
            menu.add(open);
        }
        menu.add(settings);
        menu.setOnMenuItemClickListener(new MongolMenu.OnMenuItemClickListener() {
            public boolean onMenuItemClick(MongolMenuItem item) {
                if (item == open) {
                    onOpenMenuItemClick();
                } else if (item == save) {
                    onSaveMenuItemClick();
                } else if (item == settings) {
                    onSettingsMenuItemClick();
                }
                return true;
            }
        });

        int[] location = new int[2];
        overflowMenuButton.getLocationInWindow(location);
        int gravity = Gravity.TOP | Gravity.RIGHT;
        int marginPx = convertMarginDpToPx();
        int yOffset = location[1] + marginPx;

        menu.showAtLocation(overflowMenuButton, gravity, marginPx, yOffset);
    }

    private void onOpenMenuItemClick() {
        Intent intent = new Intent(this, OpenActivity.class);
        startActivityForResult(intent, OPEN_REQUEST);
    }

    private void onSaveMenuItemClick() {
        if (PermissionsHelper.getWriteExternalStoragePermission(this))
            startSaveActivity();
    }

    private void startSaveActivity() {
        Intent intent = new Intent(this, SaveActivity.class);
        intent.putExtra(SaveActivity.TEXT_KEY, inputWindow.getText().toString());
        startActivityForResult(intent, SAVE_REQUEST);
    }

    @Override
    public void onRequestPermissionsResult(int requestCode,
                                           @NonNull String permissions[],
                                           @NonNull int[] grantResults) {
        if (PermissionsHelper.isWritePermissionRequestGranted(requestCode, grantResults)) {
            startSaveActivity();
        } else {
            PermissionsHelper.notifyUserThatTheyCantSaveFileWithoutWritePermission(this);
        }
    }

    private void onSettingsMenuItemClick() {
        Intent intent = new Intent(this, SettingsActivity.class);
        startActivityForResult(intent, SETTINGS_REQUEST);
    }

    private int convertMarginDpToPx() {
        return (int) (MENU_MARGIN_DP * getResources().getDisplayMetrics().density);
    }

    private Bitmap getInputWindowBitmap() {
        inputWindow.setCursorVisible(false);
        Bitmap bitmap = inputWindow.getBitmap();
        inputWindow.setCursorVisible(true);
        return bitmap;
    }

    private void shareToWeChat() {
        Bitmap bitmap = getInputWindowBitmap();
        Intent shareIntent = FileUtils.getShareImageIntent(this, bitmap);
        ComponentName comp = new ComponentName("com.tencent.mm",
                "com.tencent.mm.ui.tools.ShareImgUI");
        if (shareIntent == null) return;
        shareIntent.setComponent(comp);
        startActivityForResult(shareIntent, SHARE_REQUEST);
    }

    private void shareToBainu() {

        boolean isBainuInstalled = isPackageInstalled(BAINU_PACKAGE_NAME);
        if (!isBainuInstalled) {
            askIfUserWantsToDownloadBainu();
            return;
        }

        String text = inputWindow.getText().toString();
        String menksoftCode = MongolCode.INSTANCE.unicodeToMenksoft(text);
        Intent shareIntent = new Intent();
        shareIntent.setAction(Intent.ACTION_SEND);
        shareIntent.putExtra(Intent.EXTRA_TEXT, menksoftCode);
        shareIntent.setType("text/plain");
        ComponentName comp = new ComponentName("com.zuga.im",
                "com.zuga.im.bainuSdk.BNEntryActivity");
        shareIntent.setComponent(comp);
        startActivityForResult(shareIntent, SHARE_REQUEST);
    }

    private void askIfUserWantsToDownloadBainu() {
        MongolAlertDialog.Builder builder = new MongolAlertDialog.Builder(this);
        builder.setMessage(getString(R.string.download_bainu_alert_message));

        builder.setPositiveButton(getString(R.string.download_bainu_alert_positive), new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialog, int which) {
                openBainuDownloadPage();
            }
        });
        builder.setNegativeButton(getString(R.string.download_bainu_alert_negative), new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialog, int which) {
                dontShowBainuOptionAgain();
            }
        });

        MongolAlertDialog dialog = builder.create();
        dialog.show();
    }

    private void openBainuDownloadPage() {
        Intent browserIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(BAINU_DOWNLOAD_SITE));
        startActivity(browserIntent);
    }

    private void dontShowBainuOptionAgain() {
        SharedPreferences settings = getSharedPreferences(SettingsActivity.PREFS_NAME, MODE_PRIVATE);
        SharedPreferences.Editor editor = settings.edit();
        editor.putBoolean(SettingsActivity.SHOW_BAINU_BUTTON_KEY, false);
        editor.apply();
    }

    private void shareToSystemApp() {
        Bitmap bitmap = getInputWindowBitmap();
        Intent shareIntent = FileUtils.getShareImageIntent(this, bitmap);
        startActivity(Intent.createChooser(shareIntent, null));
    }

    private void notifyUserOfEmptyMessage() {
        MongolToast.makeText(this,
                getString(R.string.input_window_empty),
                MongolToast.LENGTH_LONG)
                .show();
    }

    private void saveMessageToHistory(CharSequence message) {
        String messageText = message.toString();
        if (!lastSentMessage.equals(messageText)) {
            new SaveMessageToHistory(this).execute(messageText);
            lastSentMessage = messageText;
        }
    }


    @Override
    public void onColorDialogPositiveClick(int chosenBackgroundColor,
                                           int chosenForegroundColor) {
        inputWindow.setBackgroundColor(chosenBackgroundColor);
        MongolEditText editText = inputWindow.getEditText();
        Editable text = editText.getText();
        if (editText.hasSelection()) {
            ForegroundColorSpan fgSpan = new ForegroundColorSpan(chosenForegroundColor);
            int start = editText.getSelectionStart();
            int end = editText.getSelectionEnd();
            if (start > end) {
                int swap = start;
                start = end;
                end = swap;
            }
            text.setSpan(fgSpan, start, end, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
        } else {
            // remove fg color spans
            ForegroundColorSpan[] spans = text.getSpans(0, text.length(), ForegroundColorSpan.class);
            for (ForegroundColorSpan span : spans) {
                text.removeSpan(span);
            }
            // set text all one color
            inputWindow.setTextColor(chosenForegroundColor);
            saveColors(chosenBackgroundColor, chosenForegroundColor);
        }
    }

    private void saveColors(int background, int foreground) {
        SharedPreferences settings = getSharedPreferences(SettingsActivity.PREFS_NAME, MODE_PRIVATE);
        SharedPreferences.Editor editor = settings.edit();
        editor.putInt(SettingsActivity.BGCOLOR_KEY, background);
        editor.putInt(SettingsActivity.TEXTCOLOR_KEY, foreground);
        editor.apply();
    }

    @Override
    public void onFontDialogPositiveClick(Font chosenFont) {
        MongolEditText editText = inputWindow.getEditText();
        Editable text = editText.getText();
        Typeface typeface = MongolFont.get(chosenFont.getFileLocation(), getApplicationContext());
        if (editText.hasSelection()) {
            MongolTypefaceSpan fontSpan = new MongolTypefaceSpan(typeface);
            int start = editText.getSelectionStart();
            int end = editText.getSelectionEnd();
            if (start > end) {
                int swap = start;
                start = end;
                end = swap;
            }
            text.setSpan(fontSpan, start, end, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
        } else {
            // remove font spans
            MongolTypefaceSpan[] spans = text.getSpans(0, text.length(), MongolTypefaceSpan.class);
            for (MongolTypefaceSpan span : spans) {
                text.removeSpan(span);
            }
            // set font for whole textview
            inputWindow.setTypeface(typeface);
            saveFont(chosenFont.getFileLocation());
        }
    }

    private void saveFont(String font) {
        SharedPreferences settings = getSharedPreferences(SettingsActivity.PREFS_NAME, MODE_PRIVATE);
        SharedPreferences.Editor editor = settings.edit();
        editor.putString(SettingsActivity.FONT_KEY, font);
        editor.apply();
    }

    private class ScaleListener
            extends ScaleGestureDetector.SimpleOnScaleGestureListener {

        int initialHeight;
        float initialTextSize;

        @Override
        public boolean onScaleBegin(ScaleGestureDetector detector) {
            inputWindow.setIsManualScaling(true);
            initialHeight = inputWindow.getHeight();
            initialTextSize = inputWindow.getTextSize();
            mScaleFactor = 1.0f;
            return super.onScaleBegin(detector);
        }

        @Override
        public boolean onScale(ScaleGestureDetector detector) {

            mScaleFactor *= detector.getScaleFactor();
            mScaleFactor = Math.max(0.1f, Math.min(mScaleFactor, 5.0f));
            if (isVerticalScaling(detector)) {
                resizeInputWindow(initialHeight);
            } else {
                resizeText(initialTextSize);
            }
            return true;
        }

        private boolean isVerticalScaling(ScaleGestureDetector detector) {
            float spanX = detector.getCurrentSpanX();
            float spanY = detector.getCurrentSpanY();
            return spanY > spanX;
        }

        @Override
        public void onScaleEnd(ScaleGestureDetector detector) {
            inputWindow.setIsManualScaling(false);
            super.onScaleEnd(detector);
        }
    }

    private void resizeText(float initialTextSize) {
        float newSize = initialTextSize * mScaleFactor;
        float sizeSp = newSize / getResources().getDisplayMetrics().scaledDensity;
        Log.i("TAG", "resizeText: " + mScaleFactor);
        inputWindow.setTextSize(sizeSp);
    }

    private void resizeInputWindow(int initialHeight) {
        int newHeight = (int) (initialHeight * mScaleFactor);
        inputWindow.setDesiredHeight(newHeight);
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        switch (requestCode) {
            case SHARE_REQUEST:
                onShareResult();
                break;
            case SETTINGS_REQUEST:
                onSettingsResult(resultCode, data);
                break;
            case FAVORITE_MESSAGE_REQUEST:
                onFavoriteActivityResult(resultCode, data);
                break;
            case PHOTO_REQUEST_CODE:
                onPhotoResult(resultCode, data);
                break;
            case OPEN_REQUEST:
                onOpenFileResult(resultCode, data);
                break;
            case SAVE_REQUEST:
                onSaveFileResult(resultCode);
                break;
            default:
                super.onActivityResult(requestCode, resultCode, data);
        }
    }

    private void onShareResult() {
        clearInputWindow();
    }

    private void onSettingsResult(int resultCode, Intent data) {
        if (resultCode != RESULT_OK) return;
        String message = data.getStringExtra(HistoryActivity.RESULT_STRING_KEY);
        insertMessageIntoInputWindow(message);
    }

    private void insertMessageIntoInputWindow(String message) {
        if (TextUtils.isEmpty(message)) return;
        MongolEditText editText = inputWindow.getEditText();
        int start = editText.getSelectionStart();
        int end = editText.getSelectionEnd();
        editText.getText().replace(start, end, message);
    }

    private void onFavoriteActivityResult(int resultCode, Intent data) {
        if (resultCode != RESULT_OK) return;
        Bundle extras = data.getExtras();
        if (extras == null) return;
        String message = extras.getString(FavoriteActivity.RESULT_STRING_KEY);
        insertMessageIntoInputWindow(message);
    }

    private void onPhotoResult(int resultCode, Intent data) {
        if (resultCode != RESULT_OK) return;
        if (data == null || data.getData() == null) return;

        Intent intent = new Intent(this, PhotoOverlayActivity.class);
        CharSequence text = getInputWindowTextWithHardBreaksAdded();
        intent.putExtra(PhotoOverlayActivity.CURRENT_MESSAGE_KEY, text);
        SharedPreferences settings = getSharedPreferences(SettingsActivity.PREFS_NAME, MODE_PRIVATE);
        String font = settings.getString(SettingsActivity.FONT_KEY, SettingsActivity.FONT_DEFAULT);
        intent.putExtra(PhotoOverlayActivity.CURRENT_TYPEFACE_KEY, font);

        Uri uri = data.getData();
        intent.setData(uri);
        startActivity(intent);
    }

    private CharSequence getInputWindowTextWithHardBreaksAdded() {
        int count = inputWindow.getLineCount();
        SpannableStringBuilder hardLineWraps = new SpannableStringBuilder();
        for (int line = 0; line < count; line++) {
            int start = inputWindow.getLayout().getLineStart(line);
            int end = inputWindow.getLayout().getLineEnd(line);
            CharSequence substring = inputWindow.getText().subSequence(start, end);
            hardLineWraps.append(substring);
            if (!TextUtils.isEmpty(substring)
                    && line != count - 1
                    && substring.charAt(substring.length() - 1) != '\n') {
                hardLineWraps.append('\n');
            }
        }
        return hardLineWraps;
    }

    private void onOpenFileResult(int resultCode, Intent data) {
        if (resultCode != RESULT_OK) return;
        Bundle extras = data.getExtras();
        if (extras == null) return;
        String fileName = extras.getString(OpenActivity.FILE_NAME_KEY);
        String fileText = extras.getString(OpenActivity.FILE_TEXT_KEY);
        if (TextUtils.isEmpty(fileName) || fileText == null) return;
        MongolEditText editText = inputWindow.getEditText();
        editText.setText(fileText);
        editText.setSelection(0);
        inputWindow.recordSavedContent();
    }

    private void onSaveFileResult(int resultCode) {
        if (resultCode != RESULT_OK) return;
        inputWindow.recordSavedContent();
    }


    private static class SaveMessageToHistory extends AsyncTask<String, Void, Void> {

        WeakReference<MainActivity> activityReference;

        SaveMessageToHistory(MainActivity context) {
            activityReference = new WeakReference<>(context);
        }

        @Override
        protected Void doInBackground(String... params) {

            String messageText = params[0];
            MainActivity activity = activityReference.get();

            try {
                MessageDatabaseAdapter dbAdapter = new MessageDatabaseAdapter(activity);
                dbAdapter.addHistoryMessage(messageText);
            } catch (Exception e) {
                Log.e("app", e.toString());
            }
            return null;
        }
    }
}