/*
 * Copyright (c) 1997, 2020 Oracle and/or its affiliates. All rights reserved.
 *
 * This program and the accompanying materials are made available under the
 * terms of the Eclipse Public License v. 2.0, which is available at
 * http://www.eclipse.org/legal/epl-2.0.
 *
 * This Source Code may also be made available under the following Secondary
 * Licenses when the conditions for such availability set forth in the
 * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
 * version 2 with the GNU Classpath Exception, which is available at
 * https://www.gnu.org/software/classpath/license.html.
 *
 * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
 */

package com.sun.enterprise.config.serverbeans;

import com.sun.enterprise.config.serverbeans.customvalidators.NotTargetKeyword;
import com.sun.enterprise.config.serverbeans.customvalidators.NotDuplicateTargetName;
import com.sun.enterprise.config.util.ConfigApiLoggerInfo;
import com.sun.enterprise.util.LocalStringManagerImpl;
import com.sun.enterprise.util.net.NetUtils;
import com.sun.enterprise.util.StringUtils;
import com.sun.logging.LogDomains;
import org.glassfish.api.Param;
import org.glassfish.api.admin.AdminCommandContext;
import org.glassfish.api.admin.ServerEnvironment;
import org.glassfish.config.support.*;
import static org.glassfish.config.support.Constants.*;

import org.jvnet.hk2.annotations.Service;
import org.glassfish.hk2.api.PerLookup;
import org.glassfish.hk2.api.ServiceLocator;
import org.jvnet.hk2.config.*;
import org.glassfish.api.admin.config.Named;
import org.glassfish.api.admin.config.ReferenceContainer;

import jakarta.inject.Inject;
import jakarta.validation.Payload;
import java.beans.PropertyVetoException;
import java.io.File;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;

import jakarta.validation.constraints.Pattern;

/**
 * A cluster defines a homogeneous set of server instances that share the same applications, resources, and
 * configuration.
 */
@Configured
@SuppressWarnings("unused")
@NotDuplicateTargetName(message = "{node.duplicate.name}", payload = Node.class)
public interface Node extends ConfigBeanProxy, Named, ReferenceContainer, RefContainer, Payload {
    /**
     * Sets the node name
     *
     * @param value node name
     * @throws PropertyVetoException if a listener vetoes the change
     */
    @Param(name = "name", primary = true)
    @Override
    public void setName(String value) throws PropertyVetoException;

    @NotTargetKeyword(message = "{node.reserved.name}", payload = Node.class)
    @Pattern(regexp = NAME_SERVER_REGEX, message = "{node.invalid.name}", payload = Node.class)
    @Override
    public String getName();

    /**
     * points to the parent directory of the node(s) directory.
     *
     * @return path location of node-dir
     */
    @Attribute
    String getNodeDir();

    /**
     * Sets the value of the node-dir, top-level parent directory of node(s)
     *
     * @param value allowed object is {@link String }
     * @throws PropertyVetoException if a listener vetoes the change
     */
    @Param(name = "nodedir", optional = true)
    void setNodeDir(String value) throws PropertyVetoException;

    /**
     * points to a named host.
     *
     * @return a named host name
     */
    @Attribute
    @Pattern(regexp = NAME_REGEX, message = "{nodehost.invalid.name}", payload = Node.class)
    String getNodeHost();

    /**
     * Sets the value of the name property.
     *
     * @param value allowed object is {@link String }
     * @throws PropertyVetoException if a listener vetoes the change
     */
    @Param(name = "nodehost", optional = true)
    void setNodeHost(String value) throws PropertyVetoException;

    /**
     * points to a GlassFish installation root
     *
     * @return value of install-dir
     */
    @Attribute
    String getInstallDir();

    /**
     * Sets the value of install-dir, the GlassFish installation root.
     *
     * @param value allowed object is {@link String }
     * @throws PropertyVetoException if a listener vetoes the change
     */
    @Param(name = "installdir", optional = true)
    void setInstallDir(String value) throws PropertyVetoException;

    @Attribute()
    String getType();

    /**
     * Sets the value of type of this node.
     *
     * @param value allowed object is {@link String }
     * @throws PropertyVetoException if a listener vetoes the change
     */
    @Param(name = "type")
    void setType(String value) throws PropertyVetoException;

    /**
     * specifies the windows domain if applicable
     *
     * @return the Windows domain name.
     */
    @Attribute
    @Pattern(regexp = NAME_REGEX, message = "{windowsdomain.invalid.name}", payload = Node.class)
    String getWindowsDomain();

    /**
     * Sets the value of the windows domain property.
     *
     * @param value allowed object is {@link String }
     * @throws PropertyVetoException if a listener vetoes the change
     */
    @Param(name = "windowsdomain", optional = true)
    void setWindowsDomain(String value) throws PropertyVetoException;

    /**
     * true if node is frozen and we should not allow new instances to be created on the nod.
     *
     * @return "true" if node is frozen
     */
    @Attribute(defaultValue = "false", dataType = Boolean.class)
    String getFreeze();

    /**
     * Sets the value of the freeze
     *
     * @param value "true" to freeze node and not allow instances to be created
     *
     * @throws PropertyVetoException if a listener vetoes the change
     */
    void setFreeze(String value) throws PropertyVetoException;

    @Element
    SshConnector getSshConnector();

    void setSshConnector(SshConnector connector);

    /**
     * Returns the install dir with separators as forward slashes. This is needed to run commands over SSH tools on Windows
     * where the backslashes are interpruted as escape chars.
     *
     * @return the install dir with separators as forward slashes
     */
    @DuckTyped
    String getInstallDirUnixStyle();

    /**
     * Returns the node dir with separators as forward slashes. This is needed to run commands over SSH tools on Windows
     * where the backslashes are interpruted as escape chars.
     *
     * @return the node dir with separators as forward slashes
     */
    @DuckTyped
    String getNodeDirUnixStyle();

    /**
     * Returns the node dir as an absolute path. If the node dir path in the Node element is relative this will make it
     * absolute relative to the node's installdir.
     *
     * @return the node's nodedir as an absolute path. Null if no nodedir.
     */
    @DuckTyped
    String getNodeDirAbsolute();

    @DuckTyped
    String getNodeDirAbsoluteUnixStyle();

    /**
     * Is a node being used by any server instance?
     *
     * @return true if node is referenced by any server instance, else false.
     */
    @DuckTyped
    boolean nodeInUse();

    /**
     * True if this is the default local node. Example: localhost-domain1
     *
     * @return
     */
    @DuckTyped
    boolean isDefaultLocalNode();

    /**
     * True if the node's nodeHost is local to this
     *
     * @return
     */
    @DuckTyped
    boolean isLocal();

    /**
     * Does the node allow instance creation?
     *
     * @return true if node allows instance creation, else false
     */
    @DuckTyped
    boolean instanceCreationAllowed();

    class Duck {
        public static String getInstallDirUnixStyle(Node node) {
            String installDir = node.getInstallDir();
            if (installDir == null)
                return null;
            return installDir.replaceAll("\\\\", "/");
        }

        public static String getNodeDirUnixStyle(Node node) {
            String nodeDir = node.getNodeDir();
            if (nodeDir == null)
                return null;
            return nodeDir.replaceAll("\\\\", "/");
        }

        public static String getNodeDirAbsolute(Node node) {
            // If nodedir is relative make it absolute relative to installRoot
            String nodeDir = node.getNodeDir();
            if (nodeDir == null || nodeDir.length() == 0)
                return null;
            File nodeDirFile = new File(nodeDir);
            if (nodeDirFile.isAbsolute()) {
                return nodeDir;
            }
            // node-dir is relative. Make it absolute. We root it under the
            // GlassFish root install directory.
            String installDir = node.getInstallDir();
            File installRootFile = new File(installDir, "glassfish");
            File absoluteNodeDirFile = new File(installRootFile, nodeDir);
            return absoluteNodeDirFile.getPath();
        }

        public static String getNodeDirAbsoluteUnixStyle(Node node) {
            String nodeDirAbsolute = getNodeDirAbsolute(node);
            if (nodeDirAbsolute == null)
                return null;
            return nodeDirAbsolute.replaceAll("\\\\", "/");
        }

        public static boolean isDefaultLocalNode(Node node) {
            Dom serverDom = Dom.unwrap(node);
            Domain domain = serverDom.getHabitat().getService(Domain.class);
            if (node.getName().equals("localhost-" + domain.getName())) {
                return true;
            }
            return false;
        }

        public static boolean isLocal(Node node) {
            // Short circuit common case for efficiency
            Dom serverDom = Dom.unwrap(node);
            Domain domain = serverDom.getHabitat().getService(Domain.class);
            if (node.getName().equals("localhost-" + domain.getName())) {
                return true;
            }
            String nodeHost = node.getNodeHost();
            if (nodeHost == null || nodeHost.length() == 0) {
                return false;
            }
            return NetUtils.isThisHostLocal(nodeHost);
        }

        public static boolean nodeInUse(Node node) {
            //check if node is referenced by an instance
            String nodeName = node.getName();
            Dom serverDom = Dom.unwrap(node);
            Servers servers = serverDom.getHabitat().getService(Servers.class);
            List<Server> serverList = servers.getServer();
            if (serverList != null) {
                for (Server server : serverList) {
                    if (nodeName.equals(server.getNodeRef())) {
                        return true;
                    }
                }
            }
            return false;
        }

        public static boolean instanceCreationAllowed(Node node) {
            return !Boolean.parseBoolean(node.getFreeze());
        }
    }

    @Service
    @PerLookup
    class Decorator implements CreationDecorator<Node> {
        @Param(name = "nodedir", optional = true)
        String nodedir = null;
        @Param(name = "nodehost", optional = true)
        String nodehost = null;
        @Param(name = "installdir", optional = true)
        String installdir = null;
        @Param(name = "type")
        String type = null;
        @Param(name = "sshport", optional = true)
        String sshPort = null;
        @Param(name = "sshnodehost", optional = true)
        String sshHost = null;
        @Param(name = "sshuser", optional = true)
        String sshuser = null;
        @Param(name = "sshkeyfile", optional = true)
        String sshkeyfile;
        @Param(name = "sshpassword", optional = true)
        String sshpassword;
        @Param(name = "sshkeypassphrase", optional = true)
        String sshkeypassphrase;
        @Param(name = "windowsdomain", optional = true)
        String windowsdomain;
        @Inject
        ServiceLocator habitat;
        @Inject
        ServerEnvironment env;
        @Inject
        Domain domain;
        @Inject
        Nodes nodes;

        /**
         * Decorates the newly CRUD created cluster configuration instance. tasks : - ensures that it references an existing
         * configuration - creates a new config from the default-config if no config-ref was provided. - check for deprecated
         * parameters.
         *
         * @param context administration command context
         * @param instance newly created configuration element
         * @throws TransactionFailure
         * @throws PropertyVetoException
         */
        @Override
        public void decorate(AdminCommandContext context, final Node instance) throws TransactionFailure, PropertyVetoException {

            LocalStringManagerImpl localStrings = new LocalStringManagerImpl(Node.class);

            /* 16034: see if instance creation is turned off on node */
            if (!nodes.nodeCreationAllowed()) {
                throw new TransactionFailure(
                        localStrings.getLocalString("nodeCreationNotAllowed", "Node creation is disabled. No new nodes may be created."));
            }
            // If these options were passed a value of the empty string then
            // we want to make sure they are null in the Node. The
            // admin console often passes the empty string instead of null.
            // See bug 14873
            if (!StringUtils.ok(nodedir))
                instance.setNodeDir(null);
            if (!StringUtils.ok(installdir))
                instance.setInstallDir(null);
            if (!StringUtils.ok(nodehost))
                instance.setNodeHost(null);
            if (!StringUtils.ok(windowsdomain))
                instance.setWindowsDomain(null);

            //only create-node-ssh and update-node-ssh should be changing the type to SSH
            instance.setType(type);

            if (type.equals("CONFIG"))
                return;

            SshConnector sshC = instance.createChild(SshConnector.class);

            SshAuth sshA = sshC.createChild(SshAuth.class);
            if (StringUtils.ok(sshuser))
                sshA.setUserName(sshuser);
            if (StringUtils.ok(sshkeyfile))
                sshA.setKeyfile(sshkeyfile);
            if (StringUtils.ok(sshpassword))
                sshA.setPassword(sshpassword);
            if (StringUtils.ok(sshkeypassphrase))
                sshA.setKeyPassphrase(sshkeypassphrase);
            sshC.setSshAuth(sshA);

            if (StringUtils.ok(sshPort))
                sshC.setSshPort(sshPort);

            if (StringUtils.ok(sshHost))
                sshC.setSshHost(sshHost);

            instance.setSshConnector(sshC);
        }
    }

    @Service
    @PerLookup
    class DeleteDecorator implements DeletionDecorator<Nodes, Node> {
        @Inject
        private Domain domain;
        @Inject
        Nodes nodes;
        @Inject
        Servers servers;
        @Inject
        private ServerEnvironment env;

        @Override
        public void decorate(AdminCommandContext context, Nodes parent, Node child) throws PropertyVetoException, TransactionFailure {
            Logger logger = ConfigApiLoggerInfo.getLogger();
            LocalStringManagerImpl localStrings = new LocalStringManagerImpl(Node.class);
            String nodeName = child.getName();

            if (nodeName.equals("localhost-" + domain.getName())) { // can't delete localhost node
                final String msg = localStrings.getLocalString("Node.localhost", "Cannot remove Node {0}. ", child.getName());

                logger.log(Level.SEVERE, ConfigApiLoggerInfo.cannotRemoveNode, child.getName());
                throw new TransactionFailure(msg);
            }

            List<Node> nodeList = nodes.getNode();

            // See if any servers are using this node
            List<Server> serversOnNode = servers.getServersOnNode(child);
            int n = 0;
            if (serversOnNode != null && serversOnNode.size() > 0) {
                StringBuilder sb = new StringBuilder();
                for (Server server : serversOnNode) {
                    if (n > 0)
                        sb.append(", ");
                    sb.append(server.getName());
                    n++;
                }

                final String msg = localStrings.getLocalString("Node.referencedByInstance",
                        "Node {0} referenced in server instance(s): {1}.  Remove instances before removing node.", child.getName(),
                        sb.toString());
                logger.log(Level.SEVERE, ConfigApiLoggerInfo.referencedByInstance, new Object[] { child.getName(), sb.toString() });
                throw new TransactionFailure(msg);
            }

            nodeList.remove(child);
        }
    }
}
