package com.android.dialer.util;

import android.app.Activity;
import android.app.Dialog;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.graphics.Color;
import android.graphics.Typeface;
import android.graphics.drawable.GradientDrawable;
import android.text.InputFilter;
import android.text.TextUtils;
import android.view.Gravity;
import android.view.View;
import android.view.ViewGroup;
import android.view.Window;
import android.view.WindowManager;
import android.view.inputmethod.InputMethodManager;
import android.widget.EditText;
import android.widget.LinearLayout;
import android.widget.Space;
import android.widget.TextView;

import android.support.v4.content.ContextCompat;

import com.android.dialer.R;

import java.util.Locale;

/**
 * LemenzoOS quick reply picker used from call details and contact interactions.
 *
 * <p>Messages are never sent automatically. The selected reply is passed to
 * Lemenzo Messenger as prefilled composer text so the user can review/edit it
 * before pressing Send.
 */
public final class QuickReplyDialog {

  private static final String PREFS = "lemenzo_quick_replies";
  private static final String KEY_PREFIX = "reply_";
  private static final int REPLY_COUNT = 4;
  private static final int MAX_REPLY_LENGTH = 160;

  private QuickReplyDialog() {}

  public static void show(Context context, String phoneNumber) {
    if (context == null || TextUtils.isEmpty(phoneNumber)) {
      return;
    }

    if (!(context instanceof Activity)) {
      openComposer(context, phoneNumber, null);
      return;
    }

    final Dialog dialog = createBottomDialog(context);
    final LinearLayout sheet = createSheet(context);

    addHandle(context, sheet);
    addTitle(
        context,
        sheet,
        context.getString(R.string.lemenzo_quick_reply_title),
        context.getString(R.string.lemenzo_quick_reply_subtitle));

    String[] replies = loadReplies(context);
    for (String reply : replies) {
      TextView item = createReplyRow(context, reply);
      item.setOnClickListener(
          v -> {
            dialog.dismiss();
            openComposer(context, phoneNumber, reply);
          });
      sheet.addView(item);
    }

    TextView custom =
        createSecondaryAction(
            context,
            context.getString(R.string.lemenzo_quick_reply_custom));
    custom.setOnClickListener(
        v -> {
          dialog.dismiss();
          openComposer(context, phoneNumber, null);
        });
    sheet.addView(custom);

    TextView edit =
        createSecondaryAction(
            context,
            context.getString(R.string.lemenzo_quick_reply_edit));
    edit.setTextColor(ContextCompat.getColor(context, R.color.lemenzo_phone_blue));
    edit.setOnClickListener(
        v -> {
          dialog.dismiss();
          showEditor(context, phoneNumber);
        });
    sheet.addView(edit);

    dialog.setContentView(sheet);
    showAtBottom(dialog);
  }

  private static void showEditor(Context context, String phoneNumber) {
    if (!(context instanceof Activity)) {
      return;
    }

    final Dialog dialog = createBottomDialog(context);
    final LinearLayout sheet = createSheet(context);

    addHandle(context, sheet);
    addTitle(
        context,
        sheet,
        context.getString(R.string.lemenzo_quick_reply_edit_title),
        context.getString(R.string.lemenzo_quick_reply_edit_subtitle));

    final String[] current = loadReplies(context);
    final EditText[] fields = new EditText[REPLY_COUNT];

    for (int i = 0; i < REPLY_COUNT; i++) {
      EditText field = createEditorField(context, current[i]);
      fields[i] = field;
      sheet.addView(field);
    }

    LinearLayout actions = new LinearLayout(context);
    actions.setOrientation(LinearLayout.HORIZONTAL);
    actions.setGravity(Gravity.CENTER_VERTICAL);
    LinearLayout.LayoutParams actionsParams =
        new LinearLayout.LayoutParams(
            ViewGroup.LayoutParams.MATCH_PARENT,
            ViewGroup.LayoutParams.WRAP_CONTENT);
    actionsParams.topMargin = dp(context, 8);
    actions.setLayoutParams(actionsParams);

    TextView reset =
        createCompactAction(
            context,
            context.getString(R.string.lemenzo_quick_reply_reset),
            false);
    reset.setOnClickListener(
        v -> {
          clearReplies(context);
          String[] defaults = defaultReplies(context);
          for (int i = 0; i < REPLY_COUNT; i++) {
            fields[i].setText(defaults[i]);
            fields[i].setSelection(fields[i].length());
          }
        });

    Space spacer = new Space(context);
    actions.addView(
        reset,
        new LinearLayout.LayoutParams(
            ViewGroup.LayoutParams.WRAP_CONTENT,
            dp(context, 44)));
    actions.addView(
        spacer,
        new LinearLayout.LayoutParams(
            0,
            1,
            1f));

    TextView cancel =
        createCompactAction(
            context,
            context.getString(android.R.string.cancel),
            false);
    cancel.setOnClickListener(v -> dialog.dismiss());
    actions.addView(
        cancel,
        new LinearLayout.LayoutParams(
            ViewGroup.LayoutParams.WRAP_CONTENT,
            dp(context, 44)));

    TextView save =
        createCompactAction(
            context,
            context.getString(R.string.lemenzo_quick_reply_save),
            true);
    LinearLayout.LayoutParams saveParams =
        new LinearLayout.LayoutParams(
            ViewGroup.LayoutParams.WRAP_CONTENT,
            dp(context, 44));
    saveParams.leftMargin = dp(context, 8);
    actions.addView(save, saveParams);

    save.setOnClickListener(
        v -> {
          String[] values = new String[REPLY_COUNT];
          for (int i = 0; i < REPLY_COUNT; i++) {
            String value = fields[i].getText().toString().trim();
            if (value.isEmpty()) {
              value = defaultReplies(context)[i];
            }
            values[i] = value;
          }
          saveReplies(context, values);
          dialog.dismiss();
          show(context, phoneNumber);
        });

    sheet.addView(actions);
    dialog.setContentView(sheet);
    showAtBottom(dialog);

    if (fields[0] != null) {
      fields[0].requestFocus();
      fields[0].postDelayed(
          () -> {
            InputMethodManager imm =
                (InputMethodManager) context.getSystemService(Context.INPUT_METHOD_SERVICE);
            if (imm != null) {
              imm.showSoftInput(fields[0], InputMethodManager.SHOW_IMPLICIT);
            }
          },
          180);
    }
  }

  private static void openComposer(Context context, String phoneNumber, String text) {
    Intent intent = IntentUtil.getSendSmsIntent(phoneNumber);
    if (!TextUtils.isEmpty(text)) {
      intent.putExtra(Intent.EXTRA_TEXT, text);
    }
    if (!(context instanceof Activity)) {
      intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
    }
    DialerUtils.startActivityWithErrorToast(context, intent);
  }

  private static Dialog createBottomDialog(Context context) {
    Dialog dialog = new Dialog(context);
    dialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
    dialog.setCancelable(true);
    dialog.setCanceledOnTouchOutside(true);
    return dialog;
  }

  private static void showAtBottom(Dialog dialog) {
    dialog.show();
    Window window = dialog.getWindow();
    if (window == null) {
      return;
    }

    window.setBackgroundDrawableResource(android.R.color.transparent);
    window.setDimAmount(0.55f);
    window.addFlags(WindowManager.LayoutParams.FLAG_DIM_BEHIND);
    window.setGravity(Gravity.BOTTOM);

    WindowManager.LayoutParams params = window.getAttributes();
    params.width = WindowManager.LayoutParams.MATCH_PARENT;
    params.height = WindowManager.LayoutParams.WRAP_CONTENT;
    window.setAttributes(params);
  }

  private static LinearLayout createSheet(Context context) {
    LinearLayout sheet = new LinearLayout(context);
    sheet.setOrientation(LinearLayout.VERTICAL);
    sheet.setPadding(
        dp(context, 16),
        dp(context, 10),
        dp(context, 16),
        dp(context, 20));

    GradientDrawable bg = new GradientDrawable();
    bg.setColor(ContextCompat.getColor(context, R.color.lemenzo_phone_surface));
    bg.setCornerRadii(
        new float[] {
          dp(context, 24), dp(context, 24),
          dp(context, 24), dp(context, 24),
          0, 0,
          0, 0
        });
    bg.setStroke(
        dp(context, 1),
        ContextCompat.getColor(context, R.color.lemenzo_phone_blue_outline));
    sheet.setBackground(bg);
    return sheet;
  }

  private static void addHandle(Context context, LinearLayout sheet) {
    TextView handle = new TextView(context);
    GradientDrawable bg = new GradientDrawable();
    bg.setColor(ContextCompat.getColor(context, R.color.lemenzo_phone_text_muted));
    bg.setCornerRadius(dp(context, 999));
    handle.setBackground(bg);

    LinearLayout.LayoutParams lp =
        new LinearLayout.LayoutParams(
            dp(context, 38),
            dp(context, 4));
    lp.gravity = Gravity.CENTER_HORIZONTAL;
    lp.bottomMargin = dp(context, 14);
    handle.setLayoutParams(lp);
    sheet.addView(handle);
  }

  private static void addTitle(
      Context context,
      LinearLayout sheet,
      String titleText,
      String subtitleText) {
    TextView title = new TextView(context);
    title.setText(titleText);
    title.setTextColor(ContextCompat.getColor(context, R.color.lemenzo_phone_text_primary));
    title.setTextSize(21);
    title.setTypeface(Typeface.DEFAULT, Typeface.BOLD);
    sheet.addView(title);

    TextView subtitle = new TextView(context);
    subtitle.setText(subtitleText);
    subtitle.setTextColor(ContextCompat.getColor(context, R.color.lemenzo_phone_text_secondary));
    subtitle.setTextSize(13.5f);
    LinearLayout.LayoutParams subtitleParams =
        new LinearLayout.LayoutParams(
            ViewGroup.LayoutParams.MATCH_PARENT,
            ViewGroup.LayoutParams.WRAP_CONTENT);
    subtitleParams.topMargin = dp(context, 4);
    subtitleParams.bottomMargin = dp(context, 14);
    subtitle.setLayoutParams(subtitleParams);
    sheet.addView(subtitle);
  }

  private static TextView createReplyRow(Context context, String text) {
    TextView row = new TextView(context);
    row.setText(text);
    row.setTextColor(ContextCompat.getColor(context, R.color.lemenzo_phone_text_primary));
    row.setTextSize(16);
    row.setGravity(Gravity.CENTER_VERTICAL);
    row.setPadding(
        dp(context, 14),
        dp(context, 13),
        dp(context, 14),
        dp(context, 13));

    GradientDrawable bg = new GradientDrawable();
    bg.setColor(ContextCompat.getColor(context, R.color.lemenzo_phone_surface_raised));
    bg.setCornerRadius(dp(context, 14));
    bg.setStroke(
        dp(context, 1),
        ContextCompat.getColor(context, R.color.lemenzo_phone_blue_outline));
    row.setBackground(bg);

    LinearLayout.LayoutParams lp =
        new LinearLayout.LayoutParams(
            ViewGroup.LayoutParams.MATCH_PARENT,
            ViewGroup.LayoutParams.WRAP_CONTENT);
    lp.bottomMargin = dp(context, 8);
    row.setLayoutParams(lp);
    return row;
  }

  private static TextView createSecondaryAction(Context context, String label) {
    TextView action = new TextView(context);
    action.setText(label);
    action.setTextColor(ContextCompat.getColor(context, R.color.lemenzo_phone_text_secondary));
    action.setTextSize(15);
    action.setTypeface(Typeface.DEFAULT, Typeface.BOLD);
    action.setGravity(Gravity.CENTER);
    action.setPadding(
        dp(context, 12),
        dp(context, 12),
        dp(context, 12),
        dp(context, 12));

    LinearLayout.LayoutParams lp =
        new LinearLayout.LayoutParams(
            ViewGroup.LayoutParams.MATCH_PARENT,
            ViewGroup.LayoutParams.WRAP_CONTENT);
    lp.topMargin = dp(context, 2);
    action.setLayoutParams(lp);
    return action;
  }

  private static EditText createEditorField(Context context, String value) {
    EditText field = new EditText(context);
    field.setText(value);
    field.setTextColor(ContextCompat.getColor(context, R.color.lemenzo_phone_text_primary));
    field.setHintTextColor(ContextCompat.getColor(context, R.color.lemenzo_phone_text_muted));
    field.setTextSize(15);
    field.setSingleLine(false);
    field.setMaxLines(2);
    field.setSelectAllOnFocus(false);
    field.setFilters(new InputFilter[] {new InputFilter.LengthFilter(MAX_REPLY_LENGTH)});
    field.setPadding(
        dp(context, 13),
        dp(context, 11),
        dp(context, 13),
        dp(context, 11));

    GradientDrawable bg = new GradientDrawable();
    bg.setColor(ContextCompat.getColor(context, R.color.lemenzo_phone_surface_raised));
    bg.setCornerRadius(dp(context, 13));
    bg.setStroke(
        dp(context, 1),
        ContextCompat.getColor(context, R.color.lemenzo_phone_blue_outline));
    field.setBackground(bg);

    LinearLayout.LayoutParams lp =
        new LinearLayout.LayoutParams(
            ViewGroup.LayoutParams.MATCH_PARENT,
            ViewGroup.LayoutParams.WRAP_CONTENT);
    lp.bottomMargin = dp(context, 8);
    field.setLayoutParams(lp);
    return field;
  }

  private static TextView createCompactAction(
      Context context,
      String label,
      boolean primary) {
    TextView action = new TextView(context);
    action.setText(label);
    action.setTextSize(14);
    action.setTypeface(Typeface.DEFAULT, Typeface.BOLD);
    action.setGravity(Gravity.CENTER);
    action.setPadding(
        dp(context, 14),
        0,
        dp(context, 14),
        0);

    GradientDrawable bg = new GradientDrawable();
    bg.setCornerRadius(dp(context, 12));
    if (primary) {
      bg.setColor(ContextCompat.getColor(context, R.color.lemenzo_phone_blue));
      action.setTextColor(Color.WHITE);
    } else {
      bg.setColor(ContextCompat.getColor(context, R.color.lemenzo_phone_surface_raised));
      bg.setStroke(
          dp(context, 1),
          ContextCompat.getColor(context, R.color.lemenzo_phone_blue_outline));
      action.setTextColor(ContextCompat.getColor(context, R.color.lemenzo_phone_text_secondary));
    }
    action.setBackground(bg);
    return action;
  }

  private static String[] loadReplies(Context context) {
    SharedPreferences prefs =
        context.getSharedPreferences(PREFS, Context.MODE_PRIVATE);
    String localeKey = localeKey(context);
    String[] defaults = defaultReplies(context);
    String[] result = new String[REPLY_COUNT];

    for (int i = 0; i < REPLY_COUNT; i++) {
      result[i] =
          prefs.getString(
              localeKey + "_" + KEY_PREFIX + i,
              defaults[i]);
    }
    return result;
  }

  private static void saveReplies(Context context, String[] values) {
    if (values == null || values.length != REPLY_COUNT) {
      return;
    }

    SharedPreferences.Editor editor =
        context.getSharedPreferences(PREFS, Context.MODE_PRIVATE).edit();
    String localeKey = localeKey(context);

    for (int i = 0; i < REPLY_COUNT; i++) {
      editor.putString(
          localeKey + "_" + KEY_PREFIX + i,
          values[i]);
    }
    editor.apply();
  }

  private static void clearReplies(Context context) {
    SharedPreferences prefs =
        context.getSharedPreferences(PREFS, Context.MODE_PRIVATE);
    SharedPreferences.Editor editor = prefs.edit();
    String localeKey = localeKey(context);

    for (int i = 0; i < REPLY_COUNT; i++) {
      editor.remove(localeKey + "_" + KEY_PREFIX + i);
    }
    editor.apply();
  }

  private static String[] defaultReplies(Context context) {
    return new String[] {
      context.getString(R.string.lemenzo_quick_reply_1),
      context.getString(R.string.lemenzo_quick_reply_2),
      context.getString(R.string.lemenzo_quick_reply_3),
      context.getString(R.string.lemenzo_quick_reply_4)
    };
  }

  private static String localeKey(Context context) {
    Locale locale = context.getResources().getConfiguration().getLocales().get(0);
    return locale == null ? "default" : locale.toLanguageTag();
  }

  private static int dp(Context context, int value) {
    return Math.round(
        value * context.getResources().getDisplayMetrics().density);
  }
}
