package jp.gr.java_conf.shiseissi.commonlib;

import android.app.Activity;
import android.app.AlertDialog;
import android.app.Dialog;
import android.content.DialogInterface;
import android.os.Bundle;
import android.support.v4.app.DialogFragment;
import android.support.v4.app.Fragment;
import android.view.ViewGroup;

import static android.view.ViewGroup.LayoutParams.FILL_PARENT;
import static android.view.ViewGroup.LayoutParams.WRAP_CONTENT;

import android.widget.EditText;
import android.widget.FrameLayout;

/**
 * {@link EditText}でユーザーのテキスト入力を受けて返す<br>
 * <br>
 * 入力結果を受け取りたい場合は、呼び出し元の{@link Activity}に
 * {@link EditTextDialogFragment.EventListener}を実装するか、
 * 同インターフェースを実装した{@link android.support.v4.app.Fragment}の
 * IDまたはTagを起動パラメータに渡すこと
 *
 * @author shisei
 *
 */
public class EditTextDialogFragment extends DialogFragmentEx {
    private static final String EXTRA_TITLE = "EXTRA_TITLE";
    private static final String EXTRA_HINT = "EXTRA_HINT";
    private static final String EXTRA_INIT_TEXT = "EXTRA_INIT_TEXT";
    private static final String EXTRA_SINGLE_LINE = "EXTRA_SINGLE_LINE";
    private static final String EXTRA_REQUEST_CODE = "EXTRA_REQUEST_CODE";
    private static final String EXTRA_PARAM = "EXTRA_PARAM";
    private static final String EXTRA_FRAGMENT_LISTENER_ID = "EXTRA_FRAGMENT_LISTENER_ID";
    private static final String EXTRA_FRAGMENT_LISTENER_TAG = "EXTRA_FRAGMENT_LISTENER_TAG";

    private static final String KEY_ARGUMENTS = "KEY_ARGUMENTS";

    private EditText mEditText;

    public static interface EventListener {
        /**
         * @param fragment
         * @param text 入力テキスト
         */
        void onEditTextDialogFragmentResult(EditTextDialogFragment fragment,
                String text);
        /**
         * {@link Dialog}がキャンセルされた
         * @param fragment
         */
        void onEditTextDialogFragmentCancel(EditTextDialogFragment fragment);
    }

    /**
     *
     * @param title {@link Dialog}のタイトル。無いならnull
     * @param hint {@link EditText}に表示するヒント。無いならnull
     * @param initText {@link EditText}の初期テキスト。無いならnull
     * @param singleLine 改行の許可の有無
     * @param requestCode 後で{@link EditTextDialogFragment#getRequestCode}で取得できる値
     * @param param 後で{@link EditTextDialogFragment#getParam}で取得できる値
     * @return 新規作成した{@link EditTextDialogFragment}
     */
    public static EditTextDialogFragment newInstance(CharSequence title,
            CharSequence hint, CharSequence initText, boolean singleLine,
            int requestCode, int param) {
        return newInstance(title, hint, initText, singleLine, requestCode, param, 0, null);
    }

    /**
     *
     * @param title {@link Dialog}のタイトル。無いならnull
     * @param hint {@link EditText}に表示するヒント。無いならnull
     * @param initText {@link EditText}の初期テキスト。無いならnull
     * @param singleLine 改行の許可の有無
     * @param requestCode 後で{@link EditTextDialogFragment#getRequestCode}で取得できる値
     * @param param 後で{@link EditTextDialogFragment#getParam}で取得できる値
     * @param fragmentListenerId {@link EventListener}を実装したFragmentのID。無いなら0
     * @param fragmentListenerTag {@link EventListener}を実装したFragmentのTag。無いならnull
     * @return 新規作成した{@link EditTextDialogFragment}
     */
    public static EditTextDialogFragment newInstance(CharSequence title,
            CharSequence hint, CharSequence initText, boolean singleLine,
            int requestCode, int param, int fragmentListenerId, String fragmentListenerTag) {
        EditTextDialogFragment fragment = new EditTextDialogFragment();
        Bundle args = new Bundle(7);
        args.putCharSequence(EXTRA_TITLE, title);
        args.putCharSequence(EXTRA_HINT, hint);
        args.putCharSequence(EXTRA_INIT_TEXT, initText);
        args.putBoolean(EXTRA_SINGLE_LINE, singleLine);
        args.putInt(EXTRA_REQUEST_CODE, requestCode);
        args.putInt(EXTRA_PARAM, param);
        args.putInt(EXTRA_FRAGMENT_LISTENER_ID, fragmentListenerId);
        args.putString(EXTRA_FRAGMENT_LISTENER_TAG, fragmentListenerTag);
        fragment.setArguments(args);
        return fragment;
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setCancelable(true);
        setStyle(DialogFragment.STYLE_NORMAL, 0);
        Bundle args = getArguments();
        if (args == null && savedInstanceState != null) {
            args = savedInstanceState.getBundle(KEY_ARGUMENTS);
            setArguments(args);
        }
    }

    @Override
    public Dialog onCreateDialog(Bundle savedInstanceState) {
        Activity activity = getActivity();
        FrameLayout view = new FrameLayout(activity);
        view.setLayoutParams(new ViewGroup.LayoutParams(FILL_PARENT, WRAP_CONTENT));
        float density = getResources().getDisplayMetrics().density;
        view.setPadding((int) (10 * density), 0, (int) (10 * density), 0);

        EditText editText = new EditText(activity);
        mEditText = editText;
//        editText.setTextAppearance(activity, android.R.attr.textAppearanceMedium);

        view.addView(editText, new ViewGroup.LayoutParams(
                FILL_PARENT, WRAP_CONTENT));

        AlertDialog.Builder builder = new AlertDialog.Builder(activity)
            .setView(view)
            .setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
                @Override
                public void onClick(DialogInterface dialog, int which) {
                    callOnResult();
                }
            })
            .setNegativeButton(android.R.string.cancel, new DialogInterface.OnClickListener() {
                @Override
                public void onClick(DialogInterface dialog, int which) {
                    callOnCancel();
                }
            });

        Bundle args = getArguments();
        if (args != null) {
            CharSequence hint = args.getCharSequence(EXTRA_HINT);
            if (hint != null) {
                editText.setHint(hint);
            }
            CharSequence initText = args.getCharSequence(EXTRA_INIT_TEXT);
            if (initText != null) {
                editText.setText(initText);
            }
            boolean singleLine = args.getBoolean(EXTRA_SINGLE_LINE, false);
            editText.setSingleLine(singleLine);
            if (!singleLine) {
                editText.setMinLines(3);
            }
            CharSequence title = args.getCharSequence(EXTRA_TITLE);
            if (title != null) {
                builder.setTitle(title);
            }
        }

        return builder.create();
    }

    @Override
    public void onCancel(DialogInterface dialog) {
        super.onCancel(dialog);
        callOnCancel();
    }

    @Override
    public void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
        outState.putBundle(KEY_ARGUMENTS, getArguments());
    }

    /**
     *
     * @return 設定したrequest code。予期せぬエラーが起きた場合は0
     */
    public int getRequestCode() {
        Bundle args = getArguments();
        if (args == null) {
            return 0;
        }
        return args.getInt(EXTRA_REQUEST_CODE, 0);
    }

    /**
     *
     * @return 設定したparam。未設定の場合は0
     */
    public int getParam() {
        Bundle args = getArguments();
        if (args == null) {
            return 0;
        }
        return args.getInt(EXTRA_PARAM, 0);
    }

    void callOnResult() {
        String result = mEditText.getText().toString();

        Activity activity = getActivity();
        if (activity instanceof EventListener) {
            ((EventListener) activity).onEditTextDialogFragmentResult(
                    this, result);
        }
        Bundle args = getArguments();
        if (args != null) {
            int id = args.getInt(EXTRA_FRAGMENT_LISTENER_ID);
            if (id != 0) {
                Fragment fragment = getFragmentManager().findFragmentById(id);
                if (fragment instanceof EventListener) {
                    ((EventListener) fragment).onEditTextDialogFragmentResult(
                            this, result);
                }
            }
            String tag = args.getString(EXTRA_FRAGMENT_LISTENER_TAG);
            if (tag != null) {
                Fragment fragment = getFragmentManager().findFragmentByTag(tag);
                if (fragment instanceof EventListener) {
                    ((EventListener) fragment).onEditTextDialogFragmentResult(
                            this, result);
                }
            }
        }
    }

    void callOnCancel() {
        Activity activity = getActivity();
        if (activity instanceof EventListener) {
            ((EventListener) activity).onEditTextDialogFragmentCancel(
                    this);
        }
        Bundle args = getArguments();
        if (args != null) {
            int id = args.getInt(EXTRA_FRAGMENT_LISTENER_ID);
            if (id != 0) {
                Fragment fragment = getFragmentManager().findFragmentById(id);
                if (fragment instanceof EventListener) {
                    ((EventListener) fragment).onEditTextDialogFragmentCancel(
                            this);
                }
            }
            String tag = args.getString(EXTRA_FRAGMENT_LISTENER_TAG);
            if (tag != null) {
                Fragment fragment = getFragmentManager().findFragmentByTag(tag);
                if (fragment instanceof EventListener) {
                    ((EventListener) fragment).onEditTextDialogFragmentCancel(
                            this);
                }
            }
        }
    }
}
