package com.airlock.iam.plugin.framework.infrastructure.xstream;

import com.thoughtworks.xstream.XStream;
import com.thoughtworks.xstream.converters.ConversionException;
import com.thoughtworks.xstream.converters.reflection.PureJavaReflectionProvider;
import com.thoughtworks.xstream.io.HierarchicalStreamReader;
import com.thoughtworks.xstream.io.HierarchicalStreamWriter;
import com.thoughtworks.xstream.security.NoTypePermission;
import java.util.Optional;
import org.apache.commons.lang3.Strings;

public final class XStreamHelper {
   public static XStream createXStream(Class<?>... allowedTypes) {
      XStream xStream = new XStream(new PureJavaReflectionProvider());
      xStream.addPermission(NoTypePermission.NONE);
      xStream.allowTypes(allowedTypes);
      xStream.ignoreUnknownElements();
      return xStream;
   }

   static void ensureInNode(String expected, HierarchicalStreamReader reader) throws ConversionException {
      if (!Strings.CS.equals(expected, reader.getNodeName())) {
         throw new ConversionException("Exected to be in node " + expected + " but currently in " + reader.getNodeName());
      }
   }

   static void forcefullyWriteAttribute(HierarchicalStreamWriter writer, String attribute, String value) throws ConversionException {
      if (value == null) {
         throw new ConversionException("The attribute " + attribute + " is mandatory and cannot be null");
      }

      writer.addAttribute(attribute, value);
   }

   static String readMandatoryAttribute(HierarchicalStreamReader reader, String propName) throws ConversionException {
      String attrValue = reader.getAttribute(propName);
      if (attrValue != null) {
         return attrValue;
      } else {
         throw new ConversionException("Mandatory attribute " + propName + " is missing");
      }
   }

   static Optional<String> readOptionalAttribute(HierarchicalStreamReader reader, String propName) {
      String attrValue = reader.getAttribute(propName);
      return Optional.ofNullable(attrValue);
   }

   static String readOptionalAttributeWithDefault(HierarchicalStreamReader reader, String propName, String defaultValue) {
      String attrValue = reader.getAttribute(propName);
      return attrValue != null ? attrValue : defaultValue;
   }

   static void writeAttributeIfValueIsPresent(HierarchicalStreamWriter writer, String key, Optional<String> value) {
      if (value.isPresent()) {
         writer.addAttribute(key, value.get());
      }
   }

   private XStreamHelper() {
      throw new AssertionError();
   }
}
