/*
 * 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.apache.ode.store;

import java.io.File;
import java.io.FileFilter;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URI;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;

import javax.wsdl.Definition;
import javax.wsdl.WSDLException;
import javax.wsdl.xml.WSDLReader;
import javax.xml.namespace.QName;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.ode.bpel.compiler.BpelC;
import org.apache.ode.bpel.compiler.BpelCompiler;
import org.apache.ode.bpel.compiler.DefaultResourceFinder;
import org.apache.ode.bpel.compiler.WSDLLocatorImpl;
import org.apache.ode.bpel.compiler.wsdl.Definition4BPEL;
import org.apache.ode.bpel.compiler.wsdl.WSDLFactory4BPEL;
import org.apache.ode.bpel.compiler.wsdl.WSDLFactoryBPEL20;
import org.apache.ode.bpel.dd.DeployDocument;
import org.apache.ode.bpel.dd.TDeployment;
import org.apache.ode.bpel.dd.TDeployment.Process;
import org.apache.ode.bpel.iapi.ContextException;
import org.apache.ode.bpel.obj.OProcess;
import org.apache.ode.bpel.obj.serde.DeSerializer;
import org.apache.ode.bpel.obj.serde.OmDeserializer;
import org.apache.ode.bpel.obj.serde.OmSerdeFactory;
import org.apache.ode.utils.InternPool;
import org.apache.ode.utils.InternPool.InternableBlock;
import org.apache.ode.utils.fs.FileUtils;
import org.apache.xmlbeans.XmlOptions;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.w3c.dom.Node;

/**
 * Container providing various functions on the deployment directory.
 *
 * @author mriou
 * @author Maciej Szefler <mszefler at gmail dot com>
 */
class DeploymentUnitDir {


    private static Log __log = LogFactory.getLog(DeploymentUnitDir.class);

    private String _name;
    private File _duDirectory;
    private File _descriptorFile;
    private Properties _properties = new Properties();

    private HashMap<QName, CBPInfo> _processes = new HashMap<QName, CBPInfo>();
    private HashMap<QName, TDeployment.Process> _processInfo = new HashMap<QName, TDeployment.Process>();

    private volatile DeployDocument _dd;
    private volatile DocumentRegistry _docRegistry;

    private long _version = -1;

    private static final FileFilter _wsdlFilter = new FileFilter() {
        public boolean accept(File path) {
            return path.getName().endsWith(".wsdl") && path.isFile();
        }
    };

    private static final FileFilter _cbpFilter = new FileFilter() {
        public boolean accept(File path) {
            return path.getName().endsWith(".cbp") && path.isFile();
        }
    };

    private static final FileFilter _bpelFilter = new FileFilter() {
        public boolean accept(File path) {
            return path.getName().endsWith(".bpel") && path.isFile();
        }
    };

    private static final FileFilter _endpointFilter = new FileFilter() {
        public boolean accept(File path) {
            // endpoint-configuration.properties is deprecated, keep it for backward compatibility
            return (path.getName().endsWith(".endpoint") || path.getName().equals("endpoint-configuration.properties")) && path.isFile();
        }
    };

    DeploymentUnitDir(File dir) {
        if (!dir.exists())
            throw new IllegalArgumentException("Directory " + dir + " does not exist!");

        _duDirectory = dir;
        _name = dir.getName();
        _descriptorFile = new File(_duDirectory, "deploy.xml");

        if (!_descriptorFile.exists())
            throw new IllegalArgumentException("Directory " + dir + " does not contain a deploy.xml file!");

        try {
            ApplicationContext ctx = new ClassPathXmlApplicationContext("beans.xml");
            _properties = (java.util.Properties) ctx.getBean("properties");
            if (__log.isDebugEnabled()) {
                __log.debug("Loaded spring properties from file beans.xml:" + _properties + " for " +  _name);
            }
        } catch (Exception e) {
            __log.info("Can't initialize beans.xml application context " + e + " for " + _name);
        }

    }


    String getName() {
        return _duDirectory.getName();
    }

    void setName(String name) {
        // supports extensibility
        _name = name;
    }

    CBPInfo getCBPInfo(QName typeName) {
        return _processes.get(typeName);
    }


    /**
     * Checking for each BPEL file if we have a corresponding compiled process. If we don't,
     * starts compilation.
     */
    void compile() {
        List<File> bpels = FileUtils.directoryEntriesInPath(_duDirectory, DeploymentUnitDir._bpelFilter);
        if (bpels.size() == 0)
            throw new IllegalArgumentException("Directory " + _duDirectory.getName() + " does not contain any process!");
        for (File bpel : bpels) {
            String b = bpel.getAbsolutePath();
            File cbp = new File(b.substring(0,b.lastIndexOf(".bpel")) + ".cbp");
            if (!cbp.exists() || cbp.lastModified() < bpel.lastModified()) {
                __log.debug("compiling " + bpel);
                compile(bpel);
            } else {
                __log.debug("skipping compilation of " + bpel + " cbp found: " + cbp);
            }
        }
    }

    void scan() {
        HashMap<QName, CBPInfo> processes = new HashMap<QName, CBPInfo>();
        List<File> cbps = FileUtils.directoryEntriesInPath(_duDirectory, DeploymentUnitDir._cbpFilter);
        for (File file : cbps) {
            CBPInfo cbpinfo = loadCBPInfo(file);
            processes.put(cbpinfo.processName, cbpinfo);
        }
        _processes = processes;

        HashMap<QName, Process> processInfo = new HashMap<QName, TDeployment.Process>();
        for (TDeployment.Process p : getDeploymentDescriptor().getDeploy().getProcessArray()) {
            processInfo.put(p.getName(), p);
        }
        _processInfo = processInfo;

    }

    boolean isRemoved() {
        return !_duDirectory.exists();
    }

    private void compile(final File bpelFile) {
        final BpelC bpelc = BpelC.newBpelCompiler();

        // BPEL 1.1 does not suport the <import> element, so "global" WSDL needs to be configured explicitly.
        File bpel11wsdl = findBpel11Wsdl(bpelFile);
        if (bpel11wsdl != null)
            bpelc.setProcessWSDL(bpel11wsdl.toURI());

        bpelc.setCompileProperties(prepareCompileProperties(bpelFile));
        bpelc.setBaseDirectory(_duDirectory);
        // Create process such that immutable objects are intern'ed.
        InternPool.runBlock(new InternableBlock() {
            public void run() {
                try {
                    bpelc.compile(bpelFile, getVersion());
                } catch (IOException e) {
                    __log.error("Compile error in " + bpelFile, e);
                }
            }
        });
    }

    /**
     * Load the parsed and compiled BPEL process definition.
     */
    private CBPInfo loadCBPInfo(File f) {
        InputStream is = null;
        try {
            DeSerializer deserializer = new DeSerializer(f);
            CBPInfo info = new CBPInfo(deserializer.getWrapper().getType(),deserializer.getWrapper().getGuid(), f);
            return info;
        } catch (Exception e) {
            throw new ContextException("Couldn't read compiled BPEL process " + f.getAbsolutePath(), e);
        } finally {
            try {
                if (is != null)
                    is.close();
            } catch (Exception e) {
                ;
            }
        }
    }


    public int hashCode() {
        return _duDirectory.hashCode();
    }

    public boolean equals(Object obj) {
        if (!(obj instanceof DeploymentUnitDir)) return false;
        return ((DeploymentUnitDir) obj).getDeployDir().getAbsolutePath().equals(getDeployDir().getAbsolutePath());
    }

    public File getDeployDir() {
        return _duDirectory;
    }

    /**
     *
     * The list of endpoint configuration files contained in the deployment directory and its subdirectories.
     * Files are ordered lexicographically but for each directory, files come before its sudirectories.
     * <p>The list is built on each call to handle changes.
     * @see org.apache.ode.utils.fs.FileUtils#directoryEntriesInPath(java.io.File)
     */
    public List<File> getEndpointConfigFiles() {
        return FileUtils.directoryEntriesInPath(getDeployDir(),_endpointFilter);
    }

    public DeployDocument getDeploymentDescriptor() {
        if (_dd == null) {
            File ddLocation = new File(_duDirectory, "deploy.xml");
            try {
                XmlOptions options = new XmlOptions();
                HashMap otherNs = new HashMap();

                otherNs.put("http://ode.fivesight.com/schemas/2006/06/27/dd",
                        "http://www.apache.org/ode/schemas/dd/2007/03");
                options.setLoadSubstituteNamespaces(otherNs);
                _dd = DeployDocument.Factory.parse(ddLocation, options);
            } catch (Exception e) {
                throw new ContextException("Couldn't read deployment descriptor at location "
                        + ddLocation.getAbsolutePath(), e);
            }

        }
        return _dd;
    }

    public DocumentRegistry getDocRegistry() {
        if (_docRegistry == null) {
            _docRegistry = new DocumentRegistry();

            WSDLFactory4BPEL wsdlFactory = (WSDLFactory4BPEL) WSDLFactoryBPEL20.newInstance();
            WSDLReader r = wsdlFactory.newWSDLReader();
            DefaultResourceFinder rf = new DefaultResourceFinder(_duDirectory, _duDirectory);
            URI basedir = _duDirectory.toURI();
            List<File> wsdls = FileUtils.directoryEntriesInPath(_duDirectory, DeploymentUnitDir._wsdlFilter);
            for (File file : wsdls) {
                URI uri = basedir.relativize(file.toURI());
                try {
                    _docRegistry.addDefinition((Definition4BPEL) r.readWSDL(new WSDLLocatorImpl(rf, uri)));
                } catch (WSDLException e) {
                    throw new ContextException("Couldn't read WSDL document at " + uri, e);
                }
            }
        }
        return _docRegistry;
    }

    public Definition getDefinitionForService(QName name) {
        return getDocRegistry().getDefinition(name);
    }

    public Definition getDefinitionForPortType(QName name) {
        return getDocRegistry().getDefinitionForPortType(name);
    }

    public Collection<Definition> getDefinitions() {
        Definition4BPEL defs[] = getDocRegistry().getDefinitions();
        ArrayList<Definition> ret = new ArrayList<Definition>(defs.length);
        for (Definition4BPEL def : defs)
            ret.add(def);
        return ret;
    }

    public Set<QName> getProcessNames() {
        return _processInfo.keySet();
    }

    public String toString() {
        return "{DeploymentUnit " + _name + "}";
    }

    public TDeployment.Process getProcessDeployInfo(QName type) {
        if (_processInfo == null) {
        }

        return _processInfo.get(type);
    }

    public List<File> allFiles() {
        return allFiles(_duDirectory);
    }

    private List<File> allFiles(File dir) {
        ArrayList<File> result = new ArrayList<File>();
        for (File file : dir.listFiles()) {
            if (file.isDirectory()) {
                result.addAll(allFiles(file));
            }
            if (file.isHidden()) continue;
            if (file.isFile()) {
                result.add(file);
            }
        }
        return result;
    }

    public final class CBPInfo {
        final QName processName;
        final String guid;
        final File cbp;

        CBPInfo(QName processName, String guid, File cbp) {
            this.processName = processName;
            this.guid = guid;
            this.cbp = cbp;
        }
    }

    private Map<String, Object> prepareCompileProperties(File bpelFile) {
        for (Process process : getDeploymentDescriptor().getDeploy().getProcessArray()) {
            if (process.getFileName() == null || "".equals(process.getFileName()))
                continue;

            if (bpelFile.getName().equals(process.getFileName())) {
                Map<QName, Node> props = ProcessStoreImpl.calcInitialProperties(_properties, process);
                Map<String, Object> result = new HashMap<String, Object>();
                result.put(BpelC.PROCESS_CUSTOM_PROPERTIES, props);
                return result;
            }
        }
        return null;
    }


    /**
     * Figure out the name of the WSDL file for a BPEL 1.1 process.
     *
     * @param bpelFile BPEL process file name
     * @return file name of the WSDL, or null if none specified.
     */
    private File findBpel11Wsdl(File bpelFile) {
        for (Process process : getDeploymentDescriptor().getDeploy().getProcessArray()) {
            if (process.getFileName() == null || "".equals(process.getFileName()))
                continue;
            if (!bpelFile.getName().equals(process.getFileName()))
                continue;
            if (process.getBpel11WsdlFileName() == null || "".equals(process.getBpel11WsdlFileName()))
                return null;

            return new File(bpelFile.getParentFile(), process.getBpel11WsdlFileName());
        }
        return null;
    }

    public long getVersion() {
        return _version;
    }

    /**
     * @return Static DU version number generated from DU name. -1 when package doesn't use versioning.
     */
    public long getStaticVersion() {
        String name = getName();
        int p = name.indexOf(File.separator);
        if (p != -1) {
            name = name.substring(0, p);
        }
        return BpelCompiler.getVersion(name);
    }

    public void setVersion(long version) {
        _version = version;
    }

    public Properties getProperties() {
        return _properties;
    }
}
