// this file contains some things left over from refactoring that I'm going
// to adapt and likely kill.  It was better than commenting them out but I 
// don't want to get rid of these things yet.

/**
 * Copyright (c) 2009 Red Hat, Inc.
 *
 * This software is licensed to you under the GNU General Public License,
 * version 2 (GPLv2). There is NO WARRANTY for this software, express or
 * implied, including the implied warranties of MERCHANTABILITY or FITNESS
 * FOR A PARTICULAR PURPOSE. You should have received a copy of GPLv2
 * along with this software; if not, see
 * http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
 *
 * Red Hat trademarks are not licensed under GPLv2. No permission is
 * granted to use or replicate Red Hat trademarks that are incorporated
 * in this software or its documentation.
 */

package org.cobbler;

import com.redhat.rhn.common.util.StringUtil;

import org.apache.commons.lang.StringUtils;

import java.util.Arrays;
import java.util.Collection;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;


/**
 * Base class has attributes common to 
 * distros, profiles, system records
 * @author paji
 * @version $Rev$
 */
public abstract class CobblerObject {
    
    protected String handle;
    protected Map<String, Object> dataMap = new HashMap<String, Object>();
    protected CobblerConnection client;    

    /**
     * Helper method used by all cobbler objects to 
     * return a version of themselves by UID
     * @see org.cobbler.Distro.lookupById for example usage..
     * 
     * @param client the Cobbler Connection
     * @param id the UID of the distro/profile/system record
     * @param findMethod the find xmlrpc method, eg: find_distro
     * @return true if the cobbler object was found. 
     */

    protected static Map<String, Object> lookupDataMapById(CobblerConnection client, 
                             String id, String findMethod) {
        if (id == null) {
            return null;
        }
        List<Map<String, Object>> objects = lookupDataMapsByCriteria(client,
                                                            UID, id, findMethod);
        if (!objects.isEmpty()) {
            return objects.get(0);
        }
        return null;

    }

    /**
     * look up data maps by a certain criteria
     * @param client the xmlrpc client
     * @param critera (i.e. uid profile, etc..)
     * @param value the value of the criteria
     * @param findMethod the find method to use (find_system, find_profile)
     * @return List of maps
     */

    protected static List<Map<String, Object>> lookupDataMapsByCriteria(
            CobblerConnection client, String critera, String value, String findMethod) {
        if (value == null) {
            return null;
        }

        Map<String, String> criteria  = new HashMap<String, String>();
        criteria.put(critera, value);
        List<Map<String, Object>> objects = (List<Map<String, Object>>)
                                client.invokeTokenMethod(findMethod, criteria);
        return objects;

    }
    

    /**
     * Helper method used by all cobbler objects to 
     * return a Map of themselves by name.
     * @see org.cobbler.Distro.lookupByName for example usage..
     * @param client  the Cobbler Connection
     * @param name the name of the cobbler object
     * @param lookupMethod the name of the xmlrpc
     *                       method to lookup: eg get_profile for profile 
     * @return the Cobbler Object Data Map or null
     */

    protected static Map <String, Object> lookupDataMapByName(CobblerConnection client, 
                                    String name, String lookupMethod) {
        Map <String, Object> map = (Map<String, Object>)client.
                                        invokeMethod(lookupMethod, name);
        if (map == null || map.isEmpty()) {
            return null;
        }
        return map;
    }
    
    protected abstract void invokeModify(String key, Object value);
    protected abstract void invokeSave();
    protected abstract boolean invokeRemove();
    protected abstract String invokeGetHandle();
    protected abstract void reload();
    protected abstract void invokeRename(String newName);
    
    protected String getHandle() {
        if (handle == null) {
            handle = invokeGetHandle();
        }
        return handle;
    }
    
    protected void modify(String key, Object value) {
        // FIXME: invokeModify(key, value);
        dataMap.put(key, value);
    }
    
    /**
     * calls save object to complete the commit
     */
    public void save() {
        // FIXME: invokeSave();
        update();
    }

    /**
     * removes the kickstart object from cobbler.
     * @return true if sucessfull
     */
    public boolean remove() {
        return invokeRemove();
    }
    
    //public int getDepth() {
    //    return (Integer)dataMap.get(DEPTH);
    //}
    
    /**
     * @param depthIn the depth to set
     */
    //public void setDepth(int depthIn) {
    //    modify(DEPTH, depthIn);
    //}

    /**
     * @return the kernelOptions
     */
    //public Map<String, Object> getKernelOptions() {
    //    return (Map<String, Object>)dataMap.get(KERNEL_OPTIONS);
    // }

    /**
     * gets the kernel options in string form
     * @return the string
     */
    //public String getKernelOptionsString() {
    //    return convertOptionsMap(getKernelOptions());
    //}

    /**
     * gets the kernel post options in string form
     * @return the string
     */
    //public String getKernelPostOptionsString() {
    //    return convertOptionsMap(getKernelPostOptions());
    //}

    // FIXME: refactor
    private String convertOptionsMap(Map<String, Object> map) {
        StringBuilder string = new StringBuilder();
        for (Object key : map.keySet()) {
            if (StringUtils.isEmpty((String)map.get(key))) {
                string.append(key + " ");
            }
            else {
                string.append(key + "=" + map.get(key) + " ");
            }
        }
        return string.toString();
    }

    
    /**
     * @param kernelOptionsIn the kernelOptions to set
     */
    //public void setKernelOptions(Map<String, Object> kernelOptionsIn) {
    //    modify(SET_KERNEL_OPTIONS, kernelOptionsIn);
    //}

    /**
     * @param kernelOptsIn the kernelOptions to set
     */
    //public void setKernelOptions(String kernelOptsIn) {
    //    setKernelOptions(parseKernelOpts(kernelOptsIn));
    //}


    /**
     * @param kernelOptsIn the kernelOptions to set
     */
    //public void setKernelPostOptions(String kernelOptsIn) {
    //    setKernelPostOptions(parseKernelOpts(kernelOptsIn));
    //}

    // FIXME: refactor
    private Map<String, Object> parseKernelOpts(String kernelOpts) {
        Map<String, Object> toRet = new HashMap<String, Object>();

        if (StringUtils.isEmpty(kernelOpts)) {
            return toRet;
        }

        String[] options = StringUtils.split(kernelOpts);
        for (String option : options) {
            String[] split = option.split("=");
            if (split.length == 1) {
                toRet.put(split[0], "");
            }
            else if (split.length == 2) {
                toRet.put(split[0], split[1]);
            }
        }
        return toRet;
    }

    
    /**
     * @return the kickstart Metadata
     */
    //public Map<String, Object> getKsMeta() {
    //    return (Map<String, Object>)dataMap.get(KS_META);
    //}

    
    /**
     * @param kernelMetaIn the kernelMeta to set
     */
    //public void setKsMeta(Map<String, ? extends Object> kernelMetaIn) {
    //    modify(SET_KS_META, kernelMetaIn);
    //}

    
    /**
     * @return the name
     */
    //public String getName() {
    //    return (String)dataMap.get(NAME);
    //}

    /**
     * @param nameIn sets the new name
     */
    //public void setName(String nameIn) {
    //    invokeRename(nameIn);
    //    dataMap.put(NAME, nameIn);
    //    handle = null;
    //    handle = getHandle();
    //    reload();
    // }
    
    //protected void update() {
    //    // FIXME: comments?
    //    client.invokeTokenMethod("update");            
    //}
    
    public String toString() {
        return "$ObjectType :: " + dataMap;
    }

    protected String invokeGetHandle() {
        return (String)client.invokeTokenMethod(getGetHandleFunctionName(), this.getName());
    }

    protected void invokeModify(String key, Object value) {
        client.invokeTokenMethod(getModifyFunctionName(), getHandle(), key, value);
    }

    protected void invokeSave() {
        client.invokeTokenMethod(getSaveFunctionName(), getHandle());
    }

    protected boolean invokeRemove() {
        return (Boolean) client.invokeTokenMethod(getRemoveFunctionName(), getName());
    }

    protected void invokeRename(String newName) {
        client.invokeTokenMethod(getRenameFunctionName(), getHandle(), newName);
    }
    
    public void reload() {
        $ObjectType obj = lookupById(client, getId());
        map = obj.dataMap;
    }

    // FIXME: needed/refactor?
    protected static CobblerObject handleLookup(CobblerConnection client, Map map) {
        if (map != null) {
            $ObjectType obj = new $ObjectType(client);
            obj.dataMap = map;
            return obj;
        }
        return null;
    }


}

=====


#include header.tmpl

/**
 * Network
 * @version $Rev$
 */
public class Network {
    private static final String SUBNET = "subnet";
    private static final String DNS_NAME = "dns_name";
    private static final String IP_ADDRESS = "ip_address";
    private static final String STATIC = "static";
    private static final String MAC_ADDRESS = "mac_address";

    private String name;
    private String subnet;
    private String ipAddress;
    private boolean isStatic;
    private String macAddress;
    /**
     * Constructor to create a new network interface
     * @param nameIn the name of the network
     */
    public Network(String nameIn) {
        name = nameIn;
    }

    /**
     * Intentionally given default/package scope
     * returns a nicely formatted map that can be used by
     * the system record to set it in xmlrpc.
     * @return a map representation of the interface
     */
    Map<String, Object> toMap() {
        Map<String, Object> inet = new HashMap<String, Object>();
        addToMap(inet, "macaddress-" + name, macAddress);
        addToMap(inet, "subnet-" + name, subnet);
        addToMap(inet, "ipaddress-" + name, ipAddress);
        addToMap(inet, "macaddress-" + name, macAddress);
        addToMap(inet, "static-" + name, isStatic);
        return inet;
    }

    private void addToMap(Map<String, Object> inet, String key, Object value) {
        if (value != null || (value instanceof String &&
                            !StringUtils.isBlank((String)value))) {
            inet.put(key, value);
        }
    }

    /**
     * Given a interface name and map generated by the system record
     * this method creates a new Network object.
     * @param name the name of the interface
     * @param ifaceInfo the interface information
     * @return the netwrok object
     */
    static Network load(String name, Map<String, Object> ifaceInfo) {
        Network net = new Network(name);
        net.setMacAddress((String)ifaceInfo.get(MAC_ADDRESS));
        net.setNetmask((String)ifaceInfo.get(SUBNET));
        net.setIpAddress((String)ifaceInfo.get(IP_ADDRESS));
        net.setStaticNetwork(ifaceInfo.containsKey(STATIC) &&
                                    Boolean.TRUE.equals(ifaceInfo.get(STATIC)));
        return net;
    }

    /**
     * @return Returns the name.
     */
    public String getName() {
        return name;
    }

    /**
     * @return Returns the subnet.
     */
    public String getSubnet() {
        return subnet;
    }
    
    /**
     * @param subnetIn The subnet to set.
     */
    public void setNetmask(String subnetIn) {
        subnet = subnetIn;
    }

    /**
     * @return Returns the ipAddress.
     */
    public String getIpAddress() {
        return ipAddress;
    }

    /**
     * @param ipAddressIn The ipAddress to set.
     */
    public void setIpAddress(String ipAddressIn) {
        ipAddress = ipAddressIn;
    }

    /**
     * @return Returns the isStatic.
     */
    public boolean isStaticNetwork() {
        return isStatic;
    }

    /**
     * @param staticIn The isStatic to set.
     */
    public void setStaticNetwork(boolean staticIn) {
        isStatic = staticIn;
    }

    /**
     * @return Returns the macAddress.
     */
    public String getMacAddress() {
        return macAddress;
    }

    /**
     * @param macAddressIn The macAddress to set.
     */
    public void setMacAddress(String macAddressIn) {
        macAddress = macAddressIn;
    }
}
