/*
 * #%L
 * Fuse EAP :: Config
 * %%
 * Copyright (C) 2015 RedHat
 * %%
 * 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.
 * #L%
 */
package org.jboss.fuse.eap.config;

import java.util.Arrays;
import java.util.List;

import de.pdark.decentxml.Document;
import de.pdark.decentxml.Element;
import de.pdark.decentxml.Text;
import static org.jboss.fuse.eap.config.ConfigSupport.*;
import static org.jboss.fuse.eap.config.LayerConfig.Type.INSTALLING;
import static org.jboss.fuse.eap.config.LayerConfig.Type.OPTIONAL;

/**
 */
public class SwitchyardConfigEditor implements ConfigEditor
{

   @Override
   public void applyStandaloneConfigChange(boolean enable, Document doc)
   {
      WildflyCamelConfigEditor.updateExtension(enable, doc);
      WildflyCamelConfigEditor.updateSubsystem(enable, doc);
//      WildflyCamelConfigEditor.updateWeldConfig(enable, doc);
      WildflyCamelConfigEditor.updateHawtIOSystemProperties(enable, doc);
      WildflyCamelConfigEditor.updateHawtIOSecurityDomain(enable, doc);

      updateExtension(enable, doc);
      updateLogging(enable, doc);
      updateSecurityDomain(enable, doc);
      updateSubsystem(enable, doc);
   }

   @Override
   public void applyDomainConfigChange(boolean enable, Document doc)
   {
      applyStandaloneConfigChange(enable, doc);
      updateInfinispan(enable, doc);

   }

   public static void updateExtension(boolean enable, Document doc)
   {
      Element extensions = doc.getRootElement().getChild("extensions");
      assertExists(extensions, "Did not find the <extensions> element");
      Element element = findElementWithAttributeValue(extensions.getChildren("extension"), "module", "org.switchyard");
      if (enable && element == null)
      {
         extensions.addNodes(
            new Text("    "),
            new Element("extension").addAttribute("module", "org.switchyard"),
            new Text("\n    ")
         );
      }
      if (!enable && element != null)
      {
         element.remove();
      }
   }

   public static void updateLogging(boolean enable, Document doc)
   {
      List<Element> profiles = findProfileElements(doc);
      for (Element profile : profiles)
      {

         Element logging = findElementWithStartingAttributeValue(profile.getChildren("subsystem"), "xmlns", "urn:jboss:domain:logging:");
         assertExists(logging, "Did not find the security subsystem");

         Element logger = findElementWithAttributeValue(logging.getChildren("logger"), "category", "org.switchyard");
         if (enable && logger == null)
         {
            logging.addNodes(
               new Text("    "),
               createElementFromText(
                  "            <logger category=\"org.switchyard\">\n" +
                     "                <level name=\"INFO\"/>\n" +
                     "            </logger>\n"),
               new Text("\n            ")
            );
         }
         if (!enable && logger != null)
         {
            logger.remove();
         }

         logger = findElementWithAttributeValue(logging.getChildren("logger"), "category", "org.apache.deltaspike.core.api.provider.BeanManagerProvider");
         if (enable && logger == null)
         {
            logging.addNodes(
               new Text("    "),
               createElementFromText(
                  "            <logger category=\"org.apache.deltaspike.core.api.provider.BeanManagerProvider\">\n" +
                     "                <level name=\"ERROR\"/>\n" +
                     "            </logger>\n"),
               new Text("\n            ")
            );
         }
         if (!enable && logger != null)
         {
            logger.remove();
         }
      }
   }

   public static void updateSecurityDomain(boolean enable, Document doc)
   {
      List<Element> profiles = findProfileElements(doc);
      for (Element profile : profiles)
      {
         Element security = findElementWithStartingAttributeValue(profile.getChildren("subsystem"), "xmlns", "urn:jboss:domain:security:");
         assertExists(security, "Did not find the security subsystem");
         Element domains = security.getChild("security-domains");
         assertExists(domains, "Did not find the <security-domains> element");
         Element domain = findElementWithAttributeValue(domains.getChildren("security-domain"), "name", "hawtio-domain");
         if (enable && domain == null)
         {
            domains.addNodes(
               new Text("    "),
               createElementFromText(
                  "                <security-domain name=\"bpel-console\" cache-type=\"default\">\n" +
                     "                   <authentication>\n" +
                     "                      <login-module code=\"UsersRoles\" flag=\"required\"/>\n" +
                     "                   </authentication>\n" +
                     "                </security-domain>"),
               new Text("\n            ")
            );
         }
         if (!enable && domain != null)
         {
            domain.remove();
         }
      }
   }

   public static void updateSubsystem(boolean enable, Document doc)
   {
      List<Element> profiles = findProfileElements(doc);
      for (Element profile : profiles)
      {
         Element subsystem = findElementWithStartingAttributeValue(profile.getChildren("subsystem"), "xmlns", "urn:jboss:domain:switchyard");
         if (enable && subsystem == null)
         {
            profile.addNodes(
               new Text("    "),
               loadElementFrom(SwitchyardConfigEditor.class.getResource("switchyard-subsystem.xml")),
               new Text("\n    ")
            );
         }
         if (!enable && subsystem != null)
         {
            subsystem.remove();
         }
      }
   }

   public static void updateInfinispan(boolean enable, Document doc)
   {
      List<Element> profiles = findProfileElements(doc);
      for (Element profile : profiles)
      {

         Element infinispan = findElementWithStartingAttributeValue(profile.getChildren("subsystem"), "xmlns", "urn:jboss:domain:infinispan:");
         assertExists(infinispan, "Did not find the security subsystem");
         Element container = findElementWithAttributeValue(infinispan.getChildren("cache-container"), "name", "switchyard");
         if (enable && container == null)
         {
            infinispan.addNodes(
               new Text("    "),
               createElementFromText(
                  "                <cache-container name=\"switchyard\" default-cache=\"default\" start=\"EAGER\">\n" +
                     "                    <transport lock-timeout=\"60000\"/>\n" +
                     "                    <replicated-cache name=\"default\" mode=\"SYNC\" batching=\"true\" start=\"EAGER\">\n" +
                     "                        <locking isolation=\"REPEATABLE_READ\"/>\n" +
                     "                    </replicated-cache>\n" +
                     "                </cache-container>\n"),
               new Text("\n            ")
            );
         }
         if (!enable && container != null)
         {
            container.remove();
         }
      }
   }

    @Override
    public List<LayerConfig> getLayerConfigs() {
        return Arrays.asList(
                new LayerConfig("fuse", INSTALLING, -10),
                new LayerConfig("bpms", OPTIONAL, -9),
                new LayerConfig("soa", INSTALLING, -8)
        );
    }


}
