/*
 * $Id$
 *
 * Copyright 1996-2008 Sun Microsystems, Inc.  All Rights Reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Sun designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Sun in the LICENSE file that accompanied this code.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
 * CA 95054 USA or visit www.sun.com if you need additional information or
 * have any questions.
 */
package com.sun.javatest.cof;

import java.io.InputStreamReader;
import java.io.RandomAccessFile;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.StringTokenizer;
import java.util.TimeZone;

import com.sun.javatest.util.I18NResourceBundle;

/* temp */public/* temp */class COFEnvironment extends COFItem {
        static String[] propOrder = { "machine", "os", "jdk", "systemLocale",
                        "userLocale", "encoding", "timezone", "bits", "displaydepth",
                        "description", "sw" };

        static String[] propTags = { "machine", "os", "jdk", "system-locale",
                        "user-locale", "encoding", "timezone", "bits", "displaydepth",
                        "description", "sw" };

        static LinkedHashMap xmlAttributes;

        static LinkedHashMap xmlElements;

        static String xmlTagName;
        private static I18NResourceBundle i18n = I18NResourceBundle
        .getBundleForClass(Main.class);

        static {
                xmlElements = new LinkedHashMap();
                for (int i = 0; i < propOrder.length; i++) {
                        xmlElements.put(propOrder[i], propTags[i]);
                }
                xmlAttributes = new LinkedHashMap();
                xmlAttributes.put("id", "id");
                xmlTagName = "environment";
        }

        //    @XmlElement(namespace = "http://qare.sfbay.sun.com/projects/COF/2003/2_0_2/Schema")
        protected Integer bits;

        //    @XmlElement(namespace = "http://qare.sfbay.sun.com/projects/COF/2003/2_0_2/Schema")
        protected String description;

        //    @XmlElement(namespace = "http://qare.sfbay.sun.com/projects/COF/2003/2_0_2/Schema")
        protected Integer displaydepth;

        private String domainName;

        //    @XmlElement(namespace = "http://qare.sfbay.sun.com/projects/COF/2003/2_0_2/Schema")
        protected String encoding;

        private String hostName;

        //    @XmlAttribute(required = true)
        protected String id = "env:0";

        //    @XmlElement(namespace = "http://qare.sfbay.sun.com/projects/COF/2003/2_0_2/Schema")
        protected String jdk;

        //  @XmlElement(namespace = "http://qare.sfbay.sun.com/projects/COF/2003/2_0_2/Schema", required = true)
        protected String machine;

        //    @XmlElement(namespace = "http://qare.sfbay.sun.com/projects/COF/2003/2_0_2/Schema", required = true)
        protected COFOS os;

        //    @XmlElement(namespace = "http://qare.sfbay.sun.com/projects/COF/2003/2_0_2/Schema", required = true)
        protected List/*<SWEntity>*/sw;

        //    @XmlElement(name = "system-locale", namespace = "http://qare.sfbay.sun.com/projects/COF/2003/2_0_2/Schema")
        protected String systemLocale;

        //    @XmlElement(namespace = "http://qare.sfbay.sun.com/projects/COF/2003/2_0_2/Schema")
        protected String timezone;

        //    @XmlElement(name = "system-locale", namespace = "http://qare.sfbay.sun.com/projects/COF/2003/2_0_2/Schema")
        protected String userLocale;

        COFEnvironment(COFData data) {
                initDefaultHostInfo();
                initDefaultOSInfo();

                hostName = data.get("environment.host", hostName);
                domainName = data.get("environment.domain", domainName);
                setMachine(data.get("environment.machine", hostName + "." + domainName));
                os.setName(data.get("environment.os.name", os.getName()));
                os.setVersion(data.get("environment.os.version", os.getVersion()));
                os.setArch(data.get("environment.os.arch", os.getArch()));
                setJdk(data.get("environment.jdk", jdk));
                setUserLocale(data.get("environment.user-locale", java.util.Locale.getDefault().toString()));
                setSystemLocale(data.get("environment.system-locale", data
                                .get("LOCALE")));
                setEncoding(data.get("environment.encoding", (new InputStreamReader(
                                System.in)).getEncoding()));
                setTimezone(data.get("environment.timezone", TimeZone.getDefault()
                                .getID()));
                setBits(data.get("environment.bits", null) == null ? null
                                : new Integer(data.get("environment.bits")));
                setDisplaydepth(data.get("environment.displaydepth", null) == null ? null
                                : new Integer(data.get("environment.displaydepth")));
                setDescription(data.get("environment.description"));
        }

        /**
         * Gets the value of the bits property.
         *
         * @return
         *     possible object is
         *     {@link Integer }
         *
         */
        public Integer getBits() {
                return bits;
        }

        private String getCalderaLinuxVersionInfo() {
                String res = "N/A";

                RandomAccessFile raf = null;
                try {
                        raf = new RandomAccessFile("/etc/issue", "r");
                        String line;
                        while ((line = raf.readLine()) != null) {
                                StringTokenizer st = new StringTokenizer(line, " ");
                                if (st.countTokens() >= 2) {
                                        if (st.nextToken().toUpperCase().equals("VERSION")) {
                                                res = st.nextToken();
                                                break;
                                        }
                                }
                        }
                } catch (Exception e) {
                        // System.err.println("Something might be wrong with Caldera");
                        // cat.warn("The version number of Caldera cannot be retrieved");
                } finally {
                        if (raf != null) {
                                try {
                                        raf.close();
                                } catch (Exception e) {
                                }
                        }
                }

                return res;
        }

        /**
         * Gets the value of the description property.
         *
         * @return
         *     possible object is
         *     {@link String }
         *
         */
        public String getDescription() {
                return description;
        }

        /**
         * Gets the value of the displaydepth property.
         *
         * @return
         *     possible object is
         *     {@link Integer }
         *
         */
        public Integer getDisplaydepth() {
                return displaydepth;
        }

        /**
         * Gets the value of the encoding property.
         *
         * @return
         *     possible object is
         *     {@link String }
         *
         */
        public String getEncoding() {
                return encoding;
        }

        private String getGenericLinuxVersionInfo(String fileName) {
                String res = "N/A";

                RandomAccessFile raf = null;
                try {
                        raf = new RandomAccessFile(fileName, "r");
                        StringTokenizer st = new StringTokenizer(raf.readLine(), " ");
                        while (st.hasMoreElements()) {
                                String ele = st.nextToken();
                                if (Character.isDigit(ele.charAt(0))) {
                                        res = ele;
                                        break;
                                }
                        }
                } catch (Exception e) {
                        // System.err.println("Something might be wrong with Linux");
                } finally {
                        if (raf != null) {
                                try {
                                        raf.close();
                                } catch (Exception e) {
                                }
                        }
                }

                return res;
        }

        /**
         * Gets the value of the id property.
         *
         * @return
         *     possible object is
         *     {@link String }
         *
         */
        public String getId() {
                return id;
        }

        LinkedHashMap getItemAttributes() {
                return xmlAttributes;
        }

        LinkedHashMap getItemElements() {
                return xmlElements;
        }

        String getItemTagName() {
                return xmlTagName;
        }

        /**
         * Gets the value of the jdk property.
         *
         * @return
         *     possible object is
         *     {@link String }
         *
         */
        public String getJdk() {
                return jdk;
        }

        /**
         * Gets the value of the machine property.
         *
         * @return
         *     possible object is
         *     {@link String }
         *
         */
        public String getMachine() {
                return machine;
        }

        /**
         * Gets the value of the os property.
         *
         * @return
         *     possible object is
         *     {@link OS }
         *
         */
        public COFOS getOs() {
                return os;
        }

        String[] getPropOrder() {
                return propOrder;
        }

        /**
         * Gets the value of the sw property.
         *
         * <p>
         * This accessor method returns a reference to the live list,
         * not a snapshot. Therefore any modification you make to the
         * returned list will be present inside the JAXB object.
         * This is why there is not a <CODE>set</CODE> method for the sw property.
         *
         * <p>
         * For example, to add a new item, do as follows:
         * <pre>
         *    getSw().add(newItem);
         * </pre>
         *
         *
         * <p>
         * Objects of the following type(s) are allowed in the list
         * {@link SWEntity }
         *
         *
         */
        public List/*<SWEntity>*/getSw() {
                if (sw == null) {
                        sw = new ArrayList/*<SWEntity>*/();
                }
                return this.sw;
        }

        /**
         * Gets the value of the systemLocale property.
         *
         * @return
         *     possible object is
         *     {@link String }
         *
         */
        public String getSystemLocale() {
                return systemLocale;
        }

        String getTagName() {
                return itemTagName;
        }

        String[] getTags() {
                return propTags;
        }

        /**
         * Gets the value of the timezone property.
         *
         * @return
         *     possible object is
         *     {@link String }
         *
         */
        public String getTimezone() {
                return timezone;
        }

        /**
         * Gets the value of the userLocale property.
         *
         * @return
         *     possible object is
         *     {@link String }
         *
         */
        public String getUserLocale() {
                return userLocale;
        }

        private void initDefaultHostInfo() {
                domainName = "unknown";

                try {
                        hostName = InetAddress.getLocalHost().getHostName();
                } catch (UnknownHostException e) {
                        hostName = "unknown";
                }
        }

        private void initDefaultOSInfo() {
                os = new COFOS();
                os.setName(System.getProperty("os.name"));
                os.setVersion(System.getProperty("os.version"));
                os.setArch(System.getProperty("os.arch"));

                // standardize results
                /*        if (osName.equals("sunos") || osName.equals("solaris")) {
                 osName = "solaris";
                 if (osVersion.equals("5.6"))
                 osVersion = "2.6";
                 else if (osVersion.equals("5.7"))
                 osVersion = "2.7";
                 else if (osVersion.equals("5.8"))
                 osVersion = "8";
                 else if (osVersion.equals("5.9"))
                 osVersion = "9";
                 } else if (osName.startsWith("windows")) {
                 osName = "windows";
                 if (osName.indexOf("95") != -1)
                 osVersion = "95";
                 else if (osName.indexOf("98") != -1)
                 osVersion = "98";
                 else if (osName.indexOf("2000") != -1)
                 osVersion = "2000";
                 else if (osName.indexOf("me") != -1)
                 osVersion = "me";
                 else if (osName.indexOf("nt") != -1)
                 osVersion = "nt_4.0";
                 else if (osName.indexOf("xp") != -1)
                 osVersion = "xp";
                 } else if (osName.equals("linux")) {
                 if ((new File("/etc/turbolinux-release")).exists()) {
                 osName = "turbo_linux";
                 osVersion = getGenericLinuxVersionInfo("/etc/turbolinux-release");
                 } else if ((new File("/etc/SuSE-release")).exists()) {
                 osName = "suse_linux";
                 osVersion = getGenericLinuxVersionInfo("/etc/SuSE-release");
                 } else if ((new File("/etc/mandrake-release")).exists()) {
                 osName = "mandrake_linux";
                 osVersion = getGenericLinuxVersionInfo("/etc/mandrake-release");
                 } else if ((new File("/etc/redhat-release")).exists()) {
                 osName = "redhat_linux";
                 osVersion = getGenericLinuxVersionInfo("/etc/redhat-release");
                 } else if ((new File("/etc/lst.cnf")).exists()) {
                 osName = "caldera_linux";
                 osVersion = getCalderaLinuxVersionInfo();
                 } else {
                 osName = "unknown_linux";
                 osVersion = "N/A";
                 }
                 }
                 */}

        /**
         * Sets the value of the bits property.
         *
         * @param value
         *     allowed object is
         *     {@link Integer }
         *
         */
        public void setBits(Integer value) {
                this.bits = value;
        }

        /**
         * Sets the value of the description property.
         *
         * @param value
         *     allowed object is
         *     {@link String }
         *
         */
        public void setDescription(String value) {
                this.description = value;
        }

        /**
         * Sets the value of the displaydepth property.
         *
         * @param value
         *     allowed object is
         *     {@link Integer }
         *
         */
        public void setDisplaydepth(Integer value) {
                this.displaydepth = value;
        }

        /**
         * Sets the value of the encoding property.
         *
         * @param value
         *     allowed object is
         *     {@link String }
         *
         */
        public void setEncoding(String value) {
                this.encoding = value;
        }

        /**
         * Sets the value of the id property.
         *
         * @param value
         *     allowed object is
         *     {@link String }
         *
         */
        public void setId(String value) {
                this.id = value;
        }

        /**
         * Sets the value of the jdk property.
         *
         * @param value
         *     allowed object is
         *     {@link String }
         *
         */
        public void setJdk(String value) {
                this.jdk = value;
        }

        /**
         * Sets the value of the machine property.
         *
         * @param value
         *     allowed object is
         *     {@link String }
         *
         */
        public void setMachine(String value) {
                if (value.endsWith(".unknown"))
                try {
                                machine = InetAddress.getLocalHost().getCanonicalHostName();
                                if (machine.indexOf(".") == -1)
                                        System.err.println(i18n.getString("environment.badMachineName", machine));
                                return;
                } catch (UnknownHostException e) {
                        System.err.println(i18n.getString("environment.cantGetLocalhostName", e.getMessage()));
                        value = value.substring(0,  value.indexOf(".unknown")-1);
                        System.err.println(i18n.getString("environment.badMachineName", value));
                }
                this.machine = value;
        }

        /**
         * Sets the value of the os property.
         *
         * @param value
         *     allowed object is
         *     {@link OS }
         *
         */
        public void setOs(COFOS value) {
                this.os = value;
        }

        /**
         * Sets the value of the systemLocale property.
         *
         * @param value
         *     allowed object is
         *     {@link String }
         *
         */
        public void setSystemLocale(String value) {
                this.systemLocale = value;
        }

        /**
         * Sets the value of the timezone property.
         *
         * @param value
         *     allowed object is
         *     {@link String }
         *
         */
        public void setTimezone(String value) {
                this.timezone = value;
        }

        /**
         * Sets the value of the userLocale property.
         *
         * @param value
         *     allowed object is
         *     {@link String }
         *
         */
        public void setUserLocale(String value) {
                this.userLocale = value;
        }

}
