/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you 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 org.netbeans.modules.payara.jakartaee;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.netbeans.modules.payara.spi.PayaraModule;
import org.netbeans.modules.payara.common.parser.TreeParser;
import org.netbeans.modules.j2ee.deployment.common.api.ConfigurationException;
import org.netbeans.modules.j2ee.deployment.common.api.MessageDestination;
import org.netbeans.modules.j2ee.deployment.common.api.MessageDestination.Type;
import org.netbeans.modules.j2ee.deployment.plugins.spi.MessageDestinationDeployment;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;

/**
 *
 * @author Nitya Doraisamy
 */
public class Hk2MessageDestinationManager implements  MessageDestinationDeployment {

    private Hk2DeploymentManager dm;

    private static final String DOMAIN_XML_PATH = "config/domain.xml";
    public static final String JMS_PREFIX = "jms/"; // NOI18N
    public static final String QUEUE = "javax.jms.Queue"; // NOI18N
    public static final String TOPIC = "javax.jms.Topic"; // NOI18N
    public static final String QUEUE_PROP = "PhysicalQueue"; // NOI18N
    public static final String TOPIC_PROP = "PhysicalTopic"; // NOI18N

    public static final String QUEUE_CNTN_FACTORY = "javax.jms.QueueConnectionFactory"; // NOI18N
    public static final String TOPIC_CNTN_FACTORY = "javax.jms.TopicConnectionFactory"; // NOI18N

    
    public Hk2MessageDestinationManager(Hk2DeploymentManager dm) {
        this.dm = dm;
    }

    @Override
    public Set<MessageDestination> getMessageDestinations() throws ConfigurationException {
        PayaraModule commonSupport = dm.getCommonServerSupport();
        String domainsDir = commonSupport.getInstanceProperties().get(PayaraModule.DOMAINS_FOLDER_ATTR);
        String domainName = commonSupport.getInstanceProperties().get(PayaraModule.DOMAIN_NAME_ATTR);
        if (null != domainsDir) {
            // XXX Fix to work with current server domain, not just default domain.
            File domainXml = new File(domainsDir, domainName + File.separatorChar + DOMAIN_XML_PATH);

            // TODO : need to account for a remote domain here?
            return readMessageDestinations(domainXml, "/domain/", null);
        } else {
            return Collections.emptySet();
        }
    }

    @Override
    public void deployMessageDestinations(Set<MessageDestination> destinations) throws ConfigurationException {
        // since a connection pool is not a Datasource, all resource deployment has to
        // happen in a different part of the deploy processing...  so this should remain
        // empty to prevent redundant processing.
    }

    // ------------------------------------------------------------------------
    //  Used by ModuleConfigurationImpl since
    // ------------------------------------------------------------------------
    public static Set<MessageDestination> getMessageDestinations(File resourceDir, String baseName) {
        File resourcesXml = new File(resourceDir, baseName+".xml");
        return readMessageDestinations(resourcesXml, "/", resourceDir);
    }
    
    private static Set<MessageDestination> readMessageDestinations(File xmlFile, String xPathPrefix, File resourcesDir) {
        Set<MessageDestination> msgDestinations = new HashSet<MessageDestination>();
        if(xmlFile.exists()) {
            Map<String, AdminObjectResource> aoResourceMap = new HashMap<String, AdminObjectResource>();
            List<TreeParser.Path> pathList = new ArrayList<TreeParser.Path>();
            pathList.add(new TreeParser.Path(xPathPrefix + "resources/admin-object-resource", new AdminObjectReader(aoResourceMap)));

            try {
                TreeParser.readXml(xmlFile, pathList);
            } catch(IllegalStateException ex) {
                Logger.getLogger("payara-jakartaee").log(Level.INFO, ex.getLocalizedMessage(), ex);
            }

            for(AdminObjectResource adminObj: aoResourceMap.values()) {
                String type = adminObj.getResType();
                if (type.equals(QUEUE)) {
                    msgDestinations.add(new SunMessageDestination(adminObj.getJndiName(), MessageDestination.Type.QUEUE, resourcesDir));
                } else {
                    msgDestinations.add(new SunMessageDestination(adminObj.getJndiName(), MessageDestination.Type.TOPIC, resourcesDir));
                }
            }
        }
        return msgDestinations;
    }

    public static MessageDestination createMessageDestination(String name, MessageDestination.Type type, File resourceDir, String baseName) throws ConfigurationException {
        SunMessageDestination msgDest;
        if(! name.startsWith(JMS_PREFIX)){
            name = JMS_PREFIX + name;
        }

        DuplicateAOFinder aoFinder = new DuplicateAOFinder(name);
        DuplicateConnectorFinder connFinder = new DuplicateConnectorFinder(name);
        ConnectorPoolFinder cpFinder = new ConnectorPoolFinder();

        File xmlFile = new File(resourceDir, baseName+".xml");
        if(xmlFile.exists()) {
            List<TreeParser.Path> pathList = new ArrayList<TreeParser.Path>();
            pathList.add(new TreeParser.Path("/resources/admin-object-resource", aoFinder));
            pathList.add(new TreeParser.Path("/resources/connector-resource", connFinder));
            pathList.add(new TreeParser.Path("/resources/connector-connection-pool", cpFinder));
            TreeParser.readXml(xmlFile, pathList);
            if(connFinder.isDuplicate()) {
               throw new ConfigurationException("Resource already exists");
            }
        }

        String connectionFactoryJndiName= name + "Factory"; // NOI18N
        String connectionFactoryPoolName = name + "FactoryPool"; // NOI18N
        try {
            createAdminObject(xmlFile, name, type);
            createConnectorConnectionPool(xmlFile, connectionFactoryPoolName, type);
            createConnector(xmlFile, connectionFactoryJndiName, connectionFactoryPoolName);
        } catch (IOException ex) {
            Logger.getLogger("payara-jakartaee").log(Level.WARNING, ex.getLocalizedMessage(), ex); // NOI18N
            throw new ConfigurationException(ex.getLocalizedMessage(), ex);
        }


        msgDest = new SunMessageDestination(name, type, resourceDir);
        return msgDest;

    }

    private static final String ATTR_JNDINAME = "jndi-name";
    private static final String ATTR_POOLNAME = "pool-name";
    private static final String ATTR_POOL_NAME = "name";
    
    private static final String AO_TAG_1 =
            "    <admin-object-resource enabled=\"true\" ";
    private static final String ATTR_RESTYPE =
            " res-type";
    private static final String AO_TAG_2 =
            " res-adapter=\"jmsra\">\n";
    private static final String PROP_NAME =
            "Name";
    private static final String AO_TAG_3 =
            "    </admin-object-resource>\n";
    public static void createAdminObject(File sunResourcesXml, String jndiName, Type type) throws IOException {
        // <admin-object-resource res-adapter="jmsra" res-type="javax.jms.Queue" jndi-name="testao"></admin-object-resource>
        StringBuilder xmlBuilder = new StringBuilder(500);
        xmlBuilder.append(AO_TAG_1);
        ResourceModifier.appendAttr(xmlBuilder, ATTR_JNDINAME, jndiName, false);
        if (MessageDestination.Type.QUEUE.equals(type)) {
            ResourceModifier.appendAttr(xmlBuilder, ATTR_RESTYPE, QUEUE, true);
            xmlBuilder.append(AO_TAG_2);
            ResourceModifier.appendProperty(xmlBuilder, PROP_NAME, QUEUE_PROP, true);
        } else if (MessageDestination.Type.TOPIC.equals(type)) {
            ResourceModifier.appendAttr(xmlBuilder, ATTR_RESTYPE, TOPIC, true);
            xmlBuilder.append(AO_TAG_2);
            ResourceModifier.appendProperty(xmlBuilder, PROP_NAME, TOPIC_PROP, true);
        }
        xmlBuilder.append(AO_TAG_3);
        String xmlFragment = xmlBuilder.toString();
        Logger.getLogger("payara-jakartaee").log(Level.FINER, "New Connector resource:\n" + xmlFragment);
        ResourceModifier.appendResource(sunResourcesXml, xmlFragment);
    }

    private static final String CONNECTOR_POOL_TAG_1 =
            "    <connector-connection-pool ";
    private static final String ATTR_CONN_DEFINITION =
            " connection-definition-name";
    private static final String CONNECTOR_POOL_TAG_2 =
            " resource-adapter-name=\"jmsra\"/>\n";
    public static void createConnectorConnectionPool(File sunResourcesXml, String poolName, Type type) throws IOException {
        //<connector-connection-pool name="testconnectorpool" resource-adapter-name="jmsra" connectiondefinition="javax.jms.ConnectionFactory"/>
        StringBuilder xmlBuilder = new StringBuilder(500);
        xmlBuilder.append(CONNECTOR_POOL_TAG_1);
        ResourceModifier.appendAttr(xmlBuilder, ATTR_POOL_NAME, poolName, true);
        if(type.equals(MessageDestination.Type.QUEUE)) {
            ResourceModifier.appendAttr(xmlBuilder, ATTR_CONN_DEFINITION, QUEUE_CNTN_FACTORY, true);
        } else if (type.equals(MessageDestination.Type.TOPIC)) {
            ResourceModifier.appendAttr(xmlBuilder, ATTR_CONN_DEFINITION, TOPIC_CNTN_FACTORY, true);
        }
        xmlBuilder.append(CONNECTOR_POOL_TAG_2);

        String xmlFragment = xmlBuilder.toString();
        Logger.getLogger("payara-jakartaee").log(Level.FINER, "New Connector Connection Pool resource:\n" + xmlFragment);
        ResourceModifier.appendResource(sunResourcesXml, xmlFragment);
    }

    private static final String CONNECTOR_TAG_1 =
            "    <connector-resource enabled=\"true\" ";
    private static final String CONNECTOR_TAG_2 =
            " />\n";
    public static void createConnector(File sunResourcesXml, String jndiName, String poolName) throws IOException {
        // <connector-resource pool-name="testconnectorpool" jndi-name="testconnector" />
        StringBuilder xmlBuilder = new StringBuilder(500);
        xmlBuilder.append(CONNECTOR_TAG_1);
        ResourceModifier.appendAttr(xmlBuilder, ATTR_JNDINAME, jndiName, true);
        ResourceModifier.appendAttr(xmlBuilder, ATTR_POOLNAME, poolName, true);
        xmlBuilder.append(CONNECTOR_TAG_2);

        String xmlFragment = xmlBuilder.toString();
        Logger.getLogger("payara-jakartaee").log(Level.FINER, "New Connector resource:\n" + xmlFragment);
        ResourceModifier.appendResource(sunResourcesXml, xmlFragment);
    }
    
    private static class AdminObjectReader extends TreeParser.NodeReader {

        private final Map<String, AdminObjectResource> resourceMap;

        public AdminObjectReader(Map<String, AdminObjectResource> resourceMap) {
            this.resourceMap = resourceMap;
        }

        //<admin-object-resource
            //enabled="true"
            //jndi-name="jms/testQ"
            //res-type="javax.jms.Queue"
            //res-adapter="jmsra"
           //</admin-object-resource>
        @Override
        public void readAttributes(String qname, Attributes attributes) throws SAXException {
            String type = attributes.getValue("object-type");

            // Ignore system resources
            if(type != null && type.startsWith("system-")) {
                return;
            }
            String jndiName = attributes.getValue("jndi-name");
            String resType = attributes.getValue("res-type");
            String resadapter = attributes.getValue("res-adapter");
            if(jndiName != null && jndiName.length() > 0 &&
                    resType != null && resType.length() > 0) {
                // add to admin object resource list
                resourceMap.put(jndiName,
                        new AdminObjectResource(jndiName, resType, resadapter));
            }
        }
    }
    
    private static class AdminObjectResource {

        private final String jndiName;
        private final String resType;
        private final String resAdapter;

        public AdminObjectResource(String jndiName, String resType, String resAdapter) {
            this.jndiName = jndiName;
            this.resType = resType;
            this.resAdapter = resAdapter;
        }

        public String getJndiName() {
            return jndiName;
        }

        public String getResType() {
            return resType;
        }

        public String getResAdapter() {
            return resAdapter;
        }
    }

    private static class DuplicateAOFinder extends TreeParser.NodeReader {

        private final String targetJndiName;
        private boolean duplicate;
        private String resType;

        public DuplicateAOFinder(String jndiName) {
            targetJndiName = jndiName;
            duplicate = false;
            resType = null;
        }

        @Override
        public void readAttributes(String qname, Attributes attributes) throws SAXException {
            String jndiName = attributes.getValue("jndi-name");
            if(targetJndiName.equals(jndiName)) {
                if(duplicate) {
                    Logger.getLogger("payara-jakartaee").log(Level.WARNING,
                            "Duplicate jndi-names defined for Admin Object resources.");
                }
                duplicate = true;
                resType = attributes.getValue("res-type");
            }
        }

        public boolean isDuplicate() {
            return duplicate;
        }

        public String getResType() {
            return resType;
        }
    }

    private static class DuplicateConnectorFinder extends TreeParser.NodeReader {

        private final String targetJndiName;
        private boolean duplicate;
        private String poolName;

        public DuplicateConnectorFinder(String jndiName) {
            targetJndiName = jndiName;
            duplicate = false;
            poolName = null;
        }

        @Override
        public void readAttributes(String qname, Attributes attributes) throws SAXException {
            String jndiName = attributes.getValue("jndi-name");
            if(targetJndiName.equals(jndiName)) {
                if(duplicate) {
                    Logger.getLogger("payara-jakartaee").log(Level.WARNING,
                            "Duplicate jndi-names defined for Connector resources.");
                }
                duplicate = true;
                poolName = attributes.getValue("pool-name");
            }
        }

        public boolean isDuplicate() {
            return duplicate;
        }

        public String getPoolName() {
            return poolName;
        }
    }

    private static class ConnectorPoolFinder extends TreeParser.NodeReader {

        private Map<String, String> properties = null;
        private Map<String, ConnectorPool> pools = new HashMap<String, ConnectorPool>();

        @Override
        public void readAttributes(String qname, Attributes attributes) throws SAXException {
            properties = new HashMap<String, String>();
            String poolName = attributes.getValue("name"); // NOI18N
            if(poolName != null && poolName.length() > 0) {
                if(!pools.containsKey(poolName)) {
                    properties.put("name", poolName); // NOI18N
                    properties.put("raname", attributes.getValue("resource-adapter-name")); // NOI18N
                    properties.put("conndefname", attributes.getValue("connection-definition-name")); // NOI18N
                } else {
                    Logger.getLogger("payara-jakartaee").log(Level.WARNING, // NOI18N
                            "Duplicate pool-names defined for Resource Adapter Pools: "+poolName); // NOI18N
                }
            }
        }

        @Override
        public void readChildren(String qname, Attributes attributes) throws SAXException {
            if (null != attributes && null != properties) {
                String key = attributes.getValue("name"); // NOI18N
                if(key != null && key.length() > 0) {
                    properties.put(key.toLowerCase(Locale.ENGLISH), attributes.getValue("value")); // NOI18N
                }
            }
        }

        @Override
        public void endNode(String qname) throws SAXException {
            String poolName = properties.get("name");
            ConnectorPool pool = new ConnectorPool(
                    poolName,
                    properties.get("raname"),
                    properties.get("conndefname")
                    );
            pools.put(poolName, pool);
        }

        public List<String> getPoolNames() {
            return new ArrayList<String>(pools.keySet());
        }

        public Map<String, ConnectorPool> getPoolData() {
            return Collections.unmodifiableMap(pools);
        }

    }

    private static class ConnectorPool {

        private final String poolName;
        private final String raName;
        private final String conndefName;

        public ConnectorPool(String poolName, String raname, String conndefname) {
            this.poolName = poolName;
            this.raName = raname;
            this.conndefName = conndefname;
        }

        public String getPoolName() {
            return poolName;
        }

        public String getRaName() {
            return raName;
        }

        public String getConndefName() {
            return conndefName;
        }
    }
}
