/*
 * Copyright (C) 2019 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.android.car.ui.toolbar;

import android.car.drivingstate.CarUxRestrictions;
import android.content.Context;
import android.graphics.drawable.Drawable;
import android.view.View;
import android.widget.Toast;

import androidx.annotation.VisibleForTesting;

import com.android.car.ui.R;
import com.android.car.ui.utils.CarUxRestrictionsUtil;

import java.lang.ref.WeakReference;

/**
 * Represents a button to display in the {@link Toolbar}.
 *
 * <p>There are currently 3 types of buttons: icon, text, and switch. Using
 * {@link Builder#setCheckable()} will ensure that you get a switch, after that
 * {@link Builder#setIcon(int)} will ensure an icon, and anything left just requires
 * {@link Builder#setTitle(int)}.
 *
 * <p>Each MenuItem has a {@link DisplayBehavior} that controls if it appears on the {@link Toolbar}
 * itself, or it's overflow menu.
 *
 * <p>If you require a search or settings button, you should use
 * {@link Builder#setToSearch()} or
 * {@link Builder#setToSettings()}.
 *
 * <p>Some properties can be changed after the creating a MenuItem, but others require being set
 * with a {@link Builder}.
 */
public class MenuItem {

    private final Context mContext;
    private final boolean mIsCheckable;
    private final boolean mIsActivatable;
    private final boolean mIsSearch;
    private final boolean mShowIconAndTitle;
    private final boolean mIsTinted;
    @CarUxRestrictions.CarUxRestrictionsInfo

    private int mId;
    private CarUxRestrictions mCurrentRestrictions;
    // This is a WeakReference to allow the Toolbar (and by extension, the whole screen
    // the toolbar is on) to be garbage-collected if the MenuItem is held past the
    // lifecycle of the toolbar.
    private WeakReference<Listener> mListener = new WeakReference<>(null);
    private CharSequence mTitle;
    private Drawable mIcon;
    private OnClickListener mOnClickListener;
    private DisplayBehavior mDisplayBehavior;
    private int mUxRestrictions;
    private boolean mIsEnabled;
    private boolean mIsChecked;
    private boolean mIsVisible;
    private boolean mIsActivated;

    private MenuItem(Builder builder) {
        mContext = builder.mContext;
        mId = builder.mId;
        mIsCheckable = builder.mIsCheckable;
        mIsActivatable = builder.mIsActivatable;
        mTitle = builder.mTitle;
        mIcon = builder.mIcon;
        mOnClickListener = builder.mOnClickListener;
        mDisplayBehavior = builder.mDisplayBehavior;
        mIsEnabled = builder.mIsEnabled;
        mIsChecked = builder.mIsChecked;
        mIsVisible = builder.mIsVisible;
        mIsActivated = builder.mIsActivated;
        mIsSearch = builder.mIsSearch;
        mShowIconAndTitle = builder.mShowIconAndTitle;
        mIsTinted = builder.mIsTinted;
        mUxRestrictions = builder.mUxRestrictions;

        mCurrentRestrictions = CarUxRestrictionsUtil.getInstance(mContext).getCurrentRestrictions();
    }

    private void update() {
        Listener listener = mListener.get();
        if (listener != null) {
            listener.onMenuItemChanged();
        }
    }

    /** Sets the id, which is purely for the client to distinguish MenuItems with.  */
    public void setId(int id) {
        mId = id;
        update();
    }

    /** Gets the id, which is purely for the client to distinguish MenuItems with. */
    public int getId() {
        return mId;
    }

    /** Returns whether the MenuItem is enabled */
    public boolean isEnabled() {
        return mIsEnabled;
    }

    /** Sets whether the MenuItem is enabled */
    public void setEnabled(boolean enabled) {
        mIsEnabled = enabled;

        update();
    }

    /** Returns whether the MenuItem is checkable. If it is, it will be displayed as a switch. */
    public boolean isCheckable() {
        return mIsCheckable;
    }

    /**
     * Returns whether the MenuItem is currently checked. Only valid if {@link #isCheckable()}
     * is true.
     */
    public boolean isChecked() {
        return mIsChecked;
    }

    /**
     * Sets whether or not the MenuItem is checked.
     * @throws IllegalStateException When {@link #isCheckable()} is false.
     */
    public void setChecked(boolean checked) {
        if (!isCheckable()) {
            throw new IllegalStateException("Cannot call setChecked() on a non-checkable MenuItem");
        }

        mIsChecked = checked;

        update();
    }

    public boolean isTinted() {
        return mIsTinted;
    }

    /** Returns whether or not the MenuItem is visible */
    public boolean isVisible() {
        return mIsVisible;
    }

    /** Sets whether or not the MenuItem is visible */
    public void setVisible(boolean visible) {
        mIsVisible = visible;

        update();
    }

    /**
     * Returns whether the MenuItem is activatable. If it is, it's every click will toggle
     * the MenuItem's View to appear activated or not.
     */
    public boolean isActivatable() {
        return mIsActivatable;
    }

    /** Returns whether or not this view is selected. Toggles after every click */
    public boolean isActivated() {
        return mIsActivated;
    }

    /** Sets the MenuItem as activated and updates it's View to the activated state */
    public void setActivated(boolean activated) {
        if (!isActivatable()) {
            throw new IllegalStateException(
                    "Cannot call setActivated() on a non-activatable MenuItem");
        }

        mIsActivated = activated;

        update();
    }

    /** Gets the title of this MenuItem. */
    public CharSequence getTitle() {
        return mTitle;
    }

    /** Sets the title of this MenuItem. */
    public void setTitle(CharSequence title) {
        mTitle = title;

        update();
    }

    /** Sets the title of this MenuItem to a string resource. */
    public void setTitle(int resId) {
        setTitle(mContext.getString(resId));
    }

    /** Sets the UxRestrictions of this MenuItem. */
    public void setUxRestrictions(@CarUxRestrictions.CarUxRestrictionsInfo int uxRestrictions) {
        if (mUxRestrictions != uxRestrictions) {
            mUxRestrictions = uxRestrictions;
            update();
        }
    }

    @CarUxRestrictions.CarUxRestrictionsInfo
    public int getUxRestrictions() {
        return mUxRestrictions;
    }

    /** Gets the current {@link OnClickListener} */
    public OnClickListener getOnClickListener() {
        return mOnClickListener;
    }

    public boolean isShowingIconAndTitle() {
        return mShowIconAndTitle;
    }

    /** Sets the {@link OnClickListener} */
    public void setOnClickListener(OnClickListener listener) {
        mOnClickListener = listener;

        update();
    }

    /* package */ void setCarUxRestrictions(CarUxRestrictions restrictions) {
        boolean wasRestricted = isRestricted();
        mCurrentRestrictions = restrictions;

        if (isRestricted() != wasRestricted) {
            update();
        }
    }

    /* package */ boolean isRestricted() {
        return CarUxRestrictionsUtil.isRestricted(mUxRestrictions, mCurrentRestrictions);
    }

    /** Calls the {@link OnClickListener}. */
    @VisibleForTesting(otherwise = VisibleForTesting.PACKAGE_PRIVATE)
    public void performClick() {
        if (!isEnabled() || !isVisible()) {
            return;
        }

        if (isRestricted()) {
            Toast.makeText(mContext,
                    R.string.car_ui_restricted_while_driving, Toast.LENGTH_LONG).show();
            return;
        }

        if (isActivatable()) {
            setActivated(!isActivated());
        }

        if (isCheckable()) {
            setChecked(!isChecked());
        }

        if (mOnClickListener != null) {
            mOnClickListener.onClick(this);
        }
    }

    /** Gets the current {@link DisplayBehavior} */
    public DisplayBehavior getDisplayBehavior() {
        return mDisplayBehavior;
    }

    /** Gets the current Icon */
    public Drawable getIcon() {
        return mIcon;
    }

    /** Sets the Icon of this MenuItem. */
    public void setIcon(Drawable icon) {
        mIcon = icon;

        update();
    }

    /** Sets the Icon of this MenuItem to a drawable resource. */
    public void setIcon(int resId) {
        setIcon(resId == 0
                ? null
                : mContext.getDrawable(resId));
    }

    /** Returns if this is the search MenuItem, which has special behavior when searching */
    boolean isSearch() {
        return mIsSearch;
    }

    /** Builder class */
    public static final class Builder {
        private final Context mContext;
        private final CharSequence mSearchTitle;
        private final CharSequence mSettingsTitle;
        private final Drawable mSearchIcon;
        private final Drawable mSettingsIcon;

        private int mId = View.NO_ID;
        private CharSequence mTitle;
        private Drawable mIcon;
        private OnClickListener mOnClickListener;
        private DisplayBehavior mDisplayBehavior = DisplayBehavior.ALWAYS;
        private boolean mIsTinted = true;
        private boolean mShowIconAndTitle = false;
        private boolean mIsEnabled = true;
        private boolean mIsCheckable = false;
        private boolean mIsChecked = false;
        private boolean mIsVisible = true;
        private boolean mIsActivatable = false;
        private boolean mIsActivated = false;
        private boolean mIsSearch = false;
        private boolean mIsSettings = false;
        @CarUxRestrictions.CarUxRestrictionsInfo
        private int mUxRestrictions = CarUxRestrictions.UX_RESTRICTIONS_BASELINE;

        public Builder(Context c) {
            // Must use getApplicationContext to avoid leaking activities when the MenuItem
            // is held onto for longer than the Activity's lifecycle
            mContext = c.getApplicationContext();
            mSearchTitle = mContext.getString(R.string.car_ui_toolbar_menu_item_search_title);
            mSettingsTitle = mContext.getString(R.string.car_ui_toolbar_menu_item_settings_title);
            mSearchIcon = mContext.getDrawable(R.drawable.car_ui_icon_search);
            mSettingsIcon = mContext.getDrawable(R.drawable.car_ui_icon_settings);
        }

        /** Builds a {@link MenuItem} from the current state of the Builder */
        public MenuItem build() {
            if (mIsActivatable && (mShowIconAndTitle || mIcon == null)) {
                throw new IllegalStateException("Only simple icons can be activatable");
            }
            if (mIsCheckable
                    && (mDisplayBehavior == DisplayBehavior.NEVER
                    || mShowIconAndTitle
                    || mIsActivatable)) {
                throw new IllegalStateException("Unsupported options for a checkable MenuItem");
            }
            if (mIsSearch && mIsSettings) {
                throw new IllegalStateException("Can't have both a search and settings MenuItem");
            }

            if (mIsSearch && (!mSearchTitle.equals(mTitle)
                    || !mSearchIcon.equals(mIcon)
                    || mIsCheckable
                    || mIsActivatable
                    || !mIsTinted
                    || mShowIconAndTitle
                    || mDisplayBehavior != DisplayBehavior.ALWAYS)) {
                throw new IllegalStateException("Invalid search MenuItem");
            }

            if (mIsSettings && (!mSettingsTitle.equals(mTitle)
                    || !mSettingsIcon.equals(mIcon)
                    || mIsCheckable
                    || mIsActivatable
                    || !mIsTinted
                    || mShowIconAndTitle
                    || mDisplayBehavior != DisplayBehavior.ALWAYS
                    || mUxRestrictions != CarUxRestrictions.UX_RESTRICTIONS_NO_SETUP)) {
                throw new IllegalStateException("Invalid settings MenuItem");
            }

            return new MenuItem(this);
        }

        /** Sets the id, which is purely for the client to distinguish MenuItems with. */
        public Builder setId(int id) {
            mId = id;
            return this;
        }

        /** Sets the title to a string resource id */
        public Builder setTitle(int resId) {
            setTitle(mContext.getString(resId));
            return this;
        }

        /** Sets the title */
        public Builder setTitle(CharSequence title) {
            mTitle = title;
            return this;
        }

        /**
         * Sets the icon to a drawable resource id.
         *
         * <p>The icon's color and size will be changed to match the other MenuItems.
         */
        public Builder setIcon(int resId) {
            mIcon = resId == 0
                    ? null
                    : mContext.getDrawable(resId);
            return this;
        }

        /**
         * Sets the icon to a drawable.
         *
         * <p>The icon's color and size will be changed to match the other MenuItems.
         */
        public Builder setIcon(Drawable icon) {
            mIcon = icon;
            return this;
        }

        /**
         * Sets whether to tint the icon, true by default.
         *
         * <p>Try not to use this, it should only be used if the MenuItem is displaying some
         * kind of logo or avatar and should be colored.
         */
        public Builder setTinted(boolean tinted) {
            mIsTinted = tinted;
            return this;
        }

        /** Sets whether the MenuItem is visible or not. Default true. */
        public Builder setVisible(boolean visible) {
            mIsVisible = visible;
            return this;
        }

        /**
         * Makes the MenuItem activatable, which means it will toggle it's visual state after
         * every click.
         */
        public Builder setActivatable() {
            mIsActivatable = true;
            return this;
        }

        /**
         * Sets whether or not the MenuItem is selected. If it is,
         * {@link View#setSelected(boolean)} will be called on its View.
         */
        public Builder setActivated(boolean activated) {
            setActivatable();
            mIsActivated = activated;
            return this;
        }

        /** Sets the {@link OnClickListener} */
        public Builder setOnClickListener(OnClickListener listener) {
            mOnClickListener = listener;
            return this;
        }

        /**
         * Used to show both the icon and title when displayed on the toolbar. If this
         * is false, only the icon while be displayed when the MenuItem is in the toolbar
         * and only the title will be displayed when the MenuItem is in the overflow menu.
         *
         * <p>Defaults to false.
         */
        public Builder setShowIconAndTitle(boolean showIconAndTitle) {
            mShowIconAndTitle = showIconAndTitle;
            return this;
        }

        /**
         * Sets the {@link DisplayBehavior}.
         *
         * <p>If the DisplayBehavior is {@link DisplayBehavior#NEVER}, the MenuItem must not be
         * {@link #setCheckable() checkable}.
         */
        public Builder setDisplayBehavior(DisplayBehavior behavior) {
            mDisplayBehavior = behavior;
            return this;
        }

        /** Sets whether the MenuItem is enabled or not. Default true. */
        public Builder setEnabled(boolean enabled) {
            mIsEnabled = enabled;
            return this;
        }

        /**
         * Makes the MenuItem checkable, meaning it will be displayed as a
         * switch. Currently a checkable MenuItem cannot have a {@link DisplayBehavior} of NEVER.
         *
         * <p>The MenuItem is not checkable by default.
         */
        public Builder setCheckable() {
            mIsCheckable = true;
            return this;
        }

        /**
         * Sets whether the MenuItem is checked or not. This will imply {@link #setCheckable()}.
         */
        public Builder setChecked(boolean checked) {
            setCheckable();
            mIsChecked = checked;
            return this;
        }

        /**
         * Sets under what {@link android.car.drivingstate.CarUxRestrictions.CarUxRestrictionsInfo}
         * the MenuItem should be restricted.
         */
        public Builder setUxRestrictions(
                @CarUxRestrictions.CarUxRestrictionsInfo int restrictions) {
            mUxRestrictions = restrictions;
            return this;
        }

        /**
         * Creates a search MenuItem.
         *
         * <p>The advantage of using this over creating your own is getting an OEM-styled search
         * icon, and this button will always disappear while searching, even when the
         * {@link Toolbar Toolbar's} showMenuItemsWhileSearching is true.
         *
         * <p>If using this, you should only change the id, visibility, or onClickListener.
         */
        public Builder setToSearch() {
            mIsSearch = true;
            setTitle(mSearchTitle);
            setIcon(mSearchIcon);
            return this;
        }

        /**
         * Creates a settings MenuItem.
         *
         * <p>The advantage of this over creating your own is getting an OEM-styled settings icon,
         * and that the MenuItem will be restricted based on
         * {@link CarUxRestrictions#UX_RESTRICTIONS_NO_SETUP}
         *
         * <p>If using this, you should only change the id, visibility, or onClickListener.
         */
        public Builder setToSettings() {
            mIsSettings = true;
            setTitle(mSettingsTitle);
            setIcon(mSettingsIcon);
            setUxRestrictions(CarUxRestrictions.UX_RESTRICTIONS_NO_SETUP);
            return this;
        }

        /** @deprecated Use {@link #setToSearch()} instead. */
        @Deprecated
        public static MenuItem createSearch(Context c, OnClickListener listener) {
            return MenuItem.builder(c)
                    .setToSearch()
                    .setOnClickListener(listener)
                    .build();
        }

        /** @deprecated Use {@link #setToSettings()} instead. */
        @Deprecated
        public static MenuItem createSettings(Context c, OnClickListener listener) {
            return MenuItem.builder(c)
                    .setToSettings()
                    .setOnClickListener(listener)
                    .build();
        }
    }

    /** Get a new {@link Builder}. */
    public static Builder builder(Context context) {
        return new Builder(context);
    }

    /**
     * OnClickListener for a MenuItem.
     */
    public interface OnClickListener {
        /** Called when the MenuItem is clicked */
        void onClick(MenuItem item);
    }

    /**
     * DisplayBehavior controls how the MenuItem is presented in the Toolbar
     */
    public enum DisplayBehavior {
        /** Always show the MenuItem on the toolbar instead of the overflow menu */
        ALWAYS,
        /** Never show the MenuItem in the toolbar, always put it in the overflow menu */
        NEVER
    }

    /** Listener for {@link Toolbar} to update when this MenuItem changes */
    interface Listener {
        /** Called when the MenuItem is changed. For use only by {@link Toolbar} */
        void onMenuItemChanged();
    }

    /**
     * Sets a listener for changes to this MenuItem. Note that the MenuItem will only hold
     * weak references to the Listener, so that the listener is not held if the MenuItem
     * outlives the toolbar.
     */
    void setListener(Listener listener) {
        mListener = new WeakReference<>(listener);
    }
}
