package org.apache.logging.log4j;

import java.util.Arrays;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;

public final class MarkerManager {
   private static final ConcurrentMap<String, Marker> markerMap = new ConcurrentHashMap();

   private MarkerManager() {
   }

   public static void clear() {
      markerMap.clear();
   }

   public static Marker getMarker(String name) {
      markerMap.putIfAbsent(name, new MarkerManager.Log4jMarker(name));
      return (Marker)markerMap.get(name);
   }

   /** @deprecated */
   @Deprecated
   public static Marker getMarker(String name, String parent) {
      Marker parentMarker = (Marker)markerMap.get(parent);
      if (parentMarker == null) {
         throw new IllegalArgumentException("Parent Marker " + parent + " has not been defined");
      } else {
         Marker marker = getMarker(name, parentMarker);
         return marker;
      }
   }

   /** @deprecated */
   @Deprecated
   public static Marker getMarker(String name, Marker parent) {
      markerMap.putIfAbsent(name, new MarkerManager.Log4jMarker(name));
      return ((Marker)markerMap.get(name)).addParents(parent);
   }

   public static class Log4jMarker implements Marker {
      private static final long serialVersionUID = 100L;
      private final String name;
      private volatile Marker[] parents;

      private Log4jMarker() {
         this.name = null;
         this.parents = null;
      }

      public Log4jMarker(String name) {
         if (name == null) {
            throw new IllegalArgumentException("Marker name cannot be null.");
         } else {
            this.name = name;
            this.parents = null;
         }
      }

      public synchronized Marker addParents(Marker... parents) {
         if (parents == null) {
            throw new IllegalArgumentException("A parent marker must be specified");
         } else {
            Marker[] localParents = this.parents;
            int count = 0;
            int size = parents.length;
            Marker[] markers;
            int index;
            if (localParents != null) {
               markers = parents;
               index = parents.length;

               for(int i$ = 0; i$ < index; ++i$) {
                  Marker parent = markers[i$];
                  if (!contains(parent, localParents) && !parent.isInstanceOf((Marker)this)) {
                     ++count;
                  }
               }

               if (count == 0) {
                  return this;
               }

               size = localParents.length + count;
            }

            markers = new Marker[size];
            if (localParents != null) {
               System.arraycopy(localParents, 0, markers, 0, localParents.length);
            }

            index = localParents == null ? 0 : localParents.length;
            Marker[] arr$ = parents;
            int len$ = parents.length;

            for(int i$ = 0; i$ < len$; ++i$) {
               Marker parent = arr$[i$];
               if (localParents == null || !contains(parent, localParents) && !parent.isInstanceOf((Marker)this)) {
                  markers[index++] = parent;
               }
            }

            this.parents = markers;
            return this;
         }
      }

      public synchronized boolean remove(Marker parent) {
         if (parent == null) {
            throw new IllegalArgumentException("A parent marker must be specified");
         } else {
            Marker[] localParents = this.parents;
            if (localParents == null) {
               return false;
            } else {
               int localParentsLength = localParents.length;
               if (localParentsLength == 1) {
                  if (localParents[0].equals(parent)) {
                     this.parents = null;
                     return true;
                  } else {
                     return false;
                  }
               } else {
                  int index = 0;
                  Marker[] markers = new Marker[localParentsLength - 1];

                  for(int i = 0; i < localParentsLength; ++i) {
                     Marker marker = localParents[i];
                     if (!marker.equals(parent)) {
                        if (index == localParentsLength - 1) {
                           return false;
                        }

                        markers[index++] = marker;
                     }
                  }

                  this.parents = markers;
                  return true;
               }
            }
         }
      }

      public Marker setParents(Marker... markers) {
         if (markers != null && markers.length != 0) {
            Marker[] array = new Marker[markers.length];
            System.arraycopy(markers, 0, array, 0, markers.length);
            this.parents = array;
         } else {
            this.parents = null;
         }

         return this;
      }

      public String getName() {
         return this.name;
      }

      public Marker[] getParents() {
         return this.parents == null ? null : (Marker[])Arrays.copyOf(this.parents, this.parents.length);
      }

      public boolean hasParents() {
         return this.parents == null;
      }

      public boolean isInstanceOf(Marker marker) {
         if (marker == null) {
            throw new IllegalArgumentException("A marker parameter is required");
         } else if (this == marker) {
            return true;
         } else {
            Marker[] localParents = this.parents;
            if (localParents != null) {
               int localParentsLength = localParents.length;
               if (localParentsLength == 1) {
                  return checkParent(localParents[0], marker);
               }

               if (localParentsLength == 2) {
                  return checkParent(localParents[0], marker) || checkParent(localParents[1], marker);
               }

               for(int i = 0; i < localParentsLength; ++i) {
                  Marker localParent = localParents[i];
                  if (checkParent(localParent, marker)) {
                     return true;
                  }
               }
            }

            return false;
         }
      }

      public boolean isInstanceOf(String markerName) {
         if (markerName == null) {
            throw new IllegalArgumentException("A marker name is required");
         } else if (markerName.equals(this.getName())) {
            return true;
         } else {
            Marker marker = (Marker)MarkerManager.markerMap.get(markerName);
            if (marker == null) {
               return false;
            } else {
               Marker[] localParents = this.parents;
               if (localParents != null) {
                  int localParentsLength = localParents.length;
                  if (localParentsLength == 1) {
                     return checkParent(localParents[0], marker);
                  }

                  if (localParentsLength == 2) {
                     return checkParent(localParents[0], marker) || checkParent(localParents[1], marker);
                  }

                  for(int i = 0; i < localParentsLength; ++i) {
                     Marker localParent = localParents[i];
                     if (checkParent(localParent, marker)) {
                        return true;
                     }
                  }
               }

               return false;
            }
         }
      }

      private static boolean checkParent(Marker parent, Marker marker) {
         if (parent == marker) {
            return true;
         } else {
            Marker[] localParents = parent instanceof MarkerManager.Log4jMarker ? ((MarkerManager.Log4jMarker)parent).parents : parent.getParents();
            if (localParents != null) {
               int localParentsLength = localParents.length;
               if (localParentsLength == 1) {
                  return checkParent(localParents[0], marker);
               }

               if (localParentsLength == 2) {
                  return checkParent(localParents[0], marker) || checkParent(localParents[1], marker);
               }

               for(int i = 0; i < localParentsLength; ++i) {
                  Marker localParent = localParents[i];
                  if (checkParent(localParent, marker)) {
                     return true;
                  }
               }
            }

            return false;
         }
      }

      private static boolean contains(Marker parent, Marker... localParents) {
         int i = 0;

         for(int localParentsLength = localParents.length; i < localParentsLength; ++i) {
            Marker marker = localParents[i];
            if (marker == parent) {
               return true;
            }
         }

         return false;
      }

      public boolean equals(Object o) {
         if (this == o) {
            return true;
         } else if (o != null && o instanceof Marker) {
            Marker marker = (Marker)o;
            return this.name.equals(marker.getName());
         } else {
            return false;
         }
      }

      public int hashCode() {
         return this.name.hashCode();
      }

      public String toString() {
         StringBuilder sb = new StringBuilder(this.name);
         Marker[] localParents = this.parents;
         if (localParents != null) {
            addParentInfo(sb, localParents);
         }

         return sb.toString();
      }

      private static void addParentInfo(StringBuilder sb, Marker... parents) {
         sb.append("[ ");
         boolean first = true;
         int i = 0;

         for(int parentsLength = parents.length; i < parentsLength; ++i) {
            Marker marker = parents[i];
            if (!first) {
               sb.append(", ");
            }

            first = false;
            sb.append(marker.getName());
            Marker[] p = marker instanceof MarkerManager.Log4jMarker ? ((MarkerManager.Log4jMarker)marker).parents : marker.getParents();
            if (p != null) {
               addParentInfo(sb, p);
            }
         }

         sb.append(" ]");
      }
   }
}
