// 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.common.truth.Truth.assertThat;
import static java.util.Arrays.asList;
import static org.mockito.ArgumentMatchers.any;
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.ViewGroup.LayoutParams;
import android.view.ViewGroup.MarginLayoutParams;
import android.widget.ImageView;
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.piet.host.AssetProvider;
import com.google.search.now.ui.piet.BindingRefsProto.ElementBindingRef;
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.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.GridRow;
import com.google.search.now.ui.piet.ElementsProto.ImageElement;
import com.google.search.now.ui.piet.ImagesProto.Image;
import com.google.search.now.ui.piet.RoundedCornersProto.RoundedCorners;
import java.util.Collections;
import java.util.List;
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 ElementStackAdapter} */
@RunWith(RobolectricTestRunner.class)
public class ElementStackAdapterTest {
  private static final Content INLINE_CONTENT =
      Content.newBuilder()
          .setElement(Element.newBuilder().setElementList(ElementList.getDefaultInstance()))
          .build();
  private static final Element BOUND_ELEMENT =
      Element.newBuilder().setGridRow(GridRow.getDefaultInstance()).build();
  private static final String ELEMENT_BINDING_ID = "RowBinding";
  private static final ElementBindingRef ELEMENT_BINDING =
      ElementBindingRef.newBuilder().setBindingId(ELEMENT_BINDING_ID).build();
  private static final BindingValue ELEMENT_BINDING_VALUE =
      BindingValue.newBuilder().setBindingId(ELEMENT_BINDING_ID).setElement(BOUND_ELEMENT).build();
  private static final Content BOUND_CONTENT =
      Content.newBuilder().setBoundElement(ELEMENT_BINDING).build();

  @Mock private FrameContext frameContext;
  @Mock private AssetProvider assetProvider;
  @Mock private StyleProvider mockStyleProvider;
  @Mock private HostProviders mockHostProviders;

  private Context context;
  private AdapterParameters adapterParameters;

  private ElementStackAdapter adapter;

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

    when(frameContext.getElementBindingValue(ELEMENT_BINDING)).thenReturn(ELEMENT_BINDING_VALUE);
    when(frameContext.makeStyleFor(any())).thenReturn(mockStyleProvider);
    when(frameContext.filterImageSourcesByMediaQueryCondition(any(Image.class)))
        .thenAnswer(invocation -> invocation.getArguments()[0]);
    when(mockHostProviders.getAssetProvider()).thenReturn(assetProvider);
    when(mockStyleProvider.getRoundedCorners()).thenReturn(RoundedCorners.getDefaultInstance());

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

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

  @Test
  public void testCreatesInlineAdaptersInOnCreate() {
    Element element = asElement(asList(INLINE_CONTENT, BOUND_CONTENT));

    adapter.createAdapter(element, frameContext);

    assertThat(adapter.childAdapters).hasSize(1);
    assertThat(adapter.childAdapters.get(0)).isInstanceOf(ElementListAdapter.class);
    assertThat(adapter.getBaseView().getChildCount()).isEqualTo(1);
    assertThat(adapter.getBaseView().getChildAt(0))
        .isSameAs(adapter.childAdapters.get(0).getView());
  }

  @Test
  public void testCreatesBoundAdaptersInOnBind() {
    Element element = asElement(asList(INLINE_CONTENT, BOUND_CONTENT));

    adapter.createAdapter(element, frameContext);
    adapter.bindModel(element, frameContext);

    assertThat(adapter.childAdapters).hasSize(2);
    assertThat(adapter.childAdapters.get(0)).isInstanceOf(ElementListAdapter.class);
    assertThat(adapter.childAdapters.get(1)).isInstanceOf(GridRowAdapter.class);
    assertThat(adapter.getBaseView().getChildCount()).isEqualTo(2);
    assertThat(adapter.getBaseView().getChildAt(0))
        .isSameAs(adapter.childAdapters.get(0).getView());
    assertThat(adapter.getBaseView().getChildAt(1))
        .isSameAs(adapter.childAdapters.get(1).getView());
  }

  @Test
  public void testSetsLayoutParamsOnChildForInlineAdapters() {
    Content imageContent =
        Content.newBuilder()
            .setElement(
                Element.newBuilder()
                    .setImageElement(
                        ImageElement.newBuilder().setImage(Image.getDefaultInstance())))
            .build();
    Element element = asElement(Collections.singletonList(imageContent));

    when(mockStyleProvider.hasWidth()).thenReturn(true);
    when(mockStyleProvider.hasHeight()).thenReturn(true);
    when(mockStyleProvider.getWidthSpecPx(context)).thenReturn(123);
    when(mockStyleProvider.getHeightSpecPx(context)).thenReturn(456);
    when(mockStyleProvider.getScaleType()).thenReturn(ImageView.ScaleType.CENTER_CROP);

    adapter.createAdapter(element, frameContext);
    adapter.bindModel(element, frameContext);

    LayoutParams inlineAdapterLayoutParams =
        adapter.childAdapters.get(0).getView().getLayoutParams();

    assertThat(inlineAdapterLayoutParams.width).isEqualTo(123);
    assertThat(inlineAdapterLayoutParams.height).isEqualTo(456);
  }

  @Test
  public void testSetsLayoutParamsOnChildForBoundAdapters() {
    ElementBindingRef imageBinding = ElementBindingRef.newBuilder().setBindingId("image").build();
    BindingValue imageBindingValue =
        BindingValue.newBuilder()
            .setElement(
                Element.newBuilder()
                    .setImageElement(
                        ImageElement.newBuilder().setImage(Image.getDefaultInstance())))
            .build();
    when(frameContext.getElementBindingValue(imageBinding)).thenReturn(imageBindingValue);
    Element element =
        asElement(
            Collections.singletonList(Content.newBuilder().setBoundElement(imageBinding).build()));

    when(mockStyleProvider.hasWidth()).thenReturn(true);
    when(mockStyleProvider.hasHeight()).thenReturn(true);
    when(mockStyleProvider.getWidthSpecPx(context)).thenReturn(123);
    when(mockStyleProvider.getHeightSpecPx(context)).thenReturn(456);
    when(mockStyleProvider.getScaleType()).thenReturn(ImageView.ScaleType.CENTER_CROP);

    adapter.createAdapter(element, frameContext);
    adapter.bindModel(element, frameContext);

    LayoutParams boundAdapterLayoutParams =
        adapter.childAdapters.get(0).getView().getLayoutParams();

    assertThat(boundAdapterLayoutParams.width).isEqualTo(123);
    assertThat(boundAdapterLayoutParams.height).isEqualTo(456);
  }

  @Test
  public void testSetsMarginsOnChild() {
    Element element = asElement(Collections.singletonList(INLINE_CONTENT));

    adapter.createAdapter(element, frameContext);
    adapter.bindModel(element, frameContext);

    MarginLayoutParams childAdapterLayoutParams =
        (MarginLayoutParams) adapter.childAdapters.get(0).getView().getLayoutParams();

    verify(mockStyleProvider).applyMargins(context, childAdapterLayoutParams);
  }

  @Test
  public void testGetContentsFromModel() {
    ElementStack model =
        ElementStack.newBuilder().addAllContents(asList(INLINE_CONTENT, BOUND_CONTENT)).build();

    assertThat(adapter.getContentsFromModel(model)).isSameAs(model.getContentsList());
  }

  @Test
  public void testGetModelFromElement() {
    Element element = asElement(asList(INLINE_CONTENT, BOUND_CONTENT));

    assertThat(adapter.getModelFromElement(element)).isSameAs(element.getElementStack());
  }

  private Element asElement(List<Content> contents) {
    return Element.newBuilder()
        .setElementStack(ElementStack.newBuilder().addAllContents(contents))
        .build();
  }
}
