// Copyright 2010-2014, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
//     * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
//     * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
//     * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

package org.mozc.android.inputmethod.japanese;

import org.mozc.android.inputmethod.japanese.CandidateViewManager.KeyboardCandidateViewHeightListener;
import org.mozc.android.inputmethod.japanese.FeedbackManager.FeedbackEvent;
import org.mozc.android.inputmethod.japanese.LayoutParamsAnimator.InterpolationListener;
import org.mozc.android.inputmethod.japanese.ViewManagerInterface.LayoutAdjustment;
import org.mozc.android.inputmethod.japanese.emoji.EmojiProviderType;
import org.mozc.android.inputmethod.japanese.keyboard.BackgroundDrawableFactory;
import org.mozc.android.inputmethod.japanese.keyboard.KeyEventHandler;
import org.mozc.android.inputmethod.japanese.keyboard.KeyState.MetaState;
import org.mozc.android.inputmethod.japanese.keyboard.Keyboard;
import org.mozc.android.inputmethod.japanese.keyboard.KeyboardView;
import org.mozc.android.inputmethod.japanese.model.SymbolCandidateStorage;
import org.mozc.android.inputmethod.japanese.model.SymbolMajorCategory;
import org.mozc.android.inputmethod.japanese.protobuf.ProtoCommands.Command;
import org.mozc.android.inputmethod.japanese.protobuf.ProtoCommands.CompositionMode;
import org.mozc.android.inputmethod.japanese.protobuf.ProtoCommands.Output;
import org.mozc.android.inputmethod.japanese.ui.SideFrameStubProxy;
import org.mozc.android.inputmethod.japanese.view.MozcImageView;
import org.mozc.android.inputmethod.japanese.view.Skin;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Optional;
import com.google.common.base.Preconditions;

import android.annotation.TargetApi;
import android.content.Context;
import android.content.res.Resources;
import android.graphics.Rect;
import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
import android.inputmethodservice.InputMethodService.Insets;
import android.os.Handler;
import android.os.Looper;
import android.util.AttributeSet;
import android.view.Gravity;
import android.view.View;
import android.view.ViewGroup;
import android.view.animation.AccelerateDecelerateInterpolator;
import android.view.animation.AccelerateInterpolator;
import android.view.animation.AlphaAnimation;
import android.view.animation.Animation;
import android.view.animation.DecelerateInterpolator;
import android.view.animation.Interpolator;
import android.view.animation.TranslateAnimation;
import android.view.inputmethod.CursorAnchorInfo;
import android.view.inputmethod.EditorInfo;
import android.widget.CompoundButton;
import android.widget.FrameLayout;
import android.widget.LinearLayout;

import java.util.Collections;
import java.util.EnumSet;

import javax.annotation.Nullable;

/**
 * Root {@code View} of the MechaMozc.
 * It is expected that instance methods are used after inflation is done.
 *
 */
public class MozcView extends FrameLayout implements MemoryManageable {

  @VisibleForTesting
  static class DimensionPixelSize {
    final int imeWindowPartialWidth;
    final int imeWindowRegionInsetThreshold;
    final int narrowFrameHeight;
    final int narrowImeWindowHeight;
    final int sideFrameWidth;
    final int buttonFrameHeight;
    public DimensionPixelSize(Resources resources) {
      imeWindowPartialWidth = resources.getDimensionPixelSize(R.dimen.ime_window_partial_width);
      imeWindowRegionInsetThreshold = resources.getDimensionPixelSize(
          R.dimen.ime_window_region_inset_threshold);
      narrowFrameHeight = resources.getDimensionPixelSize(R.dimen.narrow_frame_height);
      narrowImeWindowHeight = resources.getDimensionPixelSize(R.dimen.narrow_ime_window_height);
      sideFrameWidth = resources.getDimensionPixelSize(R.dimen.side_frame_width);
      buttonFrameHeight = resources.getDimensionPixelSize(R.dimen.button_frame_height);
    }
  }

  @VisibleForTesting
  static class HeightLinearInterpolationListener implements InterpolationListener {
    final int fromHeight;
    final int toHeight;

    public HeightLinearInterpolationListener(int fromHeight, int toHeight) {
      this.fromHeight = fromHeight;
      this.toHeight = toHeight;
    }

    @Override
    public ViewGroup.LayoutParams calculateAnimatedParams(
        float interpolation, ViewGroup.LayoutParams currentLayoutParams) {
      currentLayoutParams.height = fromHeight + (int) ((toHeight - fromHeight) * interpolation);
      return currentLayoutParams;
    }
  }

  // TODO(hidehiko): Refactor CandidateViewListener along with View structure refactoring.
  class InputFrameFoldButtonClickListener implements OnClickListener {
    private final View keyboardView;
    private final int originalHeight;
    private final long foldDuration;
    private final Interpolator foldKeyboardViewInterpolator;
    private final long expandDuration;
    private final Interpolator expandKeyboardViewInterpolator;
    private final LayoutParamsAnimator layoutParamsAnimator;
    InputFrameFoldButtonClickListener(
        View keyboardView, int originalHeight,
        long foldDuration, Interpolator foldKeyboardViewInterpolator,
        long expandDuration, Interpolator expandKeyboardViewInterpolator,
        LayoutParamsAnimator layoutParamsAnimator) {
      this.keyboardView = keyboardView;
      this.originalHeight = originalHeight;
      this.foldDuration = foldDuration;
      this.foldKeyboardViewInterpolator = foldKeyboardViewInterpolator;
      this.expandDuration = expandDuration;
      this.expandKeyboardViewInterpolator = expandKeyboardViewInterpolator;
      this.layoutParamsAnimator = layoutParamsAnimator;
    }

    @Override
    public void onClick(View v) {
      if (keyboardView.getHeight() == originalHeight) {
        if (viewEventListener != null) {
          viewEventListener.onFireFeedbackEvent(FeedbackEvent.INPUTVIEW_FOLD);
        }
        layoutParamsAnimator.startAnimation(
            keyboardView,
            new HeightLinearInterpolationListener(keyboardView.getHeight(), 0),
            foldKeyboardViewInterpolator, foldDuration, 0);
        CompoundButton.class.cast(v).setChecked(true);
      } else {
        if (viewEventListener != null) {
          viewEventListener.onFireFeedbackEvent(FeedbackEvent.INPUTVIEW_EXPAND);
        }
        layoutParamsAnimator.startAnimation(
            keyboardView,
            new HeightLinearInterpolationListener(keyboardView.getHeight(), originalHeight),
            expandKeyboardViewInterpolator, expandDuration, 0);
        CompoundButton.class.cast(v).setChecked(false);
      }
    }
  }

  /** Manages background view height. */
  @VisibleForTesting
  class SoftwareKeyboardHeightListener implements KeyboardCandidateViewHeightListener {
    @Override
    public void onExpanded() {
      if (!isNarrowMode()) {
        changeBottomBackgroundHeight(imeWindowHeight);
      }
    }

    @Override
    public void onCollapse() {
      if (!isNarrowMode() && getSymbolInputView().getVisibility() != VISIBLE) {
        resetBottomBackgroundHeight();
      }
    }
  }

  @VisibleForTesting
  final InOutAnimatedFrameLayout.VisibilityChangeListener onVisibilityChangeListener =
      new InOutAnimatedFrameLayout.VisibilityChangeListener() {
        @Override
        public void onVisibilityChange() {
          updateInputFrameHeight();
        }
      };

  private final DimensionPixelSize dimensionPixelSize = new DimensionPixelSize(getResources());
  private final SideFrameStubProxy leftFrameStubProxy = new SideFrameStubProxy();
  private final SideFrameStubProxy rightFrameStubProxy = new SideFrameStubProxy();

  @VisibleForTesting ViewEventListener viewEventListener;
  @VisibleForTesting boolean fullscreenMode = false;
  @VisibleForTesting boolean narrowMode = false;
  private boolean buttonFrameVisible = true;
  private Skin skin = Skin.getFallbackInstance();
  @VisibleForTesting LayoutAdjustment layoutAdjustment = LayoutAdjustment.FILL;
  private int inputFrameHeight = 0;
  @VisibleForTesting int imeWindowHeight = 0;
  @VisibleForTesting int symbolInputViewHeight = 0;
  @VisibleForTesting Animation symbolInputViewInAnimation;
  @VisibleForTesting Animation symbolInputViewOutAnimation;
  @VisibleForTesting SoftwareKeyboardHeightListener softwareKeyboardHeightListener =
      new SoftwareKeyboardHeightListener();
  @VisibleForTesting CandidateViewManager candidateViewManager;
  @VisibleForTesting boolean allowFloatingCandidateMode;

  public MozcView(Context context) {
    super(context);
  }

  public MozcView(Context context, AttributeSet attrSet) {
    super(context, attrSet);
  }

  private static Animation createAlphaAnimation(float fromAlpha, float toAlpha, long duration) {
    AlphaAnimation animation = new AlphaAnimation(fromAlpha, toAlpha);
    animation.setDuration(duration);
    return animation;
  }

  @Override
  public void onFinishInflate() {
    setKeyboardHeightRatio(100);

    leftFrameStubProxy.initialize(this,
                                  R.id.stub_left_frame, R.id.left_adjust_button,
                                  R.raw.adjust_arrow_left);
    rightFrameStubProxy.initialize(this,
                                   R.id.stub_right_frame, R.id.right_adjust_button,
                                   R.raw.adjust_arrow_right);

    candidateViewManager = new CandidateViewManager(
        getKeyboardCandidateView(),
        FloatingCandidateView.class.cast(findViewById(R.id.floating_candidate_view)));
  }

  private InputFrameFoldButtonClickListener createFoldButtonListener(View view, int height) {
    Resources resources = getResources();
    int foldOvershootDurationRate =
        resources.getInteger(R.integer.input_frame_fold_overshoot_duration_rate);
    int foldOvershootRate =
        resources.getInteger(R.integer.input_frame_fold_overshoot_rate);
    int expandOvershootDurationRate =
        resources.getInteger(R.integer.input_frame_expand_overshoot_duration_rate);
    int expandOvershootRate =
        resources.getInteger(R.integer.input_frame_expand_overshoot_rate);

    return new InputFrameFoldButtonClickListener(
        view, height, resources.getInteger(R.integer.input_frame_fold_duration),
        SequentialInterpolator.newBuilder()
            .add(new DecelerateInterpolator(),
                foldOvershootDurationRate, -foldOvershootRate / 1e6f)
            .add(new AccelerateInterpolator(), 1e6f - foldOvershootDurationRate, 1)
            .build(),
        resources.getInteger(R.integer.input_frame_expand_duration),
        SequentialInterpolator.newBuilder()
            .add(new DecelerateInterpolator(),
                expandOvershootDurationRate, 1 + expandOvershootRate / 1e6f)
            .add(new AccelerateDecelerateInterpolator(), 1e6f - expandOvershootDurationRate, 1)
            .build(),
        new LayoutParamsAnimator(new Handler(Looper.myLooper())));
  }

  public void setEventListener(final ViewEventListener viewEventListener,
                               OnClickListener widenButtonClickListener,
                               OnClickListener leftAdjustButtonClickListener,
                               OnClickListener rightAdjustButtonClickListener,
                               OnClickListener microphoneButtonClickListener) {
    Preconditions.checkNotNull(viewEventListener);
    Preconditions.checkNotNull(widenButtonClickListener);
    Preconditions.checkNotNull(leftAdjustButtonClickListener);
    Preconditions.checkNotNull(rightAdjustButtonClickListener);
    Preconditions.checkNotNull(microphoneButtonClickListener);

    checkInflated();

    this.viewEventListener = viewEventListener;

    // Propagate the given listener into the child views.
    // Set CandidateViewListener as well here, because it uses viewEventListener.
    candidateViewManager.setEventListener(viewEventListener, softwareKeyboardHeightListener);

    getSymbolInputView().setEventListener(
        viewEventListener,
        /** Click handler of the close button. */
        new OnClickListener() {
          @Override
          public void onClick(View v) {
            if (viewEventListener != null) {
              viewEventListener.onFireFeedbackEvent(FeedbackEvent.SYMBOL_INPUTVIEW_CLOSED);
            }
            hideSymbolInputView();
          }
        },
        microphoneButtonClickListener);

    getNarrowFrame().setEventListener(viewEventListener, widenButtonClickListener);
    leftFrameStubProxy.setButtonOnClickListener(leftAdjustButtonClickListener);
    rightFrameStubProxy.setButtonOnClickListener(rightAdjustButtonClickListener);
    getMicrophoneButton().setOnClickListener(microphoneButtonClickListener);
  }

  public void setKeyEventHandler(KeyEventHandler keyEventHandler) {
    checkInflated();

    // Propagate the given keyEventHandler to the child views.
    getKeyboardView().setKeyEventHandler(keyEventHandler);
    getSymbolInputView().setKeyEventHandler(keyEventHandler);
  }

  // TODO(hidehiko): Probably we'd like to remove this method when we decide to move MVC model.
  @Nullable public Keyboard getKeyboard() {
    checkInflated();
    return getKeyboardView().getKeyboard().orNull();
  }

  public void setKeyboard(Keyboard keyboard) {
    checkInflated();
    getKeyboardView().setKeyboard(keyboard);
    CompositionMode compositionMode = keyboard.getSpecification().getCompositionMode();
    getNarrowFrame().setHardwareCompositionButtonImage(compositionMode);
    candidateViewManager.setHardwareCompositionMode(compositionMode);
  }

  public void setEmojiEnabled(boolean unicodeEmojiEnabled, boolean carrierEmojiEnabled) {
    checkInflated();
    getSymbolInputView().setEmojiEnabled(unicodeEmojiEnabled, carrierEmojiEnabled);
  }

  public void setPasswordField(boolean isPasswordField) {
    checkInflated();
    getSymbolInputView().setPasswordField(isPasswordField);
    getKeyboardView().setPasswordField(isPasswordField);
  }

  public void setEditorInfo(EditorInfo editorInfo) {
    checkInflated();
    getKeyboardView().setEditorInfo(editorInfo);
    candidateViewManager.setEditorInfo(editorInfo);
  }

  public void setFlickSensitivity(int flickSensitivity) {
    checkInflated();
    getKeyboardView().setFlickSensitivity(flickSensitivity);
  }

  public void setEmojiProviderType(EmojiProviderType emojiProviderType) {
    Preconditions.checkNotNull(emojiProviderType);

    checkInflated();
    getSymbolInputView().setEmojiProviderType(emojiProviderType);
  }

  public void setSymbolCandidateStorage(SymbolCandidateStorage symbolCandidateStorage) {
    checkInflated();
    getSymbolInputView().setSymbolCandidateStorage(symbolCandidateStorage);
  }

  public void setPopupEnabled(boolean popupEnabled) {
    checkInflated();
    getKeyboardView().setPopupEnabled(popupEnabled);
    getSymbolInputView().setPopupEnabled(popupEnabled);
  }

  public boolean isPopupEnabled() {
    checkInflated();
    return getKeyboardView().isPopupEnabled();
  }

  @SuppressWarnings("deprecation")
  public void setSkin(Skin skin) {
    Preconditions.checkNotNull(skin);
    checkInflated();
    this.skin = skin;
    getKeyboardView().setSkin(skin);
    getSymbolInputView().setSkin(skin);
    candidateViewManager.setSkin(skin);
    getMicrophoneButton().setBackgroundDrawable(BackgroundDrawableFactory.createPressableDrawable(
        new ColorDrawable(skin.buttonFrameButtonPressedColor), Optional.<Drawable>absent()));
    getMicrophoneButton().setSkin(skin);
    leftFrameStubProxy.setSkin(skin);
    rightFrameStubProxy.setSkin(skin);
    getButtonFrame().setBackgroundDrawable(
        skin.buttonFrameBackgroundDrawable.getConstantState().newDrawable());
    getNarrowFrame().setSkin(skin);
    getKeyboardFrameSeparator().setBackgroundDrawable(
        skin.keyboardFrameSeparatorBackgroundDrawable.getConstantState().newDrawable());
  }

  public Skin getSkin() {
    return skin;
  }

  /**
   * Checks whether the inflation is finished or not. If not, throws an IllegalStateException,
   * or do nothing otherwise.
   * Exposed as a package private method for testing purpose.
   */
  @VisibleForTesting
  void checkInflated() {
    if (getChildCount() == 0) {
      throw new IllegalStateException("It is necessary to inflate mozc_view.xml");
    }
  }

  public void setCommand(Command outCommand) {
    checkInflated();
    candidateViewManager.update(outCommand);
    updateMetaStatesBasedOnOutput(outCommand.getOutput());
  }

  // Update COMPOSING metastate.
  @VisibleForTesting
  void updateMetaStatesBasedOnOutput(Output output) {
    Preconditions.checkNotNull(output);

    boolean hasPreedit = output.hasPreedit()
        && output.getPreedit().getSegmentCount() > 0;
    if (hasPreedit) {
      getKeyboardView().updateMetaStates(EnumSet.of(MetaState.COMPOSING),
                                         Collections.<MetaState>emptySet());
    } else {
      getKeyboardView().updateMetaStates(Collections.<MetaState>emptySet(),
                                         EnumSet.of(MetaState.COMPOSING));
    }
  }

  @TargetApi(21)
  public void setCursorAnchorInfo(CursorAnchorInfo info) {
    candidateViewManager.setCursorAnchorInfo(info);
  }

  public void setCursorAnchorInfoEnabled(boolean enabled) {
    allowFloatingCandidateMode = enabled;
    candidateViewManager.setAllowFloatingMode(enabled);
  }

  public void reset() {
    checkInflated();

    // Reset keyboard frame and view.
    resetKeyboardFrameVisibility();
    resetKeyboardViewState();

    // Reset candidate view.
    candidateViewManager.reset();

    // Reset symbol input view visibility. Set Visibility directly (without animation).
    SymbolInputView symbolInputView = getSymbolInputView();
    symbolInputView.clearAnimation();
    symbolInputView.setVisibility(View.GONE);

    // Reset *all* metastates (and set NO_GLOBE as default value).
    // Expecting metastates will be set next initialization.
    getKeyboardView().updateMetaStates(EnumSet.of(MetaState.NO_GLOBE),
                                       EnumSet.allOf(MetaState.class));

    resetFullscreenMode();
    setLayoutAdjustmentAndNarrowMode(layoutAdjustment, narrowMode);
    resetBottomBackgroundHeight();
    updateBackgroundColor();
  }

  public void resetKeyboardFrameVisibility() {
    checkInflated();

    if (narrowMode) {
      return;
    }

    SymbolInputView symbolInputView = getSymbolInputView();
    View keyboardFrame;
    int keyboardFrameHeight;
    if (symbolInputView.isInflated() && symbolInputView.getVisibility() == View.VISIBLE) {
      keyboardFrame = getNumberKeyboardFrame();
      keyboardFrameHeight = symbolInputView.getNumberKeyboardHeight();
    } else {
      keyboardFrame = getKeyboardFrame();
      keyboardFrameHeight = getInputFrameHeight();
    }

    keyboardFrame.setVisibility(View.VISIBLE);

    // The height may be changed so reset it here.
    ViewGroup.LayoutParams layoutParams = keyboardFrame.getLayoutParams();
    if (layoutParams.height != keyboardFrameHeight) {
      layoutParams.height = keyboardFrameHeight;
      keyboardFrame.setLayoutParams(layoutParams);

      // Also reset the state of the folding button, which is "conceptually" a part of
      // the keyboard.
      candidateViewManager.setInputFrameFoldButtonChecked(false);
    }
  }

  public void resetKeyboardViewState() {
    checkInflated();
    getKeyboardView().resetState();
  }

  public boolean showSymbolInputView(Optional<SymbolMajorCategory> category) {
    Preconditions.checkNotNull(category);
    checkInflated();

    SymbolInputView view = getSymbolInputView();
    if (view.getVisibility() == View.VISIBLE) {
      return false;
    }

    if (!view.isInflated()) {
      view.inflateSelf();
      CandidateView numberCandidateView =
          CandidateView.class.cast(view.findViewById(R.id.candidate_view_in_symbol_view));
      numberCandidateView.setInputFrameFoldButtonOnClickListener(createFoldButtonListener(
          getNumberKeyboardFrame(), view.getNumberKeyboardHeight()));
      candidateViewManager.setNumberCandidateView(numberCandidateView);
    }

    view.resetToMajorCategory(category);
    startSymbolInputViewInAnimation();
    candidateViewManager.setNumberMode(true);

    return true;
  }

  public boolean hideSymbolInputView() {
    checkInflated();

    SymbolInputView view = getSymbolInputView();
    if (view.getVisibility() != View.VISIBLE) {
      return false;
    }

    candidateViewManager.setNumberMode(false);
    startSymbolInputViewOutAnimation();
    return true;
  }

  private int getButtonFrameHeightIfVisible() {
    return buttonFrameVisible ? dimensionPixelSize.buttonFrameHeight : 0;
  }

  /**
   * Decides input frame height in not fullscreen mode.
   */
  @VisibleForTesting
  int getVisibleViewHeight() {
    checkInflated();

    boolean isSymbolInputViewVisible = getSymbolInputView().getVisibility() == View.VISIBLE;
    // Means only software keyboard or narrow frame
    boolean isDefaultView =
        !candidateViewManager.isKeyboardCandidateViewVisible() && !isSymbolInputViewVisible;

    if (narrowMode) {
      if (isDefaultView) {
        return dimensionPixelSize.narrowFrameHeight;
      } else {
        return dimensionPixelSize.narrowImeWindowHeight;
      }
    } else {
      if (isDefaultView) {
        return getInputFrameHeight() + getButtonFrameHeightIfVisible();
      } else {
        if (isSymbolInputViewVisible) {
          return symbolInputViewHeight;
        } else {
          return imeWindowHeight;
        }
      }
    }
  }

  @VisibleForTesting
  void updateInputFrameHeight() {
    // input_frame's height depends on fullscreen mode, narrow mode and Candidate/Symbol views.
    if (fullscreenMode) {
      setLayoutHeight(getBottomFrame(), getVisibleViewHeight());
      setLayoutHeight(getKeyboardFrame(), getInputFrameHeight());
    } else {
      if (narrowMode) {
        setLayoutHeight(getBottomFrame(), dimensionPixelSize.narrowImeWindowHeight);
      } else {
        setLayoutHeight(getBottomFrame(), imeWindowHeight);
        setLayoutHeight(getKeyboardFrame(), getInputFrameHeight());
      }
    }
  }

  @VisibleForTesting
  int getSideAdjustedWidth() {
    return dimensionPixelSize.imeWindowPartialWidth + dimensionPixelSize.sideFrameWidth;
  }

  public void setFullscreenMode(boolean fullscreenMode) {
    this.fullscreenMode = fullscreenMode;
  }

  public boolean isFullscreenMode() {
    return fullscreenMode;
  }

  @VisibleForTesting
  void resetFullscreenMode() {
    if (fullscreenMode) {
      // In fullscreen mode, InputMethodService shows extract view which height is 0 and
      // weight is 0. So our MozcView height should be fixed.
      // If CandidateView or SymbolInputView appears, MozcView height is enlarged to fix them.
      getOverlayView().setVisibility(View.GONE);
      setLayoutHeight(getTextInputFrame(), LayoutParams.WRAP_CONTENT);
      candidateViewManager.setOnVisibilityChangeListener(Optional.of(onVisibilityChangeListener));
      getSymbolInputView().setOnVisibilityChangeListener(onVisibilityChangeListener);
    } else {
      getOverlayView().setVisibility(View.VISIBLE);
      setLayoutHeight(getTextInputFrame(), LayoutParams.MATCH_PARENT);
      candidateViewManager.setOnVisibilityChangeListener(
          Optional.<InOutAnimatedFrameLayout.VisibilityChangeListener>absent());
      getSymbolInputView().setOnVisibilityChangeListener(null);
    }
    candidateViewManager.setExtractedMode(fullscreenMode);
    updateInputFrameHeight();
    updateBackgroundColor();
  }

  private static void setLayoutHeight(View view, int height) {
    ViewGroup.LayoutParams layoutParams = view.getLayoutParams();
    layoutParams.height = height;
    view.setLayoutParams(layoutParams);
  }

  public boolean isNarrowMode() {
    return narrowMode;
  }

  public boolean isFloatingCandidateMode() {
    return candidateViewManager.isFloatingMode();
  }

  public Rect getKeyboardSize() {
    Resources resources = getResources();
    // TODO(yoichio): replace resources.getDisplayMetrics().widthPixels with targetWindow.width.
    return new Rect(0, 0,
                    layoutAdjustment == LayoutAdjustment.FILL
                        ? resources.getDisplayMetrics().widthPixels
                        : dimensionPixelSize.imeWindowPartialWidth,
                    getInputFrameHeight());
  }

  /**
   * Sets {@code LayoutAdjustment} and {@code narrowMode}.
   *
   * <p>They are highly dependent on one another so this method sets both at the same time.
   * This decision makes caller-side simpler.
   */
  public void setLayoutAdjustmentAndNarrowMode(LayoutAdjustment layoutAdjustment,
                                               boolean narrowMode) {
    checkInflated();

    this.layoutAdjustment = layoutAdjustment;
    this.narrowMode = narrowMode;

    // If on narrowMode, the view is always shown with full-width regard less of given
    // layoutAdjustment.
    LayoutAdjustment temporaryAdjustment = narrowMode ? LayoutAdjustment.FILL : layoutAdjustment;

    View view = getForegroundFrame();
    FrameLayout.LayoutParams layoutParams =
        FrameLayout.LayoutParams.class.cast(view.getLayoutParams());
    Resources resources = getResources();
    layoutParams.width = temporaryAdjustment == LayoutAdjustment.FILL
        ? resources.getDisplayMetrics().widthPixels : getSideAdjustedWidth();
    layoutParams.gravity = Gravity.BOTTOM;
    if (temporaryAdjustment == LayoutAdjustment.LEFT) {
      layoutParams.gravity |= Gravity.LEFT;
    } else if (temporaryAdjustment == LayoutAdjustment.RIGHT) {
      layoutParams.gravity |= Gravity.RIGHT;
    }
    view.setLayoutParams(layoutParams);

    leftFrameStubProxy.setFrameVisibility(
        temporaryAdjustment == LayoutAdjustment.RIGHT ? VISIBLE : GONE);
    rightFrameStubProxy.setFrameVisibility(
        temporaryAdjustment == LayoutAdjustment.LEFT ? VISIBLE : GONE);

    // Set candidate and desciption text size.
    float candidateTextSize = layoutAdjustment == LayoutAdjustment.FILL
        ? resources.getDimension(R.dimen.candidate_text_size)
        : resources.getDimension(R.dimen.candidate_text_size_aligned_layout);
    float descriptionTextSize = layoutAdjustment == LayoutAdjustment.FILL
        ? resources.getDimension(R.dimen.candidate_description_text_size)
        : resources.getDimension(R.dimen.candidate_description_text_size_aligned_layout);
    candidateViewManager.setCandidateTextDimension(candidateTextSize, descriptionTextSize);
    getSymbolInputView().setCandidateTextDimension(candidateTextSize, descriptionTextSize);

    // In narrow mode, hide software keyboard and show narrow status bar.
    candidateViewManager.setNarrowMode(narrowMode);
    if (narrowMode) {
      getKeyboardFrame().setVisibility(GONE);
      getButtonFrame().setVisibility(GONE);
      getNarrowFrame().setVisibility(VISIBLE);
    } else {
      getKeyboardFrame().setVisibility(VISIBLE);
      getButtonFrame().setVisibility(buttonFrameVisible ? VISIBLE : GONE);
      getNarrowFrame().setVisibility(GONE);
      resetKeyboardFrameVisibility();
    }

    updateInputFrameHeight();
    updateBackgroundColor();
  }

  public void startLayoutAdjustmentAnimation() {
    Resources resources = getResources();
    int delta = resources.getDisplayMetrics().widthPixels
        - dimensionPixelSize.imeWindowPartialWidth;
    TranslateAnimation translateAnimation = new TranslateAnimation(
        layoutAdjustment == LayoutAdjustment.LEFT ? delta : -delta, 0, 0, 0);
    translateAnimation.setDuration(resources.getInteger(
        R.integer.layout_adjustment_transition_duration));
    translateAnimation.setInterpolator(new DecelerateInterpolator());
    getForegroundFrame().startAnimation(translateAnimation);
  }

  @VisibleForTesting
  void updateBackgroundColor() {
    // If fullscreenMode, background should not show original window.
    // If narrowMode, it is always full-width.
    // If isFloatingMode, background should be transparent.
    int resourceId = (fullscreenMode || (!narrowMode && !isFloatingMode()))
        ? R.color.input_frame_background : 0;
    getBottomBackground().setBackgroundResource(resourceId);
  }

  @VisibleForTesting
  boolean isFloatingMode() {
    return layoutAdjustment != LayoutAdjustment.FILL
        && !narrowMode
        && getResources().getDisplayMetrics().widthPixels
            >= dimensionPixelSize.imeWindowRegionInsetThreshold;
  }

  /**
   * This function is called to compute insets.
   */
  public void setInsets(int contentViewWidth, int contentViewHeight, Insets outInsets) {
    if (!isFloatingMode()) {
      outInsets.touchableInsets = Insets.TOUCHABLE_INSETS_CONTENT;
      outInsets.contentTopInsets = contentViewHeight - getVisibleViewHeight();
      outInsets.visibleTopInsets = outInsets.contentTopInsets;
      return;
    }
    int height = getVisibleViewHeight();
    int width = getSideAdjustedWidth();
    int left = layoutAdjustment == LayoutAdjustment.RIGHT ? (contentViewWidth - width) : 0;

    outInsets.touchableInsets = Insets.TOUCHABLE_INSETS_REGION;
    outInsets.touchableRegion.set(
        left, contentViewHeight - height, left + width, contentViewHeight);
    outInsets.contentTopInsets = contentViewHeight;
    outInsets.visibleTopInsets = contentViewHeight;
    return;
  }

  @VisibleForTesting
  void changeBottomBackgroundHeight(int targetHeight) {
    if (getBottomBackground().getHeight() != targetHeight) {
      setLayoutHeight(getBottomBackground(), targetHeight);
    }
  }

  @VisibleForTesting
  void resetBottomBackgroundHeight() {
    setLayoutHeight(getBottomBackground(), getInputFrameHeight() + getButtonFrameHeightIfVisible());
  }

  @VisibleForTesting
  void startSymbolInputViewInAnimation() {
    getSymbolInputView().startInAnimation();
    changeBottomBackgroundHeight(symbolInputViewHeight);
  }

  @VisibleForTesting
  void startSymbolInputViewOutAnimation() {
    getSymbolInputView().startOutAnimation();
    if (!candidateViewManager.isKeyboardCandidateViewVisible()) {
      resetBottomBackgroundHeight();
    }
  }

  /**
   * Reset components depending inputFrameHeight or imeWindowHeight.
   * This should be called when inputFrameHeight and/or imeWindowHeight are updated.
   */
  @VisibleForTesting
  void resetHeightDependingComponents() {
    getKeyboardCandidateView().setInputFrameFoldButtonOnClickListener(
        createFoldButtonListener(getKeyboardFrame(), getInputFrameHeight()));

    if (candidateViewManager != null) {
      candidateViewManager.resetHeightDependingComponents(
          getResources(), imeWindowHeight, inputFrameHeight);
    }

    SymbolInputView symbolInputView = getSymbolInputView();
    {
      long duration = getResources().getInteger(R.integer.symbol_input_transition_duration);
      float fromAlpha = 0.3f;
      float toAlpha = 1.0f;

      symbolInputViewInAnimation = createAlphaAnimation(fromAlpha, toAlpha, duration);
      symbolInputView.setInAnimation(symbolInputViewInAnimation);
      symbolInputViewOutAnimation = createAlphaAnimation(toAlpha, fromAlpha, duration);
      symbolInputView.setOutAnimation(symbolInputViewOutAnimation);
    }

    if (symbolInputView.isInflated()) {
      CandidateView numberCandidateView = CandidateView.class.cast(
          symbolInputView.findViewById(R.id.candidate_view_in_symbol_view));
      numberCandidateView.setInputFrameFoldButtonOnClickListener(createFoldButtonListener(
          getNumberKeyboardFrame(), symbolInputView.getNumberKeyboardHeight()));
    }

    // Reset side adjust buttons height.
    leftFrameStubProxy.resetAdjustButtonBottomMargin(getInputFrameHeight());
    rightFrameStubProxy.resetAdjustButtonBottomMargin(getInputFrameHeight());
  }

  /**
   * Sets keyboard height rated to original height.
   * @param keyboardHeightRatio target ratio percentage. Default is 100.
   */
  public void setKeyboardHeightRatio(int keyboardHeightRatio) {
    checkInflated();

    Resources resources = getResources();
    float heightScale = keyboardHeightRatio * 0.01f;
    float originalImeWindowHeight = resources.getDimension(R.dimen.ime_window_height);
    float originalInputFrameHeight = resources.getDimension(R.dimen.input_frame_height);
    inputFrameHeight = Math.round(originalInputFrameHeight * heightScale);
    int minImeWindowHeight = inputFrameHeight + dimensionPixelSize.buttonFrameHeight;
    imeWindowHeight =
        Math.max(Math.round(originalImeWindowHeight * heightScale), minImeWindowHeight);
    symbolInputViewHeight = Math.min(imeWindowHeight, minImeWindowHeight);

    updateInputFrameHeight();
    getSymbolInputView().setVerticalDimension(symbolInputViewHeight, heightScale);
    resetHeightDependingComponents();
  }

  @VisibleForTesting
  int getInputFrameHeight() {
    return inputFrameHeight;
  }

  @VisibleForTesting
  View getKeyboardFrame() {
    return findViewById(R.id.keyboard_frame);
  }

  View getKeyboardFrameSeparator() {
    return findViewById(R.id.keyboard_frame_separator);
  }

  private View getNumberKeyboardFrame() {
    return findViewById(R.id.number_keyboard_frame);
  }

  @VisibleForTesting
  KeyboardView getKeyboardView() {
    return KeyboardView.class.cast(findViewById(R.id.keyboard_view));
  }

  private CandidateView getKeyboardCandidateView() {
    return CandidateView.class.cast(findViewById(R.id.candidate_view));
  }

  @VisibleForTesting
  SymbolInputView getSymbolInputView() {
    return SymbolInputView.class.cast(findViewById(R.id.symbol_input_view));
  }

  @VisibleForTesting
  View getOverlayView() {
    return findViewById(R.id.overlay_view);
  }

  @VisibleForTesting
  LinearLayout getTextInputFrame() {
    return LinearLayout.class.cast(findViewById(R.id.textinput_frame));
  }

  @VisibleForTesting
  NarrowFrameView getNarrowFrame() {
    return NarrowFrameView.class.cast(findViewById(R.id.narrow_frame));
  }

  @VisibleForTesting
  View getForegroundFrame() {
    return findViewById(R.id.foreground_frame);
  }

  @VisibleForTesting
  View getBottomFrame() {
    return findViewById(R.id.bottom_frame);
  }

  @VisibleForTesting
  View getBottomBackground() {
    return findViewById(R.id.bottom_background);
  }

  @VisibleForTesting
  View getButtonFrame() {
    return findViewById(R.id.button_frame);
  }

  @VisibleForTesting
  MozcImageView getMicrophoneButton() {
    return MozcImageView.class.cast(findViewById(R.id.microphone_button));
  }

  @Override
  public void trimMemory() {
    getKeyboardView().trimMemory();
    getSymbolInputView().trimMemory();
    candidateViewManager.trimMemory();
  }

  void setGlobeButtonEnabled(boolean globeButtonEnabled) {
    getKeyboardView().setGlobeButtonEnabled(globeButtonEnabled);
  }

  void setMicrophoneButtonEnabled(boolean microphoneButtonEnabled) {
    if (narrowMode) {
      buttonFrameVisible = false;
    } else {
      buttonFrameVisible = microphoneButtonEnabled;
      int visibility = buttonFrameVisible ? View.VISIBLE : View.GONE;
      getButtonFrame().setVisibility(visibility);
      getMicrophoneButton().setVisibility(visibility);
      getSymbolInputView().setMicrophoneButtonEnabled(microphoneButtonEnabled);
      resetBottomBackgroundHeight();
    }
  }
}
