/*
 * Copyright (c) 2017-present, Facebook, Inc.
 * All rights reserved.
 *
 * This source code is licensed under the BSD-style license found in the
 * LICENSE file in the root directory of this source tree. An additional grant
 * of patent rights can be found in the PATENTS file in the same directory.
 */

package com.facebook.litho;

import android.support.v4.util.Pools;
import android.support.v4.util.Pools.Pool;
import android.support.v4.util.SimpleArrayMap;

/**
 * Keeps the {@link Component} and its information that will allow the framework
 * to understand how to render it.
 *
 * SpanSize will be defaulted to 1. It is the information that is required to calculate
 * how much of the SpanCount the component should occupy in a Grid layout.
 *
 * IsSticky will be defaulted to false. It determines if the component should be
 * a sticky header or not
 */
public class ComponentInfo {

  public static final String CLIP_CHILDREN = "clip_children";

  private static final Pool<Builder> sBuilderPool = new Pools.SynchronizedPool<>(2);
  private static final String IS_STICKY = "is_sticky";
  private static final String SPAN_SIZE = "span_size";

  private final Component mComponent;
  private final SimpleArrayMap<String, Object> mCustomAttributes;

  public static Builder create() {
    Builder builder = sBuilderPool.acquire();
    if (builder == null) {
      builder = new Builder();
    }

    return builder;
  }

  private ComponentInfo(Builder builder) {
    mComponent = builder.mComponent;
    mCustomAttributes = builder.mCustomAttributes;
  }

  public Component getComponent() {
    return mComponent;
  }

  public boolean isSticky() {
    if (mCustomAttributes == null || !mCustomAttributes.containsKey(IS_STICKY)) {
      return false;
    }

    return (boolean) mCustomAttributes.get(IS_STICKY);
  }

  public int getSpanSize() {
    if (mCustomAttributes == null || !mCustomAttributes.containsKey(SPAN_SIZE)) {
      return 1;
    }

    return (int) mCustomAttributes.get(SPAN_SIZE);
  }

  public Object getCustomAttribute(String key) {
    return mCustomAttributes == null ? null : mCustomAttributes.get(key);
  }

  public static class Builder {

    private Component mComponent;
    private SimpleArrayMap<String, Object> mCustomAttributes;

    private Builder() {
      mComponent = null;
    }

    public Builder component(Component component) {
      mComponent = component;
      return this;
    }

    public Builder isSticky(boolean isSticky) {
      return customAttribute(IS_STICKY, isSticky);
    }

    public Builder spanSize(int spanSize) {
      return customAttribute(SPAN_SIZE, spanSize);
    }

    public Builder customAttribute(String key, Object value) {
      if (mCustomAttributes == null) {
        mCustomAttributes = new SimpleArrayMap<>();
      }
      mCustomAttributes.put(key, value);

      return this;
    }

    public ComponentInfo build() {
      ComponentInfo componentInfo =  new ComponentInfo(this);
      release();

      return componentInfo;
    }

    private void release() {
      mComponent = null;
      mCustomAttributes = null;
      sBuilderPool.release(this);
    }
  }
}

@@ -458,16 +458,50 @@
 rrayMap;
+%0Aimport javax.annotation.Nullable;
 %0A%0A/**%0A *
@@ -1199,16 +1199,26 @@
 e final 
+@Nullable 
 Componen
@@ -1247,16 +1247,26 @@
 e final 
+@Nullable 
 SimpleAr
@@ -1479,16 +1479,99 @@
 r;%0A  %7D%0A%0A
+  public static ComponentInfo createEmpty() %7B%0A    return new ComponentInfo();%0A  %7D%0A%0A
   privat
@@ -1701,21 +1701,117 @@
   %7D%0A%0A  p
-ublic
+rivate ComponentInfo() %7B%0A    mComponent = null;%0A    mCustomAttributes = null;%0A  %7D%0A%0A  public @Nullable
  Compone
@@ -2256,16 +2256,26 @@
  public 
+@Nullable 
 Object g
@@ -2422,32 +2422,42 @@
  %7B%0A%0A    private 
+@Nullable 
 Component mCompo
@@ -2474,16 +2474,26 @@
 private 
+@Nullable 
 SimpleAr

Replace all usages of ComponentInfo.create().build() with ComponentInfo.createEmpty()