// Copyright 2018 The Feed Authors.
//
// 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.google.android.libraries.feed.piet;

import static com.google.android.libraries.feed.common.testing.RunnableSubject.assertThatRunnable;
import static com.google.android.libraries.feed.piet.StyleProvider.DIMENSION_NOT_SET;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import static org.mockito.MockitoAnnotations.initMocks;

import android.app.Activity;
import android.content.Context;
import android.view.Gravity;
import android.view.ViewGroup.MarginLayoutParams;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.LinearLayout.LayoutParams;
import com.google.android.libraries.feed.api.host.config.DebugBehavior;
import com.google.android.libraries.feed.common.functional.Suppliers;
import com.google.android.libraries.feed.common.time.testing.FakeClock;
import com.google.android.libraries.feed.common.ui.LayoutUtils;
import com.google.android.libraries.feed.piet.DebugLogger.MessageType;
import com.google.android.libraries.feed.piet.GridRowAdapter.KeySupplier;
import com.google.android.libraries.feed.piet.host.ActionHandler;
import com.google.android.libraries.feed.piet.host.AssetProvider;
import com.google.android.libraries.feed.piet.host.EventLogger;
import com.google.android.libraries.feed.piet.ui.GridRowView;
import com.google.search.now.ui.piet.BindingRefsProto.ElementBindingRef;
import com.google.search.now.ui.piet.BindingRefsProto.GridCellWidthBindingRef;
import com.google.search.now.ui.piet.BindingRefsProto.StyleBindingRef;
import com.google.search.now.ui.piet.ElementsProto.BindingValue;
import com.google.search.now.ui.piet.ElementsProto.Content;
import com.google.search.now.ui.piet.ElementsProto.CustomElement;
import com.google.search.now.ui.piet.ElementsProto.Element;
import com.google.search.now.ui.piet.ElementsProto.ElementList;
import com.google.search.now.ui.piet.ElementsProto.ElementStack;
import com.google.search.now.ui.piet.ElementsProto.GridCell;
import com.google.search.now.ui.piet.ElementsProto.GridCellWidth;
import com.google.search.now.ui.piet.ElementsProto.GridCellWidth.ContentWidth;
import com.google.search.now.ui.piet.ElementsProto.GridRow;
import com.google.search.now.ui.piet.ElementsProto.ImageElement;
import com.google.search.now.ui.piet.ElementsProto.TextElement;
import com.google.search.now.ui.piet.ElementsProto.Visibility;
import com.google.search.now.ui.piet.ErrorsProto.ErrorCode;
import com.google.search.now.ui.piet.ImagesProto.Image;
import com.google.search.now.ui.piet.PietProto.Frame;
import com.google.search.now.ui.piet.RoundedCornersProto.RoundedCorners;
import com.google.search.now.ui.piet.StylesProto.EdgeWidths;
import com.google.search.now.ui.piet.StylesProto.GravityVertical;
import com.google.search.now.ui.piet.StylesProto.StyleIdsStack;
import com.google.search.now.ui.piet.TextProto.ParameterizedText;
import java.util.Collections;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.robolectric.Robolectric;
import org.robolectric.RobolectricTestRunner;

/** Tests of the {@link GridRowAdapter}. */
@RunWith(RobolectricTestRunner.class)
public class GridRowAdapterTest {

  private static final String GRID_STYLE_ID = "cybercat";
  private static final StyleIdsStack GRID_STYLES =
      StyleIdsStack.newBuilder().addStyleIds(GRID_STYLE_ID).build();
  private static final Element DEFAULT_ELEMENT =
      Element.newBuilder().setElementStack(ElementStack.getDefaultInstance()).build();
  private static final Content DEFAULT_CONTENT =
      Content.newBuilder().setElement(DEFAULT_ELEMENT).build();
  private static final Content TEXT_CONTENT =
      Content.newBuilder()
          .setElement(
              Element.newBuilder()
                  .setTextElement(
                      TextElement.newBuilder()
                          .setParameterizedText(ParameterizedText.newBuilder().setText("TheGrid"))))
          .build();
  private static final String BINDING_ID = "stripes";
  private static final ElementBindingRef ELEMENT_BINDING =
      ElementBindingRef.newBuilder().setBindingId(BINDING_ID).build();
  private static final Content BOUND_CONTENTS =
      Content.newBuilder().setBoundElement(ELEMENT_BINDING).build();
  private static final Element GRID_ROW_WITH_BOUND_CELL =
      Element.newBuilder()
          .setGridRow(
              GridRow.newBuilder().addCells(GridCell.newBuilder().setContent(BOUND_CONTENTS)))
          .build();

  private Context context;
  private AdapterParameters adapterParameters;

  @Mock private ActionHandler actionHandler;
  @Mock private FrameContext frameContext;
  @Mock private StyleProvider styleProvider;
  @Mock private HostProviders hostProviders;
  @Mock private AssetProvider assetProvider;

  private GridRowAdapter adapter;

  @Before
  public void setUp() throws Exception {
    initMocks(this);
    context = Robolectric.buildActivity(Activity.class).get();

    when(hostProviders.getAssetProvider()).thenReturn(assetProvider);
    when(assetProvider.isRtL()).thenReturn(false);
    when(assetProvider.isRtLSupplier()).thenReturn(Suppliers.of(false));
    when(frameContext.makeStyleFor(GRID_STYLES)).thenReturn(styleProvider);
    when(frameContext.getActionHandler()).thenReturn(actionHandler);
    when(frameContext.filterImageSourcesByMediaQueryCondition(any(Image.class)))
        .thenAnswer(invocation -> invocation.getArguments()[0]);
    when(frameContext.reportMessage(anyInt(), any(), anyString()))
        .thenAnswer(invocation -> invocation.getArguments()[2]);
    when(styleProvider.getPadding()).thenReturn(EdgeWidths.getDefaultInstance());
    when(styleProvider.getRoundedCorners()).thenReturn(RoundedCorners.getDefaultInstance());

    adapterParameters =
        new AdapterParameters(
            context, Suppliers.of(null), hostProviders, new FakeClock(), false, false);

    when(frameContext.makeStyleFor(StyleIdsStack.getDefaultInstance()))
        .thenReturn(adapterParameters.defaultStyleProvider);

    adapter = new KeySupplier().getAdapter(context, adapterParameters);
  }

  @Test
  public void testViewDoesNotClip() {
    assertThat(adapter.getBaseView().getClipToPadding()).isFalse();
  }

  @Test
  public void testOnCreateAdapter_makesRow() {
    // We create an adapter for the inline content, but not for the bound content.
    GridRow model =
        GridRow.newBuilder()
            .addCells(GridCell.newBuilder().setContent(DEFAULT_CONTENT))
            .addCells(GridCell.newBuilder().setContent(BOUND_CONTENTS))
            .build();

    when(frameContext.getElementBindingValue(ELEMENT_BINDING))
        .thenReturn(BindingValue.newBuilder().setElement(DEFAULT_ELEMENT).build());

    adapter.createAdapter(asElement(model), frameContext);

    assertThat(adapter.getBaseView().getChildCount()).isEqualTo(1);
    assertThat(adapter.getBaseView().getBaseline()).isEqualTo(-1);
    assertThat(adapter.childAdapters).hasSize(1);
    assertThat(adapter.getBaseView().getChildAt(0))
        .isSameInstanceAs(adapter.childAdapters.get(0).getView());
  }

  @Test
  public void testOnCreateAdapter_missingContentIsException() {
    GridRow model = GridRow.newBuilder().addCells(GridCell.getDefaultInstance()).build();

    assertThatRunnable(() -> adapter.createAdapter(asElement(model), frameContext))
        .throwsAnExceptionOfType(PietFatalException.class)
        .that()
        .hasMessageThat()
        .contains("Unhandled Content type: CONTENTTYPE_NOT_SET");
  }

  @Test
  public void testOnCreateAdapter_setsGridRowStyles() {
    GridRow model =
        GridRow.newBuilder()
            .addCells(GridCell.newBuilder().setContent(DEFAULT_CONTENT))
            .setStyleReferences(GRID_STYLES)
            .build();

    adapter.createAdapter(asElement(model), frameContext);

    verify(frameContext).makeStyleFor(GRID_STYLES);
    verify(styleProvider).applyElementStyles(adapter);
  }

  @Test
  public void testOnBindModel_setsLayoutParamsOnCell_widthDefaultsToWeight() {
    GridRow model =
        GridRow.newBuilder()
            .addCells(GridCell.newBuilder().setContent(DEFAULT_CONTENT).clearWidth())
            .build();

    adapter.createAdapter(asElement(model), frameContext);
    adapter.bindModel(asElement(model), frameContext);

    assertThat(adapter.getBaseView().getChildAt(0).getLayoutParams())
        .isInstanceOf(LinearLayout.LayoutParams.class);
    LayoutParams params =
        (LinearLayout.LayoutParams) adapter.getBaseView().getChildAt(0).getLayoutParams();
    assertThat(params.width).isEqualTo(0);
    assertThat(params.weight).isEqualTo(1.0f);
  }

  @Test
  public void testOnBindModel_setsLayoutParamsOnCell_widthDp() {
    int widthDp = 123;
    GridRow model =
        GridRow.newBuilder()
            .addCells(
                GridCell.newBuilder()
                    .setContent(DEFAULT_CONTENT)
                    .setWidth(GridCellWidth.newBuilder().setDp(widthDp)))
            .build();

    adapter.createAdapter(asElement(model), frameContext);
    adapter.bindModel(asElement(model), frameContext);

    assertThat(adapter.getBaseView().getChildAt(0).getLayoutParams())
        .isInstanceOf(LinearLayout.LayoutParams.class);
    LayoutParams params =
        (LinearLayout.LayoutParams) adapter.getBaseView().getChildAt(0).getLayoutParams();
    assertThat(params.width).isEqualTo((int) LayoutUtils.dpToPx(widthDp, context));
    assertThat(params.weight).isEqualTo(0.0f);
  }

  @Test
  public void testOnBindModel_setsLayoutParamsOnCell_widthWeight() {
    int widthWeight = 321;
    GridRow model =
        GridRow.newBuilder()
            .addCells(
                GridCell.newBuilder()
                    .setContent(DEFAULT_CONTENT)
                    .setWidth(GridCellWidth.newBuilder().setWeight(widthWeight)))
            .build();

    adapter.createAdapter(asElement(model), frameContext);
    adapter.bindModel(asElement(model), frameContext);

    assertThat(adapter.getBaseView().getChildAt(0).getLayoutParams())
        .isInstanceOf(LinearLayout.LayoutParams.class);
    LayoutParams params =
        (LinearLayout.LayoutParams) adapter.getBaseView().getChildAt(0).getLayoutParams();
    assertThat(params.weight).isEqualTo((float) widthWeight);
    assertThat(params.width).isEqualTo(0);
  }

  @Test
  public void testOnBindModel_setsLayoutParamsOnCell_widthBinding() {
    GridCellWidthBindingRef widthBindingRef =
        GridCellWidthBindingRef.newBuilder().setBindingId("fatcat").build();
    int widthDp = 222;
    GridRow model =
        GridRow.newBuilder()
            .addCells(
                GridCell.newBuilder().setContent(DEFAULT_CONTENT).setWidthBinding(widthBindingRef))
            .build();
    when(frameContext.getGridCellWidthFromBinding(widthBindingRef))
        .thenReturn(GridCellWidth.newBuilder().setDp(widthDp).build());

    adapter.createAdapter(asElement(model), frameContext);
    adapter.bindModel(asElement(model), frameContext);

    assertThat(adapter.getBaseView().getChildAt(0).getLayoutParams())
        .isInstanceOf(LinearLayout.LayoutParams.class);
    LayoutParams params =
        (LinearLayout.LayoutParams) adapter.getBaseView().getChildAt(0).getLayoutParams();
    assertThat(params.width).isEqualTo((int) LayoutUtils.dpToPx(widthDp, context));
    assertThat(params.weight).isEqualTo(0.0f);
  }

  @Test
  public void testOnBindModel_setsLayoutParamsOnCell_invalidContentWidth() {
    GridRow model =
        GridRow.newBuilder()
            .addCells(
                GridCell.newBuilder()
                    .setContent(DEFAULT_CONTENT)
                    .setWidth(
                        GridCellWidth.newBuilder()
                            .setContentWidth(ContentWidth.INVALID_CONTENT_WIDTH)))
            .build();

    adapter.createAdapter(asElement(model), frameContext);
    adapter.bindModel(asElement(model), frameContext);

    LayoutParams params =
        (LinearLayout.LayoutParams) adapter.getBaseView().getChildAt(0).getLayoutParams();
    assertThat(params.width).isEqualTo(LayoutParams.WRAP_CONTENT);
    assertThat(params.weight).isEqualTo(0.0f);
    verify(frameContext)
        .reportMessage(
            MessageType.WARNING,
            ErrorCode.ERR_GRID_CELL_WIDTH_WITHOUT_CONTENTS,
            "Invalid content width: INVALID_CONTENT_WIDTH");
  }

  @Test
  public void testOnBindModel_setsLayoutParamsOnCell_widthOfChildAdapter() {
    StyleIdsStack childStyles = StyleIdsStack.newBuilder().addStyleIds("child").build();
    GridRow model =
        GridRow.newBuilder()
            .addCells(
                GridCell.newBuilder()
                    .setWidth(
                        GridCellWidth.newBuilder().setContentWidth(ContentWidth.CONTENT_WIDTH))
                    .setContent(
                        Content.newBuilder()
                            .setElement(
                                Element.newBuilder()
                                    .setImageElement(
                                        ImageElement.newBuilder()
                                            .setStyleReferences(childStyles)
                                            .setImage(Image.getDefaultInstance())))))
            .build();

    StyleProvider childStyleProvider = mock(StyleProvider.class);
    when(childStyleProvider.hasWidth()).thenReturn(true);
    when(childStyleProvider.getWidthSpecPx(context)).thenReturn(456);
    when(childStyleProvider.getRoundedCorners()).thenReturn(RoundedCorners.getDefaultInstance());
    when(childStyleProvider.getScaleType()).thenReturn(ImageView.ScaleType.CENTER_CROP);

    when(frameContext.makeStyleFor(childStyles)).thenReturn(childStyleProvider);

    adapter.createAdapter(asElement(model), frameContext);
    adapter.bindModel(asElement(model), frameContext);

    assertThat(adapter.getBaseView().getChildAt(0).getLayoutParams())
        .isInstanceOf(LinearLayout.LayoutParams.class);
    LayoutParams params =
        (LinearLayout.LayoutParams) adapter.getBaseView().getChildAt(0).getLayoutParams();
    assertThat(params.width).isEqualTo((int) LayoutUtils.dpToPx(456, context));
    assertThat(params.weight).isEqualTo(0.0f);
  }

  @Test
  public void testOnBindModel_setsLayoutParamsOnCell_heightOfChildAdapter() {
    StyleIdsStack childStyles = StyleIdsStack.newBuilder().addStyleIds("child").build();
    GridRow model =
        GridRow.newBuilder()
            .addCells(
                GridCell.newBuilder()
                    .setContent(
                        Content.newBuilder()
                            .setElement(
                                Element.newBuilder()
                                    .setImageElement(
                                        ImageElement.newBuilder()
                                            .setStyleReferences(childStyles)
                                            .setImage(Image.getDefaultInstance())))))
            .build();

    StyleProvider childStyleProvider = mock(StyleProvider.class);
    when(childStyleProvider.hasHeight()).thenReturn(true);
    when(childStyleProvider.getHeightSpecPx(context)).thenReturn(123);
    when(childStyleProvider.getRoundedCorners()).thenReturn(RoundedCorners.getDefaultInstance());
    when(childStyleProvider.getScaleType()).thenReturn(ImageView.ScaleType.CENTER_CROP);

    when(frameContext.makeStyleFor(childStyles)).thenReturn(childStyleProvider);

    adapter.createAdapter(asElement(model), frameContext);
    adapter.bindModel(asElement(model), frameContext);

    assertThat(adapter.getBaseView().getChildAt(0).getLayoutParams())
        .isInstanceOf(LinearLayout.LayoutParams.class);
    LayoutParams params =
        (LinearLayout.LayoutParams) adapter.getBaseView().getChildAt(0).getLayoutParams();
    assertThat(params.height).isEqualTo((int) LayoutUtils.dpToPx(123, context));
  }

  @Test
  public void testOnBindModel_setsLayoutParamsOnCell_heightOfChildAdapterNotDefined() {
    StyleIdsStack childStyles = StyleIdsStack.newBuilder().addStyleIds("child").build();
    GridRow model =
        GridRow.newBuilder()
            .addCells(
                GridCell.newBuilder()
                    .setContent(
                        Content.newBuilder()
                            .setElement(
                                Element.newBuilder()
                                    .setImageElement(
                                        ImageElement.newBuilder()
                                            .setImage(Image.getDefaultInstance())))))
            .build();

    StyleProvider childStyleProvider = mock(StyleProvider.class);
    when(childStyleProvider.hasHeight()).thenReturn(false);
    when(childStyleProvider.getHeightSpecPx(context)).thenReturn(DIMENSION_NOT_SET);
    when(childStyleProvider.getRoundedCorners()).thenReturn(RoundedCorners.getDefaultInstance());

    when(frameContext.makeStyleFor(childStyles)).thenReturn(childStyleProvider);

    adapter.createAdapter(asElement(model), frameContext);
    adapter.bindModel(asElement(model), frameContext);

    assertThat(adapter.getBaseView().getChildAt(0).getLayoutParams())
        .isInstanceOf(LinearLayout.LayoutParams.class);
    LayoutParams params =
        (LinearLayout.LayoutParams) adapter.getBaseView().getChildAt(0).getLayoutParams();
    assertThat(params.height).isEqualTo(LayoutParams.MATCH_PARENT);
  }

  @Test
  public void testOnBindModel_setsLayoutParamsOnCell_margins() {
    StyleIdsStack childStyles = StyleIdsStack.newBuilder().addStyleIds("child").build();
    GridRow model =
        GridRow.newBuilder()
            .addCells(
                GridCell.newBuilder()
                    .setContent(
                        Content.newBuilder()
                            .setElement(
                                Element.newBuilder()
                                    .setStyleReferences(childStyles)
                                    .setElementStack(ElementStack.getDefaultInstance()))))
            .build();

    StyleProvider childStyleProvider = mock(StyleProvider.class);
    when(childStyleProvider.getPadding()).thenReturn(EdgeWidths.getDefaultInstance());
    when(childStyleProvider.getRoundedCorners()).thenReturn(RoundedCorners.getDefaultInstance());

    when(frameContext.makeStyleFor(childStyles)).thenReturn(childStyleProvider);

    adapter.createAdapter(asElement(model), frameContext);
    adapter.bindModel(asElement(model), frameContext);

    verify(childStyleProvider)
        .applyMargins(
            context, (MarginLayoutParams) adapter.getBaseView().getChildAt(0).getLayoutParams());
  }

  @Test
  public void testOnBindModel_setsLayoutParamsOnCell_verticalGravityCenter() {
    GridRow gridRowTop =
        GridRow.newBuilder()
            .addCells(
                GridCell.newBuilder()
                    .setContent(
                        Content.newBuilder()
                            .setElement(
                                DEFAULT_ELEMENT
                                    .toBuilder()
                                    .setGravityVertical(GravityVertical.GRAVITY_MIDDLE))))
            .build();

    adapter.createAdapter(asElement(gridRowTop), frameContext);
    adapter.bindModel(asElement(gridRowTop), frameContext);

    ElementStackAdapter cellAdapter = (ElementStackAdapter) adapter.childAdapters.get(0);
    LayoutParams params = (LinearLayout.LayoutParams) cellAdapter.getView().getLayoutParams();
    assertThat(params.gravity).isEqualTo(Gravity.CENTER_VERTICAL);
  }

  @Test
  public void testOnBindModel_collapsibleCells_valid() {
    GridRow gridRow =
        GridRow.newBuilder()
            .addCells(
                GridCell.newBuilder()
                    .setWidth(
                        GridCellWidth.newBuilder().setContentWidth(ContentWidth.CONTENT_WIDTH))
                    .setContent(TEXT_CONTENT))
            .addCells(
                GridCell.newBuilder()
                    .setWidth(
                        GridCellWidth.newBuilder()
                            .setContentWidth(ContentWidth.CONTENT_WIDTH)
                            .setIsCollapsible(true))
                    .setContent(TEXT_CONTENT))
            .addCells(
                GridCell.newBuilder()
                    .setWidth(GridCellWidth.newBuilder().setDp(123))
                    .setContent(TEXT_CONTENT))
            .build();

    adapter.createAdapter(asElement(gridRow), frameContext);
    adapter.bindModel(asElement(gridRow), frameContext);

    assertThat(adapter.getBaseView().getChildAt(0).getLayoutParams().width)
        .isEqualTo(LayoutParams.WRAP_CONTENT);
    assertThat(adapter.getBaseView().getChildAt(1).getLayoutParams().width)
        .isEqualTo(LayoutParams.WRAP_CONTENT);
    assertThat(
            ((GridRowView.LayoutParams) adapter.getBaseView().getChildAt(1).getLayoutParams())
                .getIsCollapsible())
        .isTrue();
    assertThat(adapter.getBaseView().getChildAt(2).getLayoutParams().width)
        .isEqualTo((int) LayoutUtils.dpToPx(123, context));
  }

  @Test
  public void testOnBindModel_collapsibleCells_multipleCollapsible() {
    GridRow gridRow =
        GridRow.newBuilder()
            .addCells(
                GridCell.newBuilder()
                    .setWidth(
                        GridCellWidth.newBuilder()
                            .setContentWidth(ContentWidth.CONTENT_WIDTH)
                            .setIsCollapsible(true))
                    .setContent(TEXT_CONTENT))
            .addCells(
                GridCell.newBuilder()
                    .setWidth(GridCellWidth.newBuilder().setDp(456).setIsCollapsible(true))
                    .setContent(TEXT_CONTENT))
            .addCells(
                GridCell.newBuilder()
                    .setWidth(GridCellWidth.newBuilder().setDp(123))
                    .setContent(TEXT_CONTENT))
            .build();

    adapter.createAdapter(asElement(gridRow), frameContext);
    adapter.bindModel(asElement(gridRow), frameContext);

    assertThat(adapter.getBaseView().getChildAt(0).getLayoutParams().width)
        .isEqualTo(LayoutParams.WRAP_CONTENT);
    assertThat(
            ((GridRowView.LayoutParams) adapter.getBaseView().getChildAt(0).getLayoutParams())
                .getIsCollapsible())
        .isTrue();
    assertThat(adapter.getBaseView().getChildAt(1).getLayoutParams().width).isEqualTo(456);
    assertThat(
            ((GridRowView.LayoutParams) adapter.getBaseView().getChildAt(1).getLayoutParams())
                .getIsCollapsible())
        .isTrue();
    assertThat(adapter.getBaseView().getChildAt(2).getLayoutParams().width)
        .isEqualTo((int) LayoutUtils.dpToPx(123, context));
  }

  @Test
  public void testOnBindModel_collapsibleCells_mixingCollapsibleAndWeight() {
    GridRow gridRow =
        GridRow.newBuilder()
            .addCells(
                GridCell.newBuilder()
                    .setWidth(
                        GridCellWidth.newBuilder()
                            .setContentWidth(ContentWidth.CONTENT_WIDTH)
                            .setIsCollapsible(true))
                    .setContent(TEXT_CONTENT))
            .addCells(
                GridCell.newBuilder()
                    .setWidth(GridCellWidth.newBuilder().setWeight(4))
                    .setContent(TEXT_CONTENT))
            .addCells(
                GridCell.newBuilder()
                    .setWidth(GridCellWidth.newBuilder().setDp(123))
                    .setContent(TEXT_CONTENT))
            .build();

    adapter.createAdapter(asElement(gridRow), frameContext);
    adapter.bindModel(asElement(gridRow), frameContext);

    assertThat(adapter.getBaseView().getChildAt(0).getLayoutParams().width)
        .isEqualTo(LayoutParams.WRAP_CONTENT);
    assertThat(
            ((GridRowView.LayoutParams) adapter.getBaseView().getChildAt(0).getLayoutParams())
                .getIsCollapsible())
        .isTrue();
    assertThat(adapter.getBaseView().getChildAt(1).getLayoutParams().width).isEqualTo(0);
    assertThat(
            ((LinearLayout.LayoutParams) adapter.getBaseView().getChildAt(1).getLayoutParams())
                .weight)
        .isEqualTo(4.0f);
    assertThat(adapter.getBaseView().getChildAt(2).getLayoutParams().width)
        .isEqualTo((int) LayoutUtils.dpToPx(123, context));
  }

  @Test
  public void testOnBindModel_recreatesBindingCells() {
    Element cellWithOneElement =
        Element.newBuilder()
            .setElementList(
                ElementList.newBuilder()
                    .addContents(
                        Content.newBuilder()
                            .setElement(
                                Element.newBuilder()
                                    .setElementStack(ElementStack.getDefaultInstance()))))
            .build();
    Element cellWithTwoElements =
        Element.newBuilder()
            .setElementList(
                ElementList.newBuilder()
                    .addContents(
                        Content.newBuilder()
                            .setElement(
                                Element.newBuilder()
                                    .setElementStack(ElementStack.getDefaultInstance())))
                    .addContents(
                        Content.newBuilder()
                            .setElement(
                                Element.newBuilder()
                                    .setElementStack(ElementStack.getDefaultInstance()))))
            .build();

    when(frameContext.getElementBindingValue(ELEMENT_BINDING))
        .thenReturn(BindingValue.newBuilder().setElement(cellWithOneElement).build());
    adapter.createAdapter(GRID_ROW_WITH_BOUND_CELL, frameContext);
    // The cell adapter has not been created yet
    assertThat(adapter.getBaseView().getChildCount()).isEqualTo(0);
    assertThat(adapter.childAdapters).isEmpty();

    when(frameContext.getElementBindingValue(ELEMENT_BINDING))
        .thenReturn(BindingValue.newBuilder().setElement(cellWithTwoElements).build());
    adapter.bindModel(GRID_ROW_WITH_BOUND_CELL, frameContext);
    // The cell adapter creates its one view on bind.
    assertThat(((LinearLayout) adapter.getBaseView().getChildAt(0)).getChildCount()).isEqualTo(2);

    adapter.unbindModel();
    // The cell adapter has been released.
    assertThat(adapter.getBaseView().getChildCount()).isEqualTo(0);
    assertThat(adapter.childAdapters).isEmpty();

    when(frameContext.getElementBindingValue(ELEMENT_BINDING))
        .thenReturn(BindingValue.newBuilder().setElement(cellWithOneElement).build());
    adapter.bindModel(GRID_ROW_WITH_BOUND_CELL, frameContext);
    // The cell adapter can bind to a different model.
    assertThat(((LinearLayout) adapter.getBaseView().getChildAt(0)).getChildCount()).isEqualTo(1);
  }

  @Test
  public void testOnBindModel_visibilityGone() {
    when(frameContext.getElementBindingValue(ELEMENT_BINDING))
        .thenReturn(
            BindingValue.newBuilder().setBindingId(BINDING_ID).setElement(DEFAULT_ELEMENT).build());
    adapter.createAdapter(GRID_ROW_WITH_BOUND_CELL, frameContext);
    when(frameContext.getElementBindingValue(ELEMENT_BINDING))
        .thenReturn(
            BindingValue.newBuilder()
                .setBindingId(BINDING_ID)
                .setVisibility(Visibility.GONE)
                .build());

    adapter.bindModel(GRID_ROW_WITH_BOUND_CELL, frameContext);

    assertThat(adapter.getBaseView().getChildCount()).isEqualTo(0);
    assertThat(adapter.childAdapters).isEmpty();
  }

  @Test
  public void testOnBindModel_noContent() {
    when(frameContext.getElementBindingValue(ELEMENT_BINDING))
        .thenReturn(
            BindingValue.newBuilder().setBindingId(BINDING_ID).setElement(DEFAULT_ELEMENT).build());
    adapter.createAdapter(GRID_ROW_WITH_BOUND_CELL, frameContext);
    when(frameContext.getElementBindingValue(ELEMENT_BINDING))
        .thenReturn(BindingValue.newBuilder().setBindingId(BINDING_ID).build());

    assertThat(adapter.getBaseView().getChildCount()).isEqualTo(0);
    assertThat(adapter.childAdapters).isEmpty();
  }

  @Test
  public void testOnBindModel_optionalAbsent() {
    when(frameContext.getElementBindingValue(ELEMENT_BINDING))
        .thenReturn(
            BindingValue.newBuilder().setBindingId(BINDING_ID).setElement(DEFAULT_ELEMENT).build());
    adapter.createAdapter(GRID_ROW_WITH_BOUND_CELL, frameContext);

    ElementBindingRef optionalBinding = ELEMENT_BINDING.toBuilder().setIsOptional(true).build();
    GridRow optionalBindingRow =
        GridRow.newBuilder()
            .addCells(
                GridCell.newBuilder()
                    .setContent(Content.newBuilder().setBoundElement(optionalBinding)))
            .build();
    when(frameContext.getElementBindingValue(optionalBinding))
        .thenReturn(BindingValue.newBuilder().setBindingId(BINDING_ID).build());

    adapter.bindModel(asElement(optionalBindingRow), frameContext);

    assertThat(adapter.getBaseView().getChildCount()).isEqualTo(0);
    assertThat(adapter.childAdapters).isEmpty();
  }

  @Test
  public void testOnBindModel_throwsExceptionOnCellCountMismatch() {
    GridRow gridRowWithTwoElements =
        GridRow.newBuilder()
            .addCells(GridCell.newBuilder().setContent(DEFAULT_CONTENT))
            .addCells(GridCell.newBuilder().setContent(DEFAULT_CONTENT))
            .build();

    GridRow gridRowWithOneElement =
        GridRow.newBuilder().addCells(GridCell.newBuilder().setContent(DEFAULT_CONTENT)).build();

    adapter.createAdapter(asElement(gridRowWithTwoElements), frameContext);

    assertThatRunnable(() -> adapter.bindModel(asElement(gridRowWithOneElement), frameContext))
        .throwsAnExceptionOfType(IllegalStateException.class)
        .that()
        .hasMessageThat()
        .contains("Internal error in adapters per content");
  }

  @Test
  public void testOnBindModel_setsStylesOnlyIfBindingIsDefined() {
    GridRow gridRowWithStyle =
        GridRow.newBuilder()
            .addCells(GridCell.newBuilder().setContent(DEFAULT_CONTENT))
            .setStyleReferences(GRID_STYLES)
            .build();

    adapter.createAdapter(asElement(gridRowWithStyle), frameContext);
    verify(frameContext).makeStyleFor(GRID_STYLES);

    // When we bind a new model, the style does not change.
    StyleIdsStack otherStyles = StyleIdsStack.newBuilder().addStyleIds("ignored").build();
    GridRow gridRowWithOtherStyle =
        GridRow.newBuilder()
            .addCells(GridCell.newBuilder().setContent(DEFAULT_CONTENT))
            .setStyleReferences(otherStyles)
            .build();

    adapter.bindModel(asElement(gridRowWithOtherStyle), frameContext);
    verify(frameContext, never()).makeStyleFor(otherStyles);

    // If we bind a model that has a style binding, then the style does get re-applied.
    StyleIdsStack styleWithBinding =
        StyleIdsStack.newBuilder()
            .setStyleBinding(StyleBindingRef.newBuilder().setBindingId("homewardbound"))
            .build();
    GridRow gridRowWithBoundStyle =
        GridRow.newBuilder()
            .addCells(GridCell.newBuilder().setContent(DEFAULT_CONTENT))
            .setStyleReferences(styleWithBinding)
            .build();
    StyleProvider otherStyleProvider = mock(StyleProvider.class);
    when(frameContext.makeStyleFor(styleWithBinding)).thenReturn(otherStyleProvider);

    adapter.bindModel(asElement(gridRowWithBoundStyle), frameContext);
    verify(frameContext).makeStyleFor(styleWithBinding);
    verify(otherStyleProvider).applyElementStyles(adapter);
  }

  @Test
  public void testOnBindModel_collapsibleCells_valid_boundWidth() {
    GridCellWidthBindingRef widthBinding =
        GridCellWidthBindingRef.newBuilder().setBindingId("width").build();
    GridRow gridRow =
        GridRow.newBuilder()
            .addCells(
                GridCell.newBuilder()
                    .setWidth(
                        GridCellWidth.newBuilder().setContentWidth(ContentWidth.CONTENT_WIDTH))
                    .setContent(TEXT_CONTENT))
            .addCells(GridCell.newBuilder().setWidthBinding(widthBinding).setContent(TEXT_CONTENT))
            .addCells(
                GridCell.newBuilder()
                    .setWidth(GridCellWidth.newBuilder().setDp(123))
                    .setContent(TEXT_CONTENT))
            .build();

    when(frameContext.getGridCellWidthFromBinding(widthBinding))
        .thenReturn(GridCellWidth.newBuilder().setDp(456).build());
    adapter.createAdapter(asElement(gridRow), frameContext);

    when(frameContext.getGridCellWidthFromBinding(widthBinding))
        .thenReturn(
            GridCellWidth.newBuilder()
                .setContentWidth(ContentWidth.CONTENT_WIDTH)
                .setIsCollapsible(true)
                .build());
    adapter.bindModel(asElement(gridRow), frameContext);

    assertThat(adapter.getBaseView().getChildAt(0).getLayoutParams().width)
        .isEqualTo(LayoutParams.WRAP_CONTENT);
    assertThat(adapter.getBaseView().getChildAt(1).getLayoutParams().width)
        .isEqualTo(LayoutParams.WRAP_CONTENT);
    assertThat(
            ((GridRowView.LayoutParams) adapter.getBaseView().getChildAt(1).getLayoutParams())
                .getIsCollapsible())
        .isTrue();
    assertThat(adapter.getBaseView().getChildAt(2).getLayoutParams().width)
        .isEqualTo((int) LayoutUtils.dpToPx(123, context));
  }

  @Test
  public void testOnBindModel_collapsibleCells_multipleCollapsible_boundWidth() {
    GridCellWidthBindingRef widthBinding =
        GridCellWidthBindingRef.newBuilder().setBindingId("width").build();
    GridRow gridRow =
        GridRow.newBuilder()
            .addCells(
                GridCell.newBuilder()
                    .setWidth(
                        GridCellWidth.newBuilder()
                            .setContentWidth(ContentWidth.CONTENT_WIDTH)
                            .setIsCollapsible(true))
                    .setContent(TEXT_CONTENT))
            .addCells(GridCell.newBuilder().setWidthBinding(widthBinding).setContent(TEXT_CONTENT))
            .addCells(
                GridCell.newBuilder()
                    .setWidth(GridCellWidth.newBuilder().setDp(123))
                    .setContent(TEXT_CONTENT))
            .build();

    when(frameContext.getGridCellWidthFromBinding(widthBinding))
        .thenReturn(GridCellWidth.newBuilder().setDp(456).build());
    adapter.createAdapter(asElement(gridRow), frameContext);

    when(frameContext.getGridCellWidthFromBinding(widthBinding))
        .thenReturn(
            GridCellWidth.newBuilder()
                .setContentWidth(ContentWidth.CONTENT_WIDTH)
                .setIsCollapsible(true)
                .build());
    adapter.bindModel(asElement(gridRow), frameContext);

    assertThat(adapter.getBaseView().getChildAt(0).getLayoutParams().width)
        .isEqualTo(LayoutParams.WRAP_CONTENT);
    assertThat(
            ((GridRowView.LayoutParams) adapter.getBaseView().getChildAt(0).getLayoutParams())
                .getIsCollapsible())
        .isTrue();
    assertThat(adapter.getBaseView().getChildAt(1).getLayoutParams().width)
        .isEqualTo(LayoutParams.WRAP_CONTENT);
    assertThat(
            ((GridRowView.LayoutParams) adapter.getBaseView().getChildAt(1).getLayoutParams())
                .getIsCollapsible())
        .isTrue();
    assertThat(adapter.getBaseView().getChildAt(2).getLayoutParams().width)
        .isEqualTo((int) LayoutUtils.dpToPx(123, context));
  }

  @Test
  public void testUnbindModel() {
    GridRow model =
        GridRow.newBuilder()
            .addCells(GridCell.newBuilder().setContent(DEFAULT_CONTENT))
            .addCells(
                GridCell.newBuilder()
                    .setContent(Content.newBuilder().setBoundElement(ELEMENT_BINDING)))
            .build();

    when(frameContext.getElementBindingValue(ELEMENT_BINDING))
        .thenReturn(BindingValue.newBuilder().setElement(DEFAULT_ELEMENT).build());

    adapter.createAdapter(asElement(model), frameContext);
    adapter.bindModel(asElement(model), frameContext);

    adapter.unbindModel();
    assertThat(adapter.getBaseView().getChildCount()).isEqualTo(1);
    assertThat(adapter.childAdapters).hasSize(1);

    // The inline adapter has been unbound.
    assertThat(adapter.childAdapters.get(0).getRawModel()).isNull();
  }

  @Test
  public void testUnbindModel_worksTwice() {
    GridRow model =
        GridRow.newBuilder()
            .addCells(
                GridCell.newBuilder()
                    .setWidth(
                        GridCellWidth.newBuilder()
                            .setContentWidth(ContentWidth.CONTENT_WIDTH)
                            .setIsCollapsible(true))
                    .setContent(TEXT_CONTENT))
            .build();

    adapter.createAdapter(asElement(model), frameContext);
    adapter.bindModel(asElement(model), frameContext);

    adapter.unbindModel();
    adapter.unbindModel();

    // assert no failure.
  }

  @Test
  public void testReleaseAdapter() {
    GridRow model =
        GridRow.newBuilder()
            .addCells(GridCell.newBuilder().setContent(DEFAULT_CONTENT))
            .addCells(
                GridCell.newBuilder()
                    .setContent(Content.newBuilder().setBoundElement(ELEMENT_BINDING)))
            .build();

    when(frameContext.getElementBindingValue(ELEMENT_BINDING))
        .thenReturn(BindingValue.newBuilder().setElement(DEFAULT_ELEMENT).build());

    adapter.createAdapter(asElement(model), frameContext);
    adapter.bindModel(asElement(model), frameContext);

    adapter.unbindModel();
    adapter.releaseAdapter();
    assertThat(adapter.getBaseView().getChildCount()).isEqualTo(0);
    assertThat(adapter.childAdapters).isEmpty();
  }

  @Test
  public void testReleaseAdapter_collapsibleCells() {
    GridRow model =
        GridRow.newBuilder()
            .addCells(
                GridCell.newBuilder()
                    .setWidth(
                        GridCellWidth.newBuilder()
                            .setContentWidth(ContentWidth.CONTENT_WIDTH)
                            .setIsCollapsible(true))
                    .setContent(TEXT_CONTENT))
            .build();

    adapter.createAdapter(asElement(model), frameContext);
    adapter.bindModel(asElement(model), frameContext);

    adapter.unbindModel();
    adapter.releaseAdapter();

    assertThat(adapter.getBaseView().hasCollapsibleCells()).isFalse();
  }

  /**
   * Mini integration test to ensure that WRAP_CONTENT is set on GridRowAdapter when it is within a
   * hierarchy
   */
  @Test
  public void testCollapsibleCells_integration() {
    GridRow gridRow =
        GridRow.newBuilder()
            .addCells(
                GridCell.newBuilder()
                    .setWidth(GridCellWidth.newBuilder().setDp(123))
                    .setContent(TEXT_CONTENT))
            .addCells(
                GridCell.newBuilder()
                    .setWidth(
                        GridCellWidth.newBuilder()
                            .setContentWidth(ContentWidth.CONTENT_WIDTH)
                            .setIsCollapsible(true))
                    .setContent(TEXT_CONTENT))
            .addCells(
                GridCell.newBuilder()
                    .setWidth(
                        GridCellWidth.newBuilder().setContentWidth(ContentWidth.CONTENT_WIDTH))
                    .setContent(TEXT_CONTENT))
            .build();
    Frame frame =
        Frame.newBuilder()
            .addContents(
                Content.newBuilder()
                    .setElement(
                        Element.newBuilder()
                            .setElementList(
                                ElementList.newBuilder()
                                    .addContents(
                                        Content.newBuilder()
                                            .setElement(
                                                Element.newBuilder().setGridRow(gridRow))))))
            .build();
    EventLogger mockEventLogger = mock(EventLogger.class);
    FrameAdapterImpl frameAdapter =
        new FrameAdapterImpl(
            context, adapterParameters, actionHandler, mockEventLogger, DebugBehavior.SILENT);
    frameAdapter.bindModel(frame, 0, null, Collections.emptyList());
    LinearLayout gridRowView =
        ((LinearLayout) ((LinearLayout) frameAdapter.getView().getChildAt(0)).getChildAt(0));
    assertThat(gridRowView.getChildCount()).isEqualTo(3);
    assertThat(gridRowView.getChildAt(0).getLayoutParams().width)
        .isEqualTo((int) LayoutUtils.dpToPx(123, context));
    assertThat(
            ((GridRowView.LayoutParams) gridRowView.getChildAt(1).getLayoutParams())
                .getIsCollapsible())
        .isTrue();
    assertThat(gridRowView.getChildAt(2).getLayoutParams().width)
        .isEqualTo(LayoutParams.WRAP_CONTENT);
  }

  @Test
  public void testGetStyleIdsStack() {
    adapter.createAdapter(
        asElement(GridRow.newBuilder().setStyleReferences(GRID_STYLES).build()), frameContext);
    assertThat(adapter.getElementStyleIdsStack()).isEqualTo(GRID_STYLES);
  }

  @Test
  public void testCreateViewGroup() {
    LinearLayout gridView = GridRowAdapter.createView(context, Suppliers.of(false));
    assertThat(gridView.getOrientation()).isEqualTo(LinearLayout.HORIZONTAL);
    assertThat(gridView.getLayoutParams().width).isEqualTo(LayoutParams.MATCH_PARENT);
    assertThat(gridView.getLayoutParams().height).isEqualTo(LayoutParams.WRAP_CONTENT);
  }

  @Test
  public void testGetModelFromElement() {
    GridRow model =
        GridRow.newBuilder()
            .setStyleReferences(StyleIdsStack.newBuilder().addStyleIds("spacer"))
            .build();

    Element elementWithModel = Element.newBuilder().setGridRow(model).build();
    assertThat(adapter.getModelFromElement(elementWithModel)).isSameInstanceAs(model);

    Element elementWithWrongModel =
        Element.newBuilder().setCustomElement(CustomElement.getDefaultInstance()).build();
    assertThatRunnable(() -> adapter.getModelFromElement(elementWithWrongModel))
        .throwsAnExceptionOfType(PietFatalException.class)
        .that()
        .hasMessageThat()
        .contains("Missing GridRow");

    Element emptyElement = Element.getDefaultInstance();
    assertThatRunnable(() -> adapter.getModelFromElement(emptyElement))
        .throwsAnExceptionOfType(PietFatalException.class)
        .that()
        .hasMessageThat()
        .contains("Missing GridRow");
  }

  private static Element asElement(GridRow gridRow) {
    return Element.newBuilder().setGridRow(gridRow).build();
  }
}
