/*
 * 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.javaee.wildfly.config;

import java.io.BufferedOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.OutputStream;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.Map;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.netbeans.modules.j2ee.deployment.common.api.ConfigurationException;
import org.netbeans.modules.j2ee.deployment.common.api.Datasource;
import org.netbeans.modules.j2ee.deployment.common.api.DatasourceAlreadyExistsException;
import org.netbeans.modules.j2ee.deployment.plugins.api.InstanceProperties;
import org.netbeans.modules.j2ee.deployment.plugins.spi.DatasourceManager;
import org.netbeans.modules.javaee.wildfly.WildflyDeploymentManager;
import org.netbeans.modules.javaee.wildfly.config.ds.gen.DatasourceType;
import org.netbeans.modules.javaee.wildfly.config.ds.gen.Datasources;
import org.netbeans.modules.javaee.wildfly.config.ds.gen.DsSecurityType;
import org.netbeans.modules.javaee.wildfly.config.ds.gen.PoolType;
import org.netbeans.modules.javaee.wildfly.config.xml.ConfigurationParser;
import org.netbeans.modules.javaee.wildfly.ide.ui.WildflyPluginProperties;
import org.netbeans.modules.schema2beans.BaseBean;
import org.openide.filesystems.FileLock;
import org.openide.filesystems.FileObject;
import org.openide.filesystems.FileSystem;
import org.openide.filesystems.FileUtil;
import org.openide.util.Exceptions;
import org.openide.util.NbBundle;

/**
 *
 * @author Libor Kotouc
 * @author Emmanuel Hugonnet (ehsavoie) <ehsavoie@netbeans.org>
 */
public final class WildflyDatasourceManager implements DatasourceManager {

    private static final Logger LOGGER = Logger.getLogger(WildflyDatasourceManager.class.getName());

    private static final String DSdotXML = "-ds.xml"; // NOI18N

    private static final String JBossDSdotXML = "jboss-ds.xml"; // NOI18N

    private final FileObject deployDir;
    private final FileObject configFile;

    private final WildflyDeploymentManager dm;

    public WildflyDatasourceManager(WildflyDeploymentManager dm) {
        this.dm = dm;
        InstanceProperties ip = InstanceProperties.getInstanceProperties(dm.getUrl());
        String deployDirPath = ip.getProperty(WildflyPluginProperties.PROPERTY_DEPLOY_DIR);
        deployDir = FileUtil.toFileObject(new File(deployDirPath));
        String configFilePath = ip.getProperty(WildflyPluginProperties.PROPERTY_CONFIG_FILE);
        if(configFilePath != null) {
            File config = new File(configFilePath);
            if(config.exists()) {
                configFile = FileUtil.toFileObject(config);
            } else {
                throw new IllegalArgumentException("No configuration file found: " + configFilePath);
            }
        } else {
            throw new IllegalArgumentException("No configuration file configured: " + dm);
        }
    }

    @Override
    public Set<Datasource> getDatasources() throws ConfigurationException {
        return ConfigurationParser.INSTANCE.listDatasources(configFile);
    }

    @Override
    public void deployDatasources(Set<Datasource> datasources)
            throws ConfigurationException, DatasourceAlreadyExistsException {
        Set<Datasource> deployedDS = getDatasources();
        Map<String, Datasource> ddsMap = transform(deployedDS); // for faster searching

        HashMap<String, Datasource> newDS = new HashMap<String, Datasource>(); // will contain all ds which do not conflict with existing ones

        //resolve all conflicts
        LinkedList<Datasource> conflictDS = new LinkedList<Datasource>();
        for (Iterator<Datasource> it = datasources.iterator(); it.hasNext();) {
            Object o = it.next();
            if (!(o instanceof WildflyDatasource)) {
                continue;
            }
            WildflyDatasource ds = (WildflyDatasource) o;
            String jndiName = WildflyDatasource.getRawName(ds.getJndiName());
            if (ddsMap.keySet().contains(jndiName)) { // conflicting ds found
                if (!ddsMap.get(jndiName).equals(ds)) { // found ds is not equal
                    conflictDS.add(ddsMap.get(jndiName)); // NOI18N
                }
            } else if (jndiName != null) {
                newDS.put(jndiName, ds);
            }
        }

        if (conflictDS.size() > 0) { // conflict found -> exception
            throw new DatasourceAlreadyExistsException(conflictDS);
        }

        //write jboss-ds.xml
        FileObject dsXmlFo = deployDir.getFileObject(JBossDSdotXML);
        File dsXMLFile = (dsXmlFo != null ? FileUtil.toFile(dsXmlFo) : null);

        Datasources deployedDSGraph = null;
        try {
            deployedDSGraph = (dsXMLFile != null ? Datasources.createGraph(dsXMLFile) : new Datasources());
        } catch (IOException ioe) {
            Exceptions.attachLocalizedMessage(ioe, NbBundle.getMessage(getClass(), "ERR_CannotReadDSdotXml"));
            Logger.getLogger("global").log(Level.INFO, null, ioe);
            return;
        }

        //merge ds graph with newDS - remove conflicting ds from graph
        DatasourceType ltxds[] = deployedDSGraph.getDatasource();
        for (int i = 0; i < ltxds.length; i++) {
            String jndiName = ltxds[i].getJndiName();
            if (newDS.keySet().contains(jndiName)) //conflict, we must remove it from graph
            {
                deployedDSGraph.removeDatasource(ltxds[i]);
            }
        }

        //add all ds from newDS
        for (Iterator it = newDS.values().iterator(); it.hasNext();) {
            WildflyDatasource ds = (WildflyDatasource) it.next();

            DatasourceType lds = new DatasourceType();
            lds.setJndiName(WildflyDatasource.getRawName(ds.getJndiName()));
            lds.setConnectionUrl(ds.getUrl());
            lds.setDriverClass(ds.getDriverClassName());
            DsSecurityType security = new DsSecurityType();
            security.setUserName(ds.getUsername());
            security.setPassword(ds.getPassword());
            lds.setSecurity(security);
            PoolType pool = new PoolType();
            pool.setMinPoolSize(Long.parseLong(ds.getMinPoolSize()));
            pool.setMaxPoolSize(Long.parseLong(ds.getMaxPoolSize()));
            lds.setPool(pool);
            String poolName = ds.getJndiName();
            int index = ds.getJndiName().lastIndexOf('/');
            if(index > 0) {
                poolName = ds.getJndiName().substring(index);
            }
            lds.setPoolName(poolName);
            deployedDSGraph.addDatasource(lds);
        }

        //write modified graph into jboss-ds.xml
        if (newDS.size() > 0) {
            if (dsXMLFile == null) {
                try {
                    dsXmlFo = deployDir.createData(JBossDSdotXML);
                } catch (IOException ioe) {
                    Exceptions.attachLocalizedMessage(ioe, NbBundle.getMessage(getClass(), "ERR_CannotCreateDSdotXml"));
                    Logger.getLogger("global").log(Level.INFO, null, ioe);
                    return;
                }

                dsXMLFile = FileUtil.toFile(dsXmlFo);
            }

            writeFile(dsXMLFile, deployedDSGraph);
        }
    }

    private Map<String, Datasource> transform(Set<Datasource> datasources) {
        HashMap<String, Datasource> map = new HashMap<String, Datasource>();
        for (Iterator it = datasources.iterator(); it.hasNext();) {
            WildflyDatasource ds = (WildflyDatasource) it.next();
            if (ds.getJndiName() != null) {
                map.put(ds.getJndiName(), ds);
            }
        }
        return map;
    }

    private void writeFile(final File file, final BaseBean bean) throws ConfigurationException {
        try {

            FileSystem fs = deployDir.getFileSystem();
            fs.runAtomicAction(new FileSystem.AtomicAction() {
                public void run() throws IOException {
                    OutputStream os = null;
                    FileLock lock = null;
                    try {
                        String name = file.getName();
                        FileObject configFO = deployDir.getFileObject(name);
                        if (configFO == null) {
                            configFO = deployDir.createData(name);
                        }
                        lock = configFO.lock();
                        os = new BufferedOutputStream(configFO.getOutputStream(lock), 4096);
                        // TODO notification needed
                        if (bean != null) {
                            bean.write(os);
                        }
                    } finally {
                        if (os != null) {
                            try {
                                os.close();
                            } catch (IOException ioe) {
                            }
                        }
                        if (lock != null) {
                            lock.releaseLock();
                        }
                    }
                }
            });
        } catch (IOException e) {
            throw new ConfigurationException(e.getLocalizedMessage());
        }
    }

}
