package com.marcoscg.dialogsheet;

import android.annotation.SuppressLint;
import android.content.Context;
import android.content.DialogInterface;
import android.content.res.ColorStateList;
import android.content.res.Configuration;
import android.graphics.Bitmap;
import android.graphics.Color;
import android.graphics.PorterDuff;
import android.graphics.Typeface;
import android.graphics.drawable.Drawable;
import android.os.Build;
import android.support.annotation.ColorInt;
import android.support.annotation.ColorRes;
import android.support.annotation.DrawableRes;
import android.support.annotation.LayoutRes;
import android.support.annotation.StringRes;
import android.support.design.button.MaterialButton;
import android.support.v4.content.ContextCompat;
import android.support.v7.widget.AppCompatImageView;
import android.support.v7.widget.AppCompatTextView;
import android.text.TextUtils;
import android.util.TypedValue;
import android.view.View;
import android.view.WindowManager;
import android.widget.LinearLayout;
import android.widget.RelativeLayout;

import static com.marcoscg.dialogsheet.Utils.adjustAlpha;
import static com.marcoscg.dialogsheet.Utils.dpToPx;
import static com.marcoscg.dialogsheet.Utils.isColorLight;

/**
 * Created by @MarcosCGdev on 01/12/2017.
 */

public class DialogSheet {

    private Context context;
    private ExpandedBottomSheetDialog bottomSheetDialog;
    private int backgroundColor = 0, titleTextColor = 0, messageTextColor = 0;
    private boolean coloredNavigationBar = false;

    private AppCompatTextView titleTextView, messageTextView;
    private AppCompatImageView iconImageView;
    private MaterialButton positiveButton, negativeButton, neutralButton;
    private RelativeLayout textContainer;
    private LinearLayout messageContainer;

    private View inflatedView;

    public interface OnPositiveClickListener {
        public void onClick(View v);
    }

    public interface OnNegativeClickListener {
        public void onClick(View v);
    }

    public interface OnNeutralClickListener {
        public void onClick(View v);
    }

    public DialogSheet(Context context) {
        this.context = context;
        init(context);
    }

    public DialogSheet setTitle(CharSequence title) {
        if (title == null)
            titleTextView.setVisibility(View.GONE);
        else {
            titleTextView.setVisibility(View.VISIBLE);
            titleTextView.setText(title);
        }

        return this;
    }

    public DialogSheet setTitle(@StringRes int titleRes) {
        setTitle(context.getResources().getString(titleRes));
        return this;
    }

    public DialogSheet setMessage(CharSequence message) {
        if (message == null)
            messageTextView.setVisibility(View.GONE);
        else {
            messageTextView.setVisibility(View.VISIBLE);
            messageTextView.setText(message);
        }

        return this;
    }

    public DialogSheet setMessage(@StringRes int messageRes) {
        setMessage(context.getResources().getString(messageRes));
        return this;
    }

    public DialogSheet setIconDrawable(Drawable icon) {
        if (icon == null)
            hideIcon();
        else {
            showIcon();
            iconImageView.setImageDrawable(icon);
        }

        return this;
    }

    public DialogSheet setIconBitmap(Bitmap icon) {
        if (icon == null)
            hideIcon();
        else {
            showIcon();
            iconImageView.setImageBitmap(icon);
        }

        return this;
    }

    public DialogSheet setIconResource(@DrawableRes int icon) {
        showIcon();
        iconImageView.setImageResource(icon);

        return this;
    }

    /**
     * @param icon
     * @return
     * @deprecated use {@link #setIconDrawable(Drawable)} instead.
     */
    @Deprecated
    public DialogSheet setIcon(Drawable icon) {
        setIconDrawable(icon);

        return this;
    }

    /**
     * @param icon
     * @return
     * @deprecated use {@link #setIconBitmap(Bitmap)} instead.
     */
    @Deprecated
    public DialogSheet setIcon(Bitmap icon) {
        setIconBitmap(icon);

        return this;
    }

    /**
     * @param iconRes
     * @return
     * @deprecated use {@link #setIconResource(int)} instead.
     */
    @Deprecated
    public DialogSheet setIcon(@DrawableRes int iconRes) {
        showIcon();
        iconImageView.setImageResource(iconRes);
        return this;
    }

    public DialogSheet setPositiveButton(CharSequence text, final boolean shouldDismiss, final OnPositiveClickListener onPositiveClickListener) {
        if (text == null)
            positiveButton.setVisibility(View.GONE);
        else {
            positiveButton.setVisibility(View.VISIBLE);
            positiveButton.setText(text);
            positiveButton.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
                    if (shouldDismiss)
                        bottomSheetDialog.dismiss();

                    if (onPositiveClickListener != null)
                        onPositiveClickListener.onClick(view);
                }
            });
        }

        return this;
    }

    public DialogSheet setPositiveButton(CharSequence text, final OnPositiveClickListener onPositiveClickListener) {
        setPositiveButton(text, true, onPositiveClickListener);
        return this;
    }

    public DialogSheet setPositiveButton(@StringRes int textRes, boolean shouldDismiss, OnPositiveClickListener onPositiveClickListener) {
        setPositiveButton(context.getResources().getString(textRes), shouldDismiss, onPositiveClickListener);
        return this;
    }

    public DialogSheet setPositiveButton(@StringRes int textRes, OnPositiveClickListener onPositiveClickListener) {
        setPositiveButton(context.getResources().getString(textRes), true, onPositiveClickListener);
        return this;
    }

    public DialogSheet setNegativeButton(CharSequence text, final boolean shouldDismiss, final OnNegativeClickListener onNegativeClickListener) {
        if (text == null)
            negativeButton.setVisibility(View.GONE);
        else {
            negativeButton.setVisibility(View.VISIBLE);
            negativeButton.setText(text);
            negativeButton.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
                    if (shouldDismiss)
                        bottomSheetDialog.dismiss();

                    if (onNegativeClickListener != null)
                        onNegativeClickListener.onClick(view);
                }
            });
        }

        return this;
    }

    public DialogSheet setNegativeButton(CharSequence text, final OnNegativeClickListener onNegativeClickListener) {
        setNegativeButton(text, true, onNegativeClickListener);
        return this;
    }

    public DialogSheet setNegativeButton(@StringRes int textRes, boolean shouldDismiss, OnNegativeClickListener onNegativeClickListener) {
        setNegativeButton(context.getResources().getString(textRes), shouldDismiss, onNegativeClickListener);
        return this;
    }

    public DialogSheet setNegativeButton(@StringRes int textRes, OnNegativeClickListener onNegativeClickListener) {
        setNegativeButton(context.getResources().getString(textRes), true, onNegativeClickListener);
        return this;
    }

    public DialogSheet setNeutralButton(CharSequence text, final boolean shouldDismiss, final OnNeutralClickListener onNegativeClickListener) {
        if (text == null)
            neutralButton.setVisibility(View.GONE);
        else {
            neutralButton.setVisibility(View.VISIBLE);
            neutralButton.setText(text);
            neutralButton.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
                    if (shouldDismiss)
                        bottomSheetDialog.dismiss();

                    if (onNegativeClickListener != null)
                        onNegativeClickListener.onClick(view);
                }
            });
        }

        return this;
    }

    public DialogSheet setNeutralButton(CharSequence text, final OnNeutralClickListener onNegativeClickListener) {
        setNeutralButton(text, true, onNegativeClickListener);
        return this;
    }

    public DialogSheet setNeutralButton(@StringRes int textRes, boolean shouldDismiss, OnNeutralClickListener onNegativeClickListener) {
        setNeutralButton(context.getResources().getString(textRes), shouldDismiss, onNegativeClickListener);
        return this;
    }

    public DialogSheet setNeutralButton(@StringRes int textRes, OnNeutralClickListener onNegativeClickListener) {
        setNeutralButton(context.getResources().getString(textRes), true, onNegativeClickListener);
        return this;
    }

    public DialogSheet setButtonsTextAllCaps(boolean textAllCaps) {
        positiveButton.setAllCaps(textAllCaps);
        negativeButton.setAllCaps(textAllCaps);
        neutralButton.setAllCaps(textAllCaps);

        return this;
    }

    @SuppressLint("RestrictedApi")
    public DialogSheet setButtonsColor(@ColorInt int buttonsColor) {
        int rippleColor = adjustAlpha(buttonsColor, 0.2f);
        ColorStateList secondaryButtonColor = new ColorStateList(
                new int[][]{
                                new int[]{android.R.attr.state_pressed},
                                new int[]{android.R.attr.state_focused},
                                new int[]{android.R.attr.state_activated},
                                new int[]{}
                        },
                new int[]{
                                rippleColor,
                                rippleColor,
                                rippleColor,
                                Color.TRANSPARENT
                        });

        positiveButton.setSupportBackgroundTintList(ColorStateList.valueOf(buttonsColor));

        negativeButton.setTextColor(buttonsColor);
        negativeButton.setRippleColor(secondaryButtonColor);
        neutralButton.setTextColor(buttonsColor);
        neutralButton.setRippleColor(secondaryButtonColor);
        return this;
    }

    public DialogSheet setButtonsColorRes(@ColorRes int buttonsColorRes) {
        setButtonsColor(ContextCompat.getColor(context, buttonsColorRes));
        return this;
    }

    public DialogSheet setBackgroundColor(@ColorInt int backgroundColor) {
        this.backgroundColor = backgroundColor;
        return this;
    }

    public DialogSheet setBackgroundColorRes(@ColorRes int backgroundColorRes) {
        setBackgroundColor(ContextCompat.getColor(context, backgroundColorRes));
        return this;
    }

    public DialogSheet setTitleTextColor(@ColorInt int titleTextColor) {
        this.titleTextColor = titleTextColor;
        return this;
    }

    public DialogSheet setTitleTextColorRes(@ColorRes int titleTextColorRes) {
        setTitleTextColor(ContextCompat.getColor(context, titleTextColorRes));
        return this;
    }

    public DialogSheet setMessageTextColor(@ColorInt int messageTextColor) {
        this.messageTextColor = messageTextColor;
        return this;
    }

    public DialogSheet setMessageTextColorRes(@ColorRes int messageTextColorRes) {
        setMessageTextColor(ContextCompat.getColor(context, messageTextColorRes));
        return this;
    }

    public DialogSheet setSingleLineTitle(boolean singleLine) {
        titleTextView.setSingleLine(singleLine);
        return this;
    }

    public DialogSheet setColoredNavigationBar(boolean coloredNavigationBar) {
        this.coloredNavigationBar = coloredNavigationBar;
        return this;
    }

    public DialogSheet setTitleTypeface(Typeface typeface) {
        titleTextView.setTypeface(typeface);

        return this;
    }

    public DialogSheet setMessageTypeface(Typeface typeface) {
        messageTextView.setTypeface(typeface);

        return this;
    }

    public DialogSheet setButtonsTypeface(Typeface typeface) {
        positiveButton.setTypeface(typeface);
        negativeButton.setTypeface(typeface);
        neutralButton.setTypeface(typeface);

        return this;
    }

    public DialogSheet setTitleTextSize(int sizeSp) {
        titleTextView.setTextSize(TypedValue.COMPLEX_UNIT_SP, sizeSp);

        return this;
    }

    public DialogSheet setMessageTextSize(int sizeSp) {
        messageTextView.setTextSize(TypedValue.COMPLEX_UNIT_SP, sizeSp);

        return this;
    }

    public DialogSheet setButtonsTextSize(int sizeSp) {
        positiveButton.setTextSize(TypedValue.COMPLEX_UNIT_SP, sizeSp);
        negativeButton.setTextSize(TypedValue.COMPLEX_UNIT_SP, sizeSp);
        neutralButton.setTextSize(TypedValue.COMPLEX_UNIT_SP, sizeSp);

        return this;
    }

    public DialogSheet setCancelable(boolean cancelable) {
        bottomSheetDialog.setCancelable(cancelable);
        return this;
    }

    public DialogSheet setRoundedCorners(boolean roundedCorners) {
        if (!roundedCorners) {
            View bgView = bottomSheetDialog.findViewById(R.id.mainDialogContainer);
            if (bgView != null)
                bgView.setBackgroundDrawable(ContextCompat.getDrawable(context, R.drawable.dialog_sheet_main_background));
        }

        return this;
    }

    public DialogSheet setView(View view) {
        removePreviousMessageViews();
        messageContainer.addView(view);
        inflatedView = view;
        return this;
    }

    public DialogSheet setView(@LayoutRes int layoutRes) {
        removePreviousMessageViews();
        inflatedView = View.inflate(context, layoutRes, null);
        setView(inflatedView);
        return this;
    }

    public DialogSheet setOnDismissListener(DialogInterface.OnDismissListener onDismissListener) {
        bottomSheetDialog.setOnDismissListener(onDismissListener);
        return this;
    }

    public View getInflatedView() {
        return inflatedView;
    }

    public void show() {
        if (backgroundColor == 0)
            backgroundColor = Utils.getAttrColor(context, android.R.attr.windowBackground);
        if (backgroundColor != 0) {
            Drawable bgDrawable = null;
            View bgView = bottomSheetDialog.findViewById(R.id.mainDialogContainer);
            if (bgView != null)
                bgDrawable = bgView.getBackground();

            if (bgDrawable != null)
                bgDrawable.setColorFilter(backgroundColor, PorterDuff.Mode.SRC_IN);
        }

        if (titleTextColor == 0)
            titleTextColor = Utils.getTextColor(backgroundColor);
        if (messageTextColor == 0)
            messageTextColor = Utils.getTextColorSec(backgroundColor);

        titleTextView.setTextColor(titleTextColor);
        messageTextView.setTextColor(messageTextColor);

        setColoredNavBar(coloredNavigationBar);

        if (positiveButton.getVisibility() != View.VISIBLE)
            ((RelativeLayout.LayoutParams) negativeButton.getLayoutParams()).addRule(RelativeLayout.ALIGN_PARENT_RIGHT);

        if (!areButtonsVisible()) {
            int bottomPadding = 0;
            int topPadding = 0;

            if (messageTextView.getText() != null && !TextUtils.isEmpty(messageTextView.getText())) {
                bottomPadding = dpToPx(24);

                if (titleTextView.getText() == null || TextUtils.isEmpty(titleTextView.getText()))
                    topPadding = dpToPx(24);
            }

            textContainer.setPadding(0, topPadding, 0, bottomPadding);
        } else {
            if ((titleTextView.getText() == null || TextUtils.isEmpty(titleTextView.getText()))
                    && messageTextView.getText() != null && !TextUtils.isEmpty(messageTextView.getText()))
                textContainer.setPadding(0, dpToPx(24), 0, 0);
        }

        bottomSheetDialog.show();

        // Landscape fixed width
        Configuration configuration = context.getResources().getConfiguration();
        if (configuration.orientation == Configuration.ORIENTATION_LANDSCAPE &&
                configuration.screenWidthDp > 400) {
            if (bottomSheetDialog.getWindow() != null)
                bottomSheetDialog.getWindow().setLayout(dpToPx(400), -1);
        }
    }

    public void dismiss() {
        bottomSheetDialog.dismiss();
    }

    private void init(Context context) {
        int accentColor = Utils.getAttrColor(context, R.attr.dialogSheetAccent);
        int posButtonTextColor = Color.WHITE;

        if (accentColor != -1) {
            bottomSheetDialog = new ExpandedBottomSheetDialog(context, R.style.DialogSheetTheme_Colored);
            posButtonTextColor = Utils.getTextColor(accentColor);
        } else bottomSheetDialog = new ExpandedBottomSheetDialog(context, R.style.DialogSheetTheme);

        bottomSheetDialog.setContentView(R.layout.layout_bottomdialog);

        if (bottomSheetDialog.getWindow() != null)
            bottomSheetDialog.getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE);

        titleTextView = bottomSheetDialog.findViewById(R.id.dialogTitle);
        messageTextView = bottomSheetDialog.findViewById(R.id.dialogMessage);
        iconImageView = bottomSheetDialog.findViewById(R.id.dialogIcon);
        positiveButton = bottomSheetDialog.findViewById(R.id.buttonPositive);
        negativeButton = bottomSheetDialog.findViewById(R.id.buttonNegative);
        neutralButton = bottomSheetDialog.findViewById(R.id.buttonNeutral);
        textContainer = bottomSheetDialog.findViewById(R.id.textContainer);
        messageContainer = bottomSheetDialog.findViewById(R.id.messageContainer);

        positiveButton.setTextColor(posButtonTextColor);
    }

    private void showIcon() {
        iconImageView.setVisibility(View.VISIBLE);
    }

    private void hideIcon() {
        iconImageView.setVisibility(View.GONE);
    }

    private void setColoredNavBar(boolean coloredNavigationBar) {
        if (coloredNavigationBar && bottomSheetDialog.getWindow() != null && Build.VERSION.SDK_INT >= 21) {
            if (isColorLight(backgroundColor)) {
                if (Build.VERSION.SDK_INT >= 26) {
                    bottomSheetDialog.getWindow().setNavigationBarColor(backgroundColor);
                    int flags = bottomSheetDialog.getWindow().getDecorView().getSystemUiVisibility();
                    flags |= View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR;
                    bottomSheetDialog.getWindow().getDecorView().setSystemUiVisibility(flags);
                }
            } else {
                bottomSheetDialog.getWindow().setNavigationBarColor(backgroundColor);

                if (Build.VERSION.SDK_INT >= 26) {
                    int flags = bottomSheetDialog.getWindow().getDecorView().getSystemUiVisibility();
                    flags &= ~View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR;
                    bottomSheetDialog.getWindow().getDecorView().setSystemUiVisibility(flags);
                }
            }
        }
    }

    private boolean areButtonsVisible() {
        return positiveButton.getVisibility() == View.VISIBLE || negativeButton.getVisibility() == View.VISIBLE
                || neutralButton.getVisibility() == View.VISIBLE;
    }

    private void removePreviousMessageViews() {
        for (int i = 1; i < messageContainer.getChildCount(); i++) {
            messageContainer.removeViewAt(i);
        }
    }

}