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

import org.apache.openejb.NoSuchApplicationException;
import org.apache.openejb.OpenEJBException;
import org.apache.openejb.OpenEJBRuntimeException;
import org.apache.openejb.UndeployException;
import org.apache.openejb.assembler.Deployer;
import org.apache.openejb.assembler.classic.AppInfo;
import org.apache.openejb.assembler.classic.ClientInfo;
import org.apache.openejb.assembler.classic.ConnectorInfo;
import org.apache.openejb.assembler.classic.EjbJarInfo;
import org.apache.openejb.assembler.classic.InfoObject;
import org.apache.openejb.assembler.classic.WebAppInfo;
import org.apache.openejb.loader.IO;

import javax.enterprise.deploy.model.DeployableObject;
import javax.enterprise.deploy.shared.ActionType;
import javax.enterprise.deploy.shared.CommandType;
import javax.enterprise.deploy.shared.DConfigBeanVersionType;
import javax.enterprise.deploy.shared.ModuleType;
import javax.enterprise.deploy.shared.StateType;
import javax.enterprise.deploy.spi.DeploymentConfiguration;
import javax.enterprise.deploy.spi.DeploymentManager;
import javax.enterprise.deploy.spi.Target;
import javax.enterprise.deploy.spi.TargetModuleID;
import javax.enterprise.deploy.spi.exceptions.DConfigBeanVersionUnsupportedException;
import javax.enterprise.deploy.spi.exceptions.InvalidModuleException;
import javax.enterprise.deploy.spi.exceptions.OperationUnsupportedException;
import javax.enterprise.deploy.spi.exceptions.TargetException;
import javax.enterprise.deploy.spi.status.ClientConfiguration;
import javax.enterprise.deploy.spi.status.DeploymentStatus;
import javax.enterprise.deploy.spi.status.ProgressEvent;
import javax.enterprise.deploy.spi.status.ProgressListener;
import javax.enterprise.deploy.spi.status.ProgressObject;
import javax.naming.InitialContext;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintStream;
import java.io.PrintWriter;
import java.io.Serializable;
import java.io.StringWriter;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Locale;
import java.util.Properties;
import java.util.Set;
import java.util.TreeSet;

import static org.apache.openejb.loader.IO.close;

public class VmDeploymentManager implements DeploymentManager {
    private static final Target DEFAULT_TARGET = new TargetImpl("DefaultTarget", "OpenEJB Default Target");
    private static final DConfigBeanVersionType DCONFIG_BEAN_VERSION = DConfigBeanVersionType.V1_4;
    private static final Locale LOCALE = Locale.getDefault();

    private boolean connected = true;
    private Deployer deployer;
    private final String openejbUri;
    private boolean deployerLocal;

    public VmDeploymentManager() {
        String openejbHome = System.getProperty("openejb.home");
        File openejbHomeDir = new File(openejbHome);
        if (!openejbHomeDir.exists()) {
            throw new IllegalArgumentException("OpenEJB home dir does not exist: " + openejbHomeDir);
        }
        if (!openejbHomeDir.isDirectory()) {
            throw new IllegalArgumentException("OpenEJB home dir is not a directory: " + openejbHomeDir);
        }

        String openejbUri = System.getProperty("openejb.server.uri");
        if (openejbUri == null) {
            try {
                openejbUri = new URI("ejbd", null, "localhost", 4201, null, null, null).toString();
            } catch (URISyntaxException e) {
                throw new OpenEJBRuntimeException(e);
            }
        }
        this.openejbUri = openejbUri;

    }

    private Deployer getDeployer() {
    	String deployerJndi = System.getProperty("openejb.deployer.jndiname", "openejb/DeployerBusinessRemote");
    	
        if (deployer == null) {
            try {
                Properties p = new Properties();
                p.put("java.naming.factory.initial", "org.apache.openejb.client.RemoteInitialContextFactory");
                p.put("java.naming.provider.url", openejbUri);

                InitialContext ctx = new InitialContext(p);
                deployer = (Deployer) ctx.lookup(deployerJndi);
            } catch (Exception e) {
                throw new OpenEJBRuntimeException(e);
            }
        }
        return deployer;
    }

    private boolean isDeployerLocal() {
        if (deployer == null) {
            deployerLocal = new File(getDeployer().getUniqueFile()).exists();            
        }
        return deployerLocal;
    }

    @Override
    public void release() {
        connected = false;
    }

    @Override
    public Target[] getTargets() {
        if (!connected) throw new IllegalStateException("Deployment manager is disconnected");

        return new Target[]{DEFAULT_TARGET};
    }


    @Override
    public TargetModuleID[] getAvailableModules(ModuleType moduleType, Target[] targetList) throws TargetException {
        if (!connected) throw new IllegalStateException("Deployment manager is disconnected");

        if (!containsDefaultTarget(targetList)) {
            return null;
        }

        Set<TargetModuleID> targetModuleIds = toTargetModuleIds(getDeployer().getDeployedApps(), moduleType);
        return targetModuleIds.toArray(new TargetModuleID[targetModuleIds.size()]);
    }

    private static Set<TargetModuleID> toTargetModuleIds(Collection<AppInfo> deployedApps, ModuleType allowedModuleType) {
        Set<TargetModuleID> targetModuleIds = new HashSet<TargetModuleID>(deployedApps.size());
        for (AppInfo deployedApp : deployedApps) {
            TargetModuleID moduleId = toTargetModuleId(deployedApp, allowedModuleType);
            // moduleID will be null if the module was filtered
            if (moduleId != null) {
                targetModuleIds.add(moduleId);
            }
        }
        return targetModuleIds;
    }

    private static TargetModuleID toTargetModuleId(AppInfo appInfo, ModuleType allowedModuleType) {
        List<InfoObject> infos = new ArrayList<InfoObject>();
        infos.addAll(appInfo.clients);
        infos.addAll(appInfo.ejbJars);
        infos.addAll(appInfo.webApps);
        infos.addAll(appInfo.connectors);

        // if the module id is the same as the appInfo, then it is a standalone module
        if (infos.size() == 1) {
            InfoObject infoObject = infos.get(0);
            if (infoObject instanceof ClientInfo) {
                ClientInfo clientInfo = (ClientInfo) infoObject;
                if (null != appInfo.path && appInfo.path.equals(clientInfo.path)) {
                    // are client modules allowed
                    if (allowedModuleType != null && !allowedModuleType.equals(ModuleType.CAR)) {
                        return null;
                    }
                    if (null != clientInfo.moduleId && clientInfo.moduleId.equals(appInfo.path)) {
                        return new TargetModuleIDImpl(DEFAULT_TARGET, clientInfo.moduleId);
                    }
                }
            }
            if (infoObject instanceof EjbJarInfo) {
                EjbJarInfo ejbJarInfo = (EjbJarInfo) infoObject;
                if (null != appInfo.path && appInfo.path.equals(ejbJarInfo.path)) {
                    // are ejb modules allowed
                    if (allowedModuleType != null && !allowedModuleType.equals(ModuleType.EJB)) {
                        return null;
                    }
                    if (null != ejbJarInfo.moduleName&&ejbJarInfo.moduleName.equals(appInfo.appId)) {
                        return new TargetModuleIDImpl(DEFAULT_TARGET, ejbJarInfo.moduleName);
                    }
                }
            }
            if (infoObject instanceof ConnectorInfo) {
                ConnectorInfo connectorInfo = (ConnectorInfo) infoObject;
                if (null != appInfo.path&&appInfo.path.equals(connectorInfo.path)) {
                    // are connector modules allowed
                    if (allowedModuleType != null && !allowedModuleType.equals(ModuleType.RAR)) {
                        return null;
                    }
                    if (null !=connectorInfo.moduleId&& connectorInfo.moduleId.equals(appInfo.path)) {
                        return new TargetModuleIDImpl(DEFAULT_TARGET, connectorInfo.moduleId);
                    }
                }
            }
            if (infoObject instanceof WebAppInfo) {
                WebAppInfo webAppInfo = (WebAppInfo) infoObject;
                if (null !=appInfo.path&&appInfo.path.equals(webAppInfo.path)) {
                    // are web app modules allowed
                    if (allowedModuleType != null && !allowedModuleType.equals(ModuleType.WAR)) {
                        return null;
                    }
                    if (null !=webAppInfo.moduleId&&webAppInfo.moduleId.equals(appInfo.path)) {
                        return new TargetModuleIDImpl(DEFAULT_TARGET, webAppInfo.moduleId); //todo web module
                    }
                }
            }
        }

        // regular ear

        // are ear modules allowed
        if (allowedModuleType != null && !allowedModuleType.equals(ModuleType.EAR)) {
            return null;
        }

        TargetModuleIDImpl earModuleId = new TargetModuleIDImpl(DEFAULT_TARGET, appInfo.path);
        for (ClientInfo clientInfo : appInfo.clients) {
            TargetModuleIDImpl clientModuleId = new TargetModuleIDImpl(DEFAULT_TARGET, clientInfo.moduleId);
            clientModuleId.setParentTargetModuleID(earModuleId);
        }
        for (EjbJarInfo ejbJarInfo : appInfo.ejbJars) {
            TargetModuleIDImpl ejbJarModuleId = new TargetModuleIDImpl(DEFAULT_TARGET, ejbJarInfo.moduleName);
            ejbJarModuleId.setParentTargetModuleID(earModuleId);
        }
        for (ConnectorInfo connectorInfo : appInfo.connectors) {
            TargetModuleIDImpl clientModuleId = new TargetModuleIDImpl(DEFAULT_TARGET, connectorInfo.moduleId);
            clientModuleId.setParentTargetModuleID(earModuleId);
        }
        for (WebAppInfo webAppInfo : appInfo.webApps) {
            TargetModuleIDImpl clientModuleId = new TargetModuleIDImpl(DEFAULT_TARGET, webAppInfo.moduleId, webAppInfo.contextRoot);
            clientModuleId.setParentTargetModuleID(earModuleId);
        }

        return earModuleId;
    }

    @Override
    public TargetModuleID[] getNonRunningModules(ModuleType moduleType, Target[] targetList) throws TargetException {
        if (!connected) throw new IllegalStateException("Deployment manager is disconnected");

        if (!containsDefaultTarget(targetList)) {
            return null;
        }

        return new TargetModuleIDImpl[0];
    }

    @Override
    public TargetModuleID[] getRunningModules(ModuleType moduleType, Target[] targetList) throws TargetException {
        if (!connected) throw new IllegalStateException("Deployment manager is disconnected");

        if (!containsDefaultTarget(targetList)) {
            return null;
        }

        Set<TargetModuleID> targetModuleIds = toTargetModuleIds(getDeployer().getDeployedApps(), moduleType);
        return targetModuleIds.toArray(new TargetModuleID[targetModuleIds.size()]);
    }

    @Override
    public ProgressObject distribute(Target[] targetList, File moduleFile, File planFile) {
        if (!connected) throw new IllegalStateException("Deployment manager is disconnected");

        if (!isDeployerLocal()) {
            // todo when we input stream is a valid remote type we can implement this
            throw new UnsupportedOperationException("Deployment from a remote computer is not currently supproted");
        }

        // load properties
        Properties properties = new Properties();
        if (planFile != null) {
            try {
                IO.readProperties(planFile, properties);
            } catch (IOException ignored) {
            }
        }

        return deploy(targetList, properties);
    }

    @Override
    public ProgressObject distribute(Target[] targetList, InputStream moduleStream, InputStream planStream) {
        if (!connected) throw new IllegalStateException("Deployment manager is disconnected");

        // consume module stream
        if (isDeployerLocal()) {
            close(moduleStream);
        } else {
            // todo when we input stream is a valid remote type we can implement this
            throw new UnsupportedOperationException("Deployment from a remote computer is not currently supproted");
        }

        // load properties
        Properties properties = new Properties();
        if (planStream != null) {
            try {
                properties.load(planStream);
            } catch (IOException ignored) {
            } finally {
                close(planStream);
            }

        }
        return deploy(targetList, properties);
    }

    private ProgressObject deploy(Target[] targetList, Properties properties) {
        if (targetList == null) return new ProgressObjectImpl(CommandType.DISTRIBUTE, new NullPointerException("targetList is null"));

        if (!containsDefaultTarget(targetList)) {
            return new ProgressObjectImpl(CommandType.DISTRIBUTE, Collections.<TargetModuleID>emptySet());
        }

        try {
            AppInfo appInfo = getDeployer().deploy(properties);
            TargetModuleID targetModuleId = toTargetModuleId(appInfo, null);

            return new ProgressObjectImpl(CommandType.DISTRIBUTE, Collections.singleton(targetModuleId));
        } catch (ValidationFailedException e) {
            String s = System.getProperty(ReportValidationResults.VALIDATION_LEVEL, "3");
            int level = Integer.parseInt(s);

            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            PrintStream out = new PrintStream(baos);
            out.println(e.getMessage());
            print(e.getErrors(), out, level);
            print(e.getFailures(), out, level);
            print(e.getWarnings(), out, level);
            out.close();
            e = new ValidationFailedException(new String(baos.toByteArray()), e);
            return new ProgressObjectImpl(CommandType.DISTRIBUTE, e);
        } catch (OpenEJBException e) {
            return new ProgressObjectImpl(CommandType.DISTRIBUTE, e);
        }
    }

    protected void print(ValidationException[] exceptions, PrintStream out, int level) {

        for (final ValidationException exception : exceptions) {
            out.print(" ");
            out.print(exception.getPrefix());
            out.print(" ... ");
            if (!(exception instanceof ValidationError)) {
                out.print(exception.getComponentName());
                out.print(": ");
            }
            out.println(exception.getMessage(level));
        }
    }


    private boolean containsDefaultTarget(Target[] targetList) {
        for (Target target : targetList) {
            if (DEFAULT_TARGET.equals(target)) return true;
        }
        return false;
    }

    @Override
    public ProgressObject start(TargetModuleID[] moduleIdList) {
        if (!connected) throw new IllegalStateException("Deployment manager is disconnected");

        Set<TargetModuleID> deployedModules = toTargetModuleIds(getDeployer().getDeployedApps(), null);
        Set<TargetModuleID> targetModuleIds = new HashSet<TargetModuleID>(Arrays.asList(moduleIdList));
        targetModuleIds.retainAll(deployedModules);

        return new ProgressObjectImpl(CommandType.START, targetModuleIds);
    }

    @Override
    public ProgressObject stop(TargetModuleID[] moduleIdList) {
        if (!connected) throw new IllegalStateException("Deployment manager is disconnected");

        return new ProgressObjectImpl(CommandType.START, Collections.<TargetModuleID>emptySet());
    }

    @Override
    public ProgressObject undeploy(TargetModuleID[] moduleIdList) {
        if (!connected) throw new IllegalStateException("Deployment manager is disconnected");

        UndeployException undeployException = null;
        Set<TargetModuleID> results = new TreeSet<TargetModuleID>();
        for (TargetModuleID targetModuleId : moduleIdList) {
            try {
                getDeployer().undeploy(targetModuleId.getModuleID());
                results.add(targetModuleId);
            } catch (UndeployException e) {
                if (undeployException == null) {
                    undeployException = e;
                }
            } catch (NoSuchApplicationException e) {
                // app was not deployed... this should be ignored by jsr88
            }
        }

        if (undeployException == null) {
            return new ProgressObjectImpl(CommandType.UNDEPLOY, results);
        } else {
            return new ProgressObjectImpl(CommandType.UNDEPLOY, undeployException);
        }
    }

    @Override
    public boolean isRedeploySupported() {
        return false;
    }

    @Override
    public ProgressObject redeploy(TargetModuleID[] moduleIDList, File moduleArchive, File deploymentPlan) {
        throw new UnsupportedOperationException("redeploy is not supported");
    }

    @Override
    public ProgressObject redeploy(TargetModuleID[] moduleIDList, InputStream moduleArchive, InputStream deploymentPlan) {
        throw new UnsupportedOperationException("redeploy is not supported");
    }

    @Override
    public Locale[] getSupportedLocales() {
        return new Locale[]{getDefaultLocale()};
    }

    @Override
    public Locale getCurrentLocale() {
        return getDefaultLocale();
    }

    @Override
    public Locale getDefaultLocale() {
        return LOCALE;
    }

    @Override
    public boolean isLocaleSupported(Locale locale) {
        return getDefaultLocale().equals(locale);
    }

    @Override
    public void setLocale(Locale locale) {
        if (!isLocaleSupported(locale)) {
            throw new UnsupportedOperationException("Unsupported locale");
        }
    }

    @Override
    public DConfigBeanVersionType getDConfigBeanVersion() {
        return DCONFIG_BEAN_VERSION;
    }

    @Override
    public boolean isDConfigBeanVersionSupported(DConfigBeanVersionType version) {
        return DCONFIG_BEAN_VERSION.equals(version);
    }

    @Override
    public void setDConfigBeanVersion(DConfigBeanVersionType version) throws DConfigBeanVersionUnsupportedException {
        if (!isDConfigBeanVersionSupported(version)) {
            throw new DConfigBeanVersionUnsupportedException("Version not supported " + version);
        }
    }

    @Override
    public DeploymentConfiguration createConfiguration(DeployableObject deployableObject) throws InvalidModuleException {
        throw new InvalidModuleException("Not supported: " + deployableObject.getType());
    }

    public String toString() {
        if (connected) {
            return "OpenEJBDeploymentManager - connected";
        } else {
            return "OpenEJBDeploymentManager - disconnected";
        }
    }

    @SuppressWarnings("UnusedDeclaration")
    public static class TargetImpl implements Target, Comparable, Serializable {
        private static final long serialVersionUID = -7257857314911948377L;
        private final String name;
        private final String description;

        public TargetImpl(String name) {
            this(name, null);
        }

        public TargetImpl(String name, String description) {
            if (name == null) throw new NullPointerException("name is null");
            this.name = name;
            this.description = description;
        }

        @Override
        public String getName() {
            return name;
        }

        @Override
        public String getDescription() {
            return description;
        }

        public String toString() {
            return name;
        }

        public boolean equals(Object o) {
            if (this == o) return true;
            if (!(o instanceof TargetImpl)) return false;

            TargetImpl target = (TargetImpl) o;
            return name.equals(target.name);
        }

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

        @Override
        public int compareTo(Object o) {
            TargetImpl target = (TargetImpl) o;
            return name.compareTo(target.name);
        }
    }

    public static class TargetModuleIDImpl implements TargetModuleID, Comparable, Serializable {
        private static final long serialVersionUID = 2471961579457311472L;

        private final Target target;
        private final String moduleId;
        private final String webUrl;
        private TargetModuleID parentTargetModuleId;
        private Set<TargetModuleID> children = new TreeSet<TargetModuleID>();

        public TargetModuleIDImpl(Target target, String moduleId) {
            this(target, moduleId, null);
        }

        public TargetModuleIDImpl(Target target, String moduleId, String webUrl) {
            if (target == null) throw new NullPointerException("target is null");
            if (moduleId == null) throw new NullPointerException("moduleId is null");
            this.target = target;
            this.moduleId = moduleId;
            if (webUrl != null && !webUrl.startsWith("http:")) webUrl = "http://localhost:8080/" + webUrl;
            this.webUrl = webUrl;
        }

        @Override
        public Target getTarget() {
            return target;
        }

        @Override
        public String getModuleID() {
            return moduleId;
        }

        @Override
        public TargetModuleID getParentTargetModuleID() {
            return parentTargetModuleId;
        }

        public void setParentTargetModuleID(TargetModuleIDImpl parentTargetModuleId) {
            this.parentTargetModuleId = parentTargetModuleId;
            parentTargetModuleId.children.add(this);
        }

        @Override
        public TargetModuleID[] getChildTargetModuleID() {
            return children.toArray(new TargetModuleID[children.size()]);
        }

        @Override
        public String getWebURL() {
            return webUrl;
        }

        public String toString() {
            return target + "/" + moduleId + (webUrl == null ? " " : webUrl);
        }

        public boolean equals(Object o) {
            if (this == o) return true;
            if (!(o instanceof TargetModuleIDImpl)) return false;

            TargetModuleIDImpl targetModuleID = (TargetModuleIDImpl) o;
            return target.equals(targetModuleID.target) &&
                    moduleId.equals(targetModuleID.moduleId);
        }

        public int hashCode() {
            int result;
            result = target.hashCode();
            result = 29 * result + moduleId.hashCode();
            return result;
        }

        @Override
        public int compareTo(Object o) {
            TargetModuleIDImpl targetModuleID = (TargetModuleIDImpl) o;

            // compare target name
            int val = target.getName().compareTo(targetModuleID.target.getName());
            if (val != 0) return val;

            // compare moduleId
            return moduleId.compareTo(targetModuleID.moduleId);
        }
    }

    public class ProgressObjectImpl implements ProgressObject {
        private final Set<TargetModuleID> targetModuleIds;
        private final ProgressEvent event;
        private final DeploymentStatus deploymentStatus;

        public ProgressObjectImpl(CommandType command, Set<TargetModuleID> targetModuleIds) {
            this.targetModuleIds = targetModuleIds;
            deploymentStatus = new DeploymentStatusImpl(command);
            event = new ProgressEvent(this, null, deploymentStatus);
        }

        public ProgressObjectImpl(CommandType command, Exception exception) {
            this.targetModuleIds = null;
            deploymentStatus = new DeploymentStatusImpl(command, exception);
            event = new ProgressEvent(this, null, deploymentStatus);
        }

        @Override
        public synchronized TargetModuleID[] getResultTargetModuleIDs() {
            if (targetModuleIds == null) return new TargetModuleID[0];
            return targetModuleIds.toArray(new TargetModuleID[targetModuleIds.size()]);
        }

        @Override
        public synchronized DeploymentStatus getDeploymentStatus() {
            return deploymentStatus;
        }

        @Override
        public ClientConfiguration getClientConfiguration(TargetModuleID id) {
            return null;
        }

        @Override
        public boolean isCancelSupported() {
            return false;
        }

        @Override
        public void cancel() throws OperationUnsupportedException {
            throw new OperationUnsupportedException("cancel is not supported");
        }

        @Override
        public boolean isStopSupported() {
            return false;
        }

        @Override
        public void stop() throws OperationUnsupportedException {
            throw new OperationUnsupportedException("stop is not supported");
        }

        @Override
        public void addProgressListener(ProgressListener pol) {
            pol.handleProgressEvent(event);
        }

        @Override
        public void removeProgressListener(ProgressListener pol) {
        }

    }

    public static class DeploymentStatusImpl implements DeploymentStatus {
        private final CommandType command;
        private final StateType state;
        private final String message;

        public DeploymentStatusImpl(CommandType command) {
            this.command = command;
            this.state = StateType.COMPLETED;
            this.message = null;
        }

        public DeploymentStatusImpl(CommandType command, Exception exception) {
            this.command = command;
            this.state = StateType.FAILED;

            StringWriter writer = new StringWriter();
            exception.printStackTrace(new PrintWriter(writer, true));
            this.message = writer.toString();
        }

        @Override
        public CommandType getCommand() {
            return command;
        }

        @Override
        public ActionType getAction() {
            return ActionType.EXECUTE;
        }

        @Override
        public String getMessage() {
            return message;
        }

        @Override
        public StateType getState() {
            return state;
        }

        @Override
        public boolean isRunning() {
            return StateType.RUNNING.equals(state);
        }

        @Override
        public boolean isCompleted() {
            return StateType.COMPLETED.equals(state);
        }

        @Override
        public boolean isFailed() {
            return StateType.FAILED.equals(state);
        }

        public String toString() {
            StringBuilder buf = new StringBuilder();
            buf.append("DeploymentStatus[").append(command).append(',');
            buf.append(state);
            if (message != null) {
                buf.append(',').append(message);
            }
            buf.append(']');
            return buf.toString();
        }
    }
}
