/*
 * Copyright (c) Facebook, Inc. and its affiliates.
 *
 * 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.facebook.litho;

import java.util.List;
import javax.annotation.Nullable;

/**
 * {@link DebugHierarchy} provides a light(er) weight way to track and access information about the
 * component parentage of a given {@link MountItem}. For a given {@link MountItem}, it provides
 * access to a linked list of {@link Class} objects representing the class of the {@link Component}
 * and each of it's hierarchy parents.
 */
public class DebugHierarchy {

  public static class Node {

    public final @Nullable Node parent;
    public final @Nullable Component component;
    public final @Nullable List<Component> components;
    public final @OutputUnitType int type;

    public Node(
        @Nullable Node parent,
        @Nullable Component component,
        @Nullable List<Component> components,
        @OutputUnitType int type) {
      this.parent = parent;
      this.component = component;
      this.components = components;
      this.type = type;
    }

    public Node mutateType(int type) {
      if (this.type == type) {
        return this;
      }

      return new Node(parent, component, components, type);
    }

    @Override
    public String toString() {
      if (components == null || components.isEmpty()) {
        return "(no components)";
      }
      StringBuilder sb = new StringBuilder();
      sb.append('{');
      for (Component component : components) {
        sb.append(component.getSimpleName());
        sb.append(", ");
      }
      sb.deleteCharAt(sb.length() - 1);
      sb.append('}');
      return sb.toString();
    }
  }

  public static Node newNode(
      @Nullable Node parent, @Nullable Component component, @Nullable List<Component> components) {
    return new Node(parent, component, components, OutputUnitType.HOST);
  }

  private DebugHierarchy() {}

  public static int getMountItemCount(ComponentHost host) {
    return host.getMountItemCount();
  }

  public static Object getMountItemContent(ComponentHost host, int mountItemIndex) {
    return host.getMountItemAt(mountItemIndex).getContent();
  }

  public static @Nullable Node getMountItemHierarchy(ComponentHost host, int mountItemIndex) {
    return host.getMountItemAt(mountItemIndex).getHierarchy();
  }

  public static @Nullable String getOutputUnitTypeName(@OutputUnitType int type) {
    switch (type) {
      case OutputUnitType.CONTENT:
        return "CONTENT";
      case OutputUnitType.BACKGROUND:
        return "BACKGROUND";
      case OutputUnitType.FOREGROUND:
        return "FOREGROUND";
      case OutputUnitType.HOST:
        return "HOST";
      case OutputUnitType.BORDER:
        return "BORDER";
      default:
        return null;
    }
  }
}

@@ -1762,48 +1762,132 @@
     
-@Override%0A    public String toString() %7B
+private void toHierarchyString(StringBuilder sb) %7B%0A      if (parent != null) %7B%0A        parent.toHierarchyString(sb);%0A      %7D
 %0A   
@@ -1947,23 +1947,26 @@
         
-return 
+sb.append(
 %22(no com
@@ -1974,24 +1974,25 @@
 onents)%22
+)
 ;%0A      
 %7D%0A      
@@ -1987,121 +1987,103 @@
     
-%7D%0A      StringBuilder sb = new StringBuilder();%0A      sb.append('%7B');%0A      for (Component component : components
+  sb.append(',');%0A        return;%0A      %7D%0A      for (int i = components.size() - 1; i %3E= 0; i--
 ) %7B%0A
@@ -2109,16 +2109,24 @@
 omponent
+s.get(i)
 .getSimp
@@ -2158,12 +2158,11 @@
 end(
-%22, %22
+','
 );%0A 
@@ -2164,24 +2164,199 @@
 ');%0A      %7D%0A
+    %7D%0A%0A    public String toHierarchyString() %7B%0A      StringBuilder sb = new StringBuilder();%0A      sb.append('%7B');%0A      toHierarchyString(sb);%0A      if (sb.length() %3E 1) %7B%0A  
       sb.del
@@ -2383,16 +2383,24 @@
 ) - 1);%0A
+      %7D%0A
       sb

Make the DebugHierarchy print the parent hierarchy as well (and move functionality out of toString so it can be stripped)