package com.hubspot.jinjava.lib.fn;

import java.time.ZonedDateTime;
import java.util.List;
import java.util.Map;

import com.hubspot.jinjava.doc.annotations.JinjavaDoc;
import com.hubspot.jinjava.el.ext.AstDict;
import com.hubspot.jinjava.el.ext.AstList;
import com.hubspot.jinjava.el.ext.AstTuple;
import com.hubspot.jinjava.objects.date.PyishDate;


@JinjavaDoc(
    value = "Get a string that describes the type of the object, similar to Python's type()")
public class TypeFunction {

  public static String type(Object var) {
    if (var == null) {
      return "null";
    }

    if (var.getClass() == AstDict.class || Map.class.isAssignableFrom(var.getClass())) {
      return "dict";
    }

    if (var.getClass() == AstList.class || List.class.isAssignableFrom(var.getClass())) {
      return "list";
    }

    if (var.getClass() == Boolean.class) {
      return "bool";
    }

    if (var.getClass() == AstTuple.class) {
      return "tuple";
    }

    if (var.getClass() == PyishDate.class || var.getClass() == ZonedDateTime.class) {
      return "datetime";
    }

    if (Integer.class.isAssignableFrom(var.getClass())) {
      return "int";
    }

    if (Long.class.isAssignableFrom(var.getClass())) {
      return "long";
    }

    if (Float.class.isAssignableFrom(var.getClass()) || Double.class.isAssignableFrom(var.getClass())) {
      return "float";
    }

    if (String.class.isAssignableFrom(var.getClass())) {
      return "str";
    }

    return "unknown";
  }

}

@@ -107,16 +107,91 @@
 il.Map;%0A
+import java.util.Map.Entry;%0A%0Aimport com.google.common.collect.ImmutableMap;
 %0Aimport 
@@ -564,21 +564,22 @@
 %0A  p
-ublic
+rivate
  static 
 Stri
@@ -578,718 +578,773 @@
 tic 
-String type(Object var) %7B%0A    if (var == null) %7B%0A      return %22null%22;%0A    %7D%0A%0A    if (var.getClass() == AstDict.class %7C%7C Map.class.isAssignableFrom(var.getClass())) %7B%0A      return
+Map%3CClass%3C?%3E, String%3E CLASS_TYPE_TO_NAME = ImmutableMap.%3CClass%3C?%3E, String%3Ebuilder()%0A      .put(AstDict.class,
  %22dict%22
-;
+)
 %0A    
-%7D%0A%0A    if (var.getClass() == AstList.class %7C%7C List.class.isAssignableFrom(var.getClass())) %7B%0A      return %22list%22;%0A    %7D%0A%0A    if (var.getClass() == Boolean.class) %7B%0A      return
+  .put(AstList.class, %22list%22)%0A      .put(AstTuple.class, %22tuple%22)%0A      .put(Boolean.class,
  %22bool%22
-;
+)
 %0A    
-%7D%0A%0A    if (var.getClass() == AstTuple.class) %7B%0A      return %22tuple%22;
+  .put(PyishDate.class, %22datetime%22)%0A      .put(ZonedDateTime.class, %22datetime%22)
 %0A    
-%7D%0A%0A    if (var.getClass() == PyishDate.class %7C%7C var.getClass() == ZonedDateTime.class) %7B%0A      return %22datetime%22;%0A    %7D%0A%0A    if (Integer.class.isAssignableFrom(var.getClass())) %7B%0A      return %22int%22;%0A    %7D%0A%0A    if (Long.class.isAssignableFrom(var.getClass())
+  .build();%0A%0A  private static Map%3CClass%3C?%3E, String%3E ASSIGNABLE_TYPE_TO_NAME = ImmutableMap.%3CClass%3C?%3E, String%3Ebuilder()%0A      .put(Boolean.class, %22bool%22)%0A      .put(Double.class, %22float%22)%0A      .put(Float.class, %22float%22)%0A      .put(Integer.class, %22int%22)%0A      .put(List.class, %22list%22)%0A      .put(Long.class, %22long%22)%0A      .put(Map.class, %22dict%22)%0A      .put(String.class, %22str%22)%0A      .build();%0A%0A  public static String type(Object var) %7B%0A    if (var == null
 ) %7B%0A
@@ -1357,20 +1357,20 @@
 return %22
-long
+null
 %22;%0A    %7D
@@ -1379,109 +1379,126 @@
     
-if (Float.class.isAssignableFrom(var.getClass()) %7C%7C Double.class.isAssignableFrom(var.getClass()
+for (Entry%3CClass%3C?%3E, String%3E entry : CLASS_TYPE_TO_NAME.entrySet()) %7B%0A      if (var.getClass() == entry.getKey(
 )) %7B%0A
+  
     
@@ -1510,44 +1510,144 @@
 urn 
-%22float%22;%0A    %7D%0A%0A    if (String.class
+entry.getValue();%0A      %7D%0A    %7D%0A%0A    for (Entry%3CClass%3C?%3E, String%3E entry : ASSIGNABLE_TYPE_TO_NAME.entrySet()) %7B%0A      if (entry.getKey()
 .isA
@@ -1689,21 +1689,42 @@
     
+  
 return 
-%22str%22;
+entry.getValue();%0A      %7D
 %0A   

Make this data-driven