/*
 * The contents of this file are subject to the terms
 * of the Common Development and Distribution License
 * (the License).  You may not use this file except in
 * compliance with the License.
 *
 * You can obtain a copy of the license at
 * https://glassfish.dev.java.net/public/CDDLv1.0.html or
 * glassfish/bootstrap/legal/CDDLv1.0.txt.
 * See the License for the specific language governing
 * permissions and limitations under the License.
 *
 * When distributing Covered Code, include this CDDL
 * Header Notice in each file and include the License file
 * at glassfish/bootstrap/legal/CDDLv1.0.txt.
 * If applicable, add the following below the CDDL Header,
 * with the fields enclosed by brackets [] replaced by
 * you own identifying information:
 * "Portions Copyrighted [year] [name of copyright owner]"
 *
 * Copyright (c) Ericsson AB, 2004-2007. All rights reserved.
 * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
 */
package org.jvnet.glassfish.comms.admin.clbadmin;

import com.sun.enterprise.admin.servermgmt.pe.PEFileLayout;
import com.sun.enterprise.admin.server.core.AdminService;
import com.sun.enterprise.config.ConfigChange;
import com.sun.enterprise.config.ConfigContext;
import com.sun.enterprise.config.ConfigContextEvent;
import com.sun.enterprise.config.ConfigContextEventListener;
import com.sun.enterprise.config.serverbeans.Config;
import com.sun.enterprise.config.serverbeans.Configs;
import com.sun.enterprise.config.serverbeans.ConvergedLoadBalancer;
import com.sun.enterprise.config.serverbeans.Domain;
import com.sun.enterprise.util.SystemPropertyConstants;
import com.sun.enterprise.config.ConfigException;

import org.jvnet.glassfish.comms.clb.admin.Loadbalancer;
import org.jvnet.glassfish.comms.clb.admin.ObjectFactory;
import org.jvnet.glassfish.comms.admin.clbadmin.reader.api.LoadbalancerReader;
import org.jvnet.glassfish.comms.admin.clbadmin.reader.impl.LoadbalancerReaderImpl;
import org.jvnet.glassfish.comms.admin.clbadmin.transform.LoadbalancerVisitor;
import org.jvnet.glassfish.comms.admin.clbadmin.ClbConfigPublisher;
import javax.management.MBeanServer;
import javax.management.ObjectName;
import javax.management.ObjectInstance;

import java.util.List;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.ByteArrayOutputStream;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.math.BigInteger;
import java.util.Properties;


/**
 * Helper Class to Load Balancer Admin Event
 * @author Srinivas Krishnan
 */
public class ClbAdminEventHelper {
    
    private static final String DIGEST_FILE = "digestfile.properties";
    private ClbConfigPublisher _clbp = null;
    private String _name = null;
    private String _lbName = null;
    private ConfigContext _ctx = null;
    
    /**
     * Default constructor.
     */
    public ClbAdminEventHelper(ConfigContext ctx, ClbConfigPublisher clbp, ConvergedLoadBalancer clb) {
        _clbp = clbp;
        _name = clb.getConvergedLbConfigName();
        _lbName = clb.getName();
        _ctx = ctx;
    }

    public boolean isApplyChangesRequired() {
        boolean applyChanges = false;
        String iRoot = System.getProperty(SystemPropertyConstants.INSTANCE_ROOT_PROPERTY);
        String digestFilePath = iRoot + File.separator + PEFileLayout.CONFIG_DIR + File.separator + DIGEST_FILE;
        String key = _name + "." + _lbName;
        String str = getClbXML();
        String lastDigestValue = getLastDigestValue(digestFilePath, key);
        String currentDigestValue = getMessageDigest(str);

        if (!currentDigestValue.equals(lastDigestValue)) {
            // write the latest digest value into the digest file
            storeLatestDigestValue(digestFilePath, currentDigestValue, key);
            applyChanges = true;
        }
        return applyChanges;
    }
    
    public String getClbXML() {
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        try {
            LoadbalancerReader lbr = _clbp.getLbReader(_ctx, _name);
            // tranform the data using visitor pattern
            Loadbalancer _lb = new Loadbalancer();
            LoadbalancerVisitor lbVstr = new LoadbalancerVisitor(_lb);
            lbr.accept(lbVstr);
            ObjectFactory clbFactory = new ObjectFactory();
            clbFactory.store(_lb, baos);
        } catch (Exception e) {
            System.out.println(e.getMessage());
        }
        return baos.toString();
        
    }
    
    public String getMessageDigest(String lbxml) {
        String hash = "";
        try {
            MessageDigest md = MessageDigest.getInstance("MD5");
            md.update(lbxml.getBytes());
            hash = new BigInteger(md.digest()).toString(16);
        }catch(NoSuchAlgorithmException e){
            System.out.println(e.getMessage());
        }
        return hash;
    }
    
    public String getLastDigestValue(String sPath, String keyName) {
        Properties prop = new Properties();
        String lastDigestValue = null;
        try {
            File digestFile = new File(sPath);
            FileInputStream digestInputStream = new FileInputStream(digestFile);
            if (digestInputStream != null) {
                prop.load(digestInputStream);
                lastDigestValue = prop.getProperty(keyName);
            }
        } catch (IOException ioe) {
            lastDigestValue = "";
        }
        return lastDigestValue;
    }
    
    public static void storeLatestDigestValue(String sPath, String digestValue, String keyName) {
        Properties prop = new Properties();
        prop.setProperty(keyName, digestValue);
        boolean created = false;
        File digestFile = new File(sPath);
        try {
            if (!digestFile.exists())
                created = digestFile.createNewFile();
            if (digestFile.exists() || created) {
                FileOutputStream digestOutputStream = new FileOutputStream(digestFile);
                if (digestOutputStream != null)
                    prop.store(digestOutputStream, "");
            }
        }catch (IOException ioe) {
            System.out.println(ioe.getMessage());
        }
    }
    
    public static String getConfigFileNewValue(String fileName) {
        if (fileName == null)
            return "";
        int versionNumPos = fileName.lastIndexOf(".v");
        String versionNum = "0";
        if (versionNumPos != -1) {
            versionNum = fileName.substring(versionNumPos+2);
            try {
                int ver = Integer.parseInt(versionNum);
                ver++;
                versionNum = String.valueOf(ver);
            } catch (Exception e) {
                versionNum = "0";
            }
            fileName = fileName.substring(0,versionNumPos);
        }
        versionNum = ".v" + versionNum;
        String newFileName = fileName + versionNum;
        return newFileName;
    }
}