// Copyright 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

package org.chromium.chrome.browser.infobar;

import android.content.Context;
import android.text.Spannable;
import android.text.SpannableString;
import android.text.SpannableStringBuilder;
import android.text.TextUtils;
import android.text.style.ClickableSpan;
import android.view.View;
import android.widget.CheckBox;

import org.chromium.chrome.R;
import org.chromium.ui.base.DeviceFormFactor;

/**
 * Java version of the translate infobar
 */
public class TranslateInfoBar extends TwoButtonInfoBar implements SubPanelListener {
    // Needs to be kept in sync with the Type enum in translate_infobar_delegate.h.
    public static final int BEFORE_TRANSLATE_INFOBAR = 0;
    public static final int TRANSLATING_INFOBAR = 1;
    public static final int AFTER_TRANSLATE_INFOBAR = 2;
    public static final int TRANSLATE_ERROR_INFOBAR = 3;
    public static final int MAX_INFOBAR_INDEX = 4;

    // Defines what subpanel needs to be shown, if any
    public static final int NO_PANEL = 0;
    public static final int LANGUAGE_PANEL = 1;
    public static final int NEVER_PANEL = 2;
    public static final int ALWAYS_PANEL = 3;
    public static final int MAX_PANEL_INDEX = 4;

    private int mInfoBarType;
    private final TranslateOptions mOptions;
    private int mOptionsPanelViewType;
    private TranslateSubPanel mSubPanel;
    private final boolean mShouldShowNeverBar;
    private final TranslateInfoBarDelegate mTranslateDelegate;

    public TranslateInfoBar(long nativeInfoBarPtr, TranslateInfoBarDelegate delegate,
            int infoBarType, int sourceLanguageIndex, int targetLanguageIndex,
            boolean autoTranslatePair, boolean shouldShowNeverBar,
            boolean triggeredFromMenu, String[] languages) {
        super(null, BACKGROUND_TYPE_INFO,
                R.drawable.infobar_translate);

        mTranslateDelegate = delegate;
        mOptions = new TranslateOptions(sourceLanguageIndex, targetLanguageIndex, languages,
                autoTranslatePair, triggeredFromMenu);
        mInfoBarType = infoBarType;
        mShouldShowNeverBar = shouldShowNeverBar;
        mOptionsPanelViewType = NO_PANEL;
        setNativeInfoBar(nativeInfoBarPtr);
    }

    @Override
    public void onCloseButtonClicked() {
        if (getInfoBarType() == BEFORE_TRANSLATE_INFOBAR && mOptionsPanelViewType == NO_PANEL) {
            // Make it behave exactly as the Nope Button.
            onButtonClicked(false);
        } else {
            nativeOnCloseButtonClicked(mNativeInfoBarPtr);
        }
    }

    @Override
    public void onButtonClicked(boolean isPrimaryButton) {
        if (mSubPanel != null) {
            mSubPanel.onButtonClicked(isPrimaryButton);
            return;
        }

        int action = actionFor(isPrimaryButton);

        if (getInfoBarType() == BEFORE_TRANSLATE_INFOBAR && mOptionsPanelViewType == NO_PANEL
                && action == ACTION_TYPE_CANCEL && needsNeverPanel()) {
            // "Nope" was clicked and instead of dismissing we need to show
            // the extra never panel.
            swapPanel(NEVER_PANEL);
        } else {
            onTranslateInfoBarButtonClicked(action);
        }
    }

    /**
     * Based on the infobar and the button pressed figure out what action needs to happen.
     */
    private int actionFor(boolean isPrimaryButton) {
        int action = InfoBar.ACTION_TYPE_NONE;
        int infobarType = getInfoBarType();
        switch (infobarType) {
            case TranslateInfoBar.BEFORE_TRANSLATE_INFOBAR:
                action = isPrimaryButton
                        ? InfoBar.ACTION_TYPE_TRANSLATE : InfoBar.ACTION_TYPE_CANCEL;
                break;
            case TranslateInfoBar.AFTER_TRANSLATE_INFOBAR:
                if (!isPrimaryButton) {
                    action = InfoBar.ACTION_TYPE_TRANSLATE_SHOW_ORIGINAL;
                }
                break;
            case TranslateInfoBar.TRANSLATE_ERROR_INFOBAR:
                // retry
                action = InfoBar.ACTION_TYPE_TRANSLATE;
                break;
            default:
                break;
        }
        return action;
    }

    @Override
    public CharSequence getMessageText(Context context) {
        switch (getInfoBarType()) {
            case BEFORE_TRANSLATE_INFOBAR:
                String template = context.getString(R.string.translate_infobar_text);
                return formatBeforeInfoBarMessage(template, mOptions.sourceLanguage(),
                        mOptions.targetLanguage(), LANGUAGE_PANEL);
            case AFTER_TRANSLATE_INFOBAR:
                String translated = context.getString(
                        R.string.translate_infobar_translation_done, mOptions.targetLanguage());
                if (needsAlwaysPanel()) {
                    String moreOptions = context.getString(
                            R.string.translate_infobar_translation_more_options);
                    return formatAfterTranslateInfoBarMessage(translated, moreOptions,
                            ALWAYS_PANEL);
                } else {
                    return translated;
                }
            case TRANSLATING_INFOBAR:
                return context.getString(R.string.translate_infobar_translating,
                        mOptions.targetLanguage());
            default:
                return context.getString(R.string.translate_infobar_error);
        }
    }

    @Override
    public String getPrimaryButtonText(Context context) {
        switch (getInfoBarType()) {
            case BEFORE_TRANSLATE_INFOBAR:
                return context.getString(R.string.translate_button);
            case AFTER_TRANSLATE_INFOBAR:
                if (!needsAlwaysPanel()) {
                    return context.getString(R.string.translate_button_done);
                }
                return null;
            case TRANSLATE_ERROR_INFOBAR:
                return context.getString(R.string.translate_retry);
            default:
                return null; // no inner buttons on the remaining infobars
        }
    }

    @Override
    public String getSecondaryButtonText(Context context) {
        switch (getInfoBarType()) {
            case BEFORE_TRANSLATE_INFOBAR:
                return context.getString(R.string.translate_nope);
            case AFTER_TRANSLATE_INFOBAR:
                if (!needsAlwaysPanel()) {
                    return context.getString(R.string.translate_show_original);
                }
                return null;
            default:
                return null;
        }
    }

    @Override
    public void createContent(InfoBarLayout layout) {
        if (mOptionsPanelViewType == NO_PANEL) {
            mSubPanel = null;
        } else {
            mSubPanel = panelFor(mOptionsPanelViewType);
            if (mSubPanel != null) {
                mSubPanel.createContent(getContext(), layout);
            }
            return;
        }

        if (getInfoBarType() == AFTER_TRANSLATE_INFOBAR &&
                !needsAlwaysPanel() &&
                !mOptions.triggeredFromMenu()) {
            // Long always translate version
             TranslateCheckBox checkBox = new TranslateCheckBox(mOptions, this);
             checkBox.createContent(getContext(), layout);
        }

        super.createContent(layout);
    }

    // SubPanelListener implementation
    @Override
    public void onPanelClosed(int action) {
        setControlsEnabled(false);
        if (mOptionsPanelViewType == LANGUAGE_PANEL) {
            // Close the sub panel and show the infobar again.
            mOptionsPanelViewType = NO_PANEL;
            updateViewForCurrentState(createView());
        } else {
            // Apply options and close the infobar.
            onTranslateInfoBarButtonClicked(action);
        }
    }

    private void onTranslateInfoBarButtonClicked(int action) {
        onOptionsChanged();

        // We need to re-check if the pointer is null now because applying options (like never
        // translate this site) can sometimes trigger closing the InfoBar.
        if (mNativeInfoBarPtr == 0) return;
        nativeOnButtonClicked(mNativeInfoBarPtr, action, "");
    }

    @Override
    public void setControlsEnabled(boolean state) {
        super.setControlsEnabled(state);

        // Handle the "Always Translate" checkbox.
        ContentWrapperView wrapper = getContentWrapper(false);
        if (wrapper != null) {
            CheckBox checkBox = (CheckBox) wrapper.findViewById(R.id.infobar_extra_check);
            if (checkBox != null) checkBox.setEnabled(state);
        }
    }

    @Override
    public void onOptionsChanged() {
        if (mNativeInfoBarPtr == 0) return;

        if (mOptions.optionsChanged()) {
            mTranslateDelegate.applyTranslateOptions(mNativeInfoBarPtr,
                    mOptions.sourceLanguageIndex(),
                    mOptions.targetLanguageIndex(),
                    mOptions.alwaysTranslateLanguageState(),
                    mOptions.neverTranslateLanguageState(),
                    mOptions.neverTranslateDomainState());
        }
    }

    private boolean needsNeverPanel() {
        return (getInfoBarType() == TranslateInfoBar.BEFORE_TRANSLATE_INFOBAR
                && mShouldShowNeverBar);
    }

    private boolean needsAlwaysPanel() {
        return (getInfoBarType() == TranslateInfoBar.AFTER_TRANSLATE_INFOBAR
                && mOptions.alwaysTranslateLanguageState()
                && !DeviceFormFactor.isTablet(getContext()));
    }

    /**
     * @param newPanel id of the new panel to swap in. Use NO_PANEL to
     *     simply remove the current panel.
     */
    private void swapPanel(int newPanel) {
        assert (newPanel >= NO_PANEL && newPanel < MAX_PANEL_INDEX);
        mOptionsPanelViewType = newPanel;
        updateViewForCurrentState(createView());
    }

    /**
     * @return a panel of the specified {@code type}
     */
    private TranslateSubPanel panelFor(int type) {
        assert (type >= NO_PANEL && type < MAX_PANEL_INDEX);
        switch (type) {
            case LANGUAGE_PANEL:
                return new TranslateLanguagePanel(this, mOptions);
            case NEVER_PANEL:
                return new TranslateNeverPanel(this, mOptions);
            case ALWAYS_PANEL:
                return new TranslateAlwaysPanel(this, mOptions);
            default:
                return null;
        }
    }

    /**
     * Swaps out the current view in the ContentViewWrapper.
     */
    private void updateViewForCurrentState(View replacement) {
        setControlsEnabled(false);
        getInfoBarContainer().swapInfoBarViews(this, replacement);
    }

    /**
     * @return a formatted message with links to {@code panelId}.
     */
    private CharSequence formatBeforeInfoBarMessage(String template, String sourceLanguage,
            String targetLanguage, final int panelId) {

        SpannableString formattedSourceLanguage = new SpannableString(sourceLanguage);
        formattedSourceLanguage.setSpan(new ClickableSpan() {
            @Override
            public void onClick(View view) {
                swapPanel(panelId);
            }
        }, 0, sourceLanguage.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);

        SpannableString formattedTargetLanguage = new SpannableString(targetLanguage);
        formattedTargetLanguage.setSpan(new ClickableSpan() {
            @Override
            public void onClick(View view) {
                swapPanel(panelId);
            }
        }, 0, targetLanguage.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);

        return TextUtils.expandTemplate(template, formattedSourceLanguage, formattedTargetLanguage);
    }

    /**
     * @return a formatted message with a link to {@code panelId}
     */
    private CharSequence formatAfterTranslateInfoBarMessage(String statement, String linkText,
            final int panelId) {
        SpannableStringBuilder result = new SpannableStringBuilder();
        result.append(statement).append(" ");
        SpannableString formattedChange = new SpannableString(linkText);
        formattedChange.setSpan(new ClickableSpan() {
            @Override
            public void onClick(View view) {
                swapPanel(panelId);
            }
        }, 0, linkText.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
        result.append(formattedChange);
        return result;
    }

    int getInfoBarType() {
        return mInfoBarType;
    }

    void changeInfoBarTypeAndNativePointer(int infoBarType, long newNativePointer) {
        if (infoBarType >= 0 && infoBarType < MAX_INFOBAR_INDEX) {
            mInfoBarType = infoBarType;
            replaceNativePointer(newNativePointer);
            updateViewForCurrentState(createView());
        } else {
            assert false : "Trying to change the InfoBar to a type that is invalid.";
        }
    }
}
