/*
 * 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.slf4j.Logger;
import org.slf4j.LoggerFactory;
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 Logger __log = LoggerFactory.getLogger(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;
    }
}
