/*
 *  @(#)JT4TestAPIBasic.java	1.8 07/06/06
 *
 * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
 * ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
 */
package com.sun.javatest.example.services.interview;

import java.io.File;
import java.util.Enumeration;
import java.util.Iterator;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;
import java.util.ResourceBundle;
import java.util.Set;

import com.sun.javatest.TestSuite;
import com.sun.javatest.TestEnvironment;
import com.sun.javatest.InterviewParameters;

import com.sun.javatest.interview.BasicInterviewParameters;
import com.sun.javatest.Parameters.EnvParameters;
import com.sun.interview.Interview;
import com.sun.interview.NullQuestion;
import com.sun.interview.PropertiesQuestion;
import com.sun.interview.Question;
import com.sun.interview.StringQuestion;

import com.sun.interview.ChoiceQuestion;
import com.sun.interview.FileQuestion;
import com.sun.interview.ErrorQuestion;
import com.sun.interview.Checklist;

public class ServicesInterview extends BasicInterviewParameters implements
        EnvParameters {
    
    public ServicesInterview() throws InterviewParameters.Fault {
        super("services");
        init();
    }

    public ServicesInterview(String tag) throws Interview.Fault {
        super(tag);
        init();
    }

    public ServicesInterview(String tag, TestSuite ts) throws Interview.Fault {
        super(tag, ts);
        init();
    }

    private void init() {
        try {
            setHelpSet("moreinfo/interview.hs");
        }
        catch (com.sun.interview.Interview.Fault f) {
            f.printStackTrace();
        }

        // use modern semantics, not legacy behavior
        setInterviewSemantics(Interview.SEMANTIC_MAX_VERSION);

        setResourceBundle("i18n");
        setFirstQuestion(qWelcome);

	ResourceBundle rb = getResourceBundle();
	if (rb != null)
	    setTitle(rb.getString("services.interview.title"));
    }

    @Override
    public void export(Map map) {
        super.export(map);
        System.err.println("exporting main interview");
    }
    // ------ question flow (overrides) ------

    public Question getEnvFirstQuestion() {
        return qName;
    }

    protected Question getEnvSuccessorQuestion() {
        return getExcludeListFirstQuestion();
    }

    protected Question getPriorStatusSuccessorQuestion() {
        // this bypasses the concurrency question
        // all standard value questions can be rearranged or
        // bypassed
        return getTimeoutFactorFirstQuestion();
    }

    protected Question getTestsSuccessorQuestion() {
        return getTestSuitesFirstQuestion();
    }

    // ------ question flow (custom) ------

    protected Question getTestSuitesFirstQuestion() {
        return branchQ;
    }

    //----------------------------------------------------------------------
    //
    // Null questions used to break up interview

    private NullQuestion qWelcome = new NullQuestion(this, "welcome") {
        public Question getNext() {
            return getPrologSuccessorQuestion();
        }
    };

    //----------------------------------------------------------------------
    //
    // Give a name for this configuration

    private StringQuestion qName = new StringQuestion(this, "confName") {
        {
            setDefaultValue("services");
        }

        private boolean isValidIdentifier(String s) {
            if (s == null || s.equals("")) 
                return false;
	
            if (!Character.isUnicodeIdentifierStart(s.charAt(0))) 
                return false;
	
            for (int i = 1; i < s.length(); i++) {
                if (!Character.isUnicodeIdentifierPart(s.charAt(i))) 
                    return false;
            }
            return true;
        }

        public boolean isValueValid() {
            return isValidIdentifier(value);
        }

        protected Question getNext() {
            return qDesc;
//            return questions[0];
        }
    };

    Interview subI = new SubInterview();
    //----------------------------------------------------------------------
    //
    // Give a description for this configuration

    private StringQuestion qDesc = new StringQuestion(this, "confDesc") {
        {
        }

        public boolean isValueValid() {
            return true;
        }

        public Question getNext() {
           // this puts the Tests To Run question toward the beginning
           // see getTestsSuccessorQuestion() above
           return callInterview(subI, getTestsFirstQuestion());
        }

        public void export(Map data) {
            if (value == null || value.equals(""))
                data.put("description", "[Not Specified]");   // would need i18n
            else
                data.put("description", String.valueOf(value));
        }


        public boolean isHidden() {
            return true;
        }

        public boolean isEnabled() {
            return false;
        }
    };

    private NullQuestion branchQ = new NullQuestion(this, "nullQ") {
        public boolean isHidden() { return true; }

        public Question getNext() {
            return qCmdType;
        }
    };
    
    
    private static final String AGENT = "agent";
    private static final String OTHER_VM = "otherVM";
    
    private Question qCmdType = new ChoiceQuestion(this, "cmdType") {
	    {
		setChoices(new String[] { null, OTHER_VM, AGENT}, true);
	    }
            
	    public Question getNext() {
		if (value == null || value.length() == 0)
		    return null;
		else if (value.equals(OTHER_VM))
		    return qJVM;
		else {
                    return intro;
                }
            }
            
	    public Checklist.Item[] getChecklistItems() {
		if (value != AGENT) 
		    return null;

		return new Checklist.Item[] {
		    createChecklistItem("agent", "agent.needToStart"),
		};
	    }

	    public void export(Map data) {
		String cmd;
		if (value != null && value.equals(OTHER_VM))
		    cmd = getOtherVMExecuteCommand();
		else
		    cmd = "com.sun.javatest.agent.ActiveAgentCommand " +
			"com.sun.javatest.lib.ExecStdTestSameJVMCmd " +
			"$testExecuteClass $testExecuteArgs";
		data.put("command.execute", cmd);
	    }
	};

    //----------------------------------------------------------------------
    //
    // What is the path for the JVM you wish to use to execute the tests?

    private FileQuestion qJVM = new FileQuestion(this, "jvm") {
	    public Question getNext() {
		if (value == null || value.getPath().length() == 0) 
		    return null;
		else if (! (value.exists() && value.isFile() && value.canRead())) 
		    return qBadJVM;
		else {
                    String [] tests = getTests();
                    return intro;
                }   //else 
            }
	};

    private Question qBadJVM = new ErrorQuestion(this, "badJVM") {
	    public Object[] getTextArgs() {
		return new Object[] { qJVM.getValue().getPath() };
	    }
	};

    private String getOtherVMExecuteCommand() {

	StringBuffer sb = new StringBuffer();
	sb.append("com.sun.javatest.lib.ExecStdTestOtherJVMCmd ");
	File jvm = qJVM.getValue();
	sb.append(jvm == null ? "unknown_jvm" : jvm.getPath());
        String tsCP = getTestSuite().getTestSuiteInfo("classpath");
        if (tsCP != null) {
            sb.append(" -classpath ");
            String[] paths = tsCP.split(":");
            char fs = File.separatorChar;
            char ps = File.pathSeparatorChar;
            for (String p : paths) {
                sb.append("$testSuiteRootDir" + fs + p + ps);
            }
            sb.append(" $testExecuteClass $testExecuteArgs");
        }
	return sb.toString();
    }
    
    // End of insertion


    // BEGIN MIDP

    private NullQuestion intro = new NullQuestion(this, "testIntro") {
        public Question getNext() {
            return pq;
        }
    };

    
    private PropertiesQuestion pq = new PropertiesQuestion(this, "pq") {
        {
            Properties p = new Properties();
            
            p.put("sfw.path", "/sfw/");
            p.put("ant.path", "apache-ant-1.7.0-bin/apache-ant-1.7.0");
            p.put("ant1.wd", "ant/");
            p.put("ant2.wd", "ant/");
            p.put("ant1.target", "build");
                    

            setDefaultValue(p);
            setValue(p);
            this.setConstraints("ant1.wd", new FilenameConstraints());
            this.setConstraints("ant2.wd", new FilenameConstraints());
        }

        public Question getNext() {
            return qBasicParams;
        }

        public void export(Map data) {
            // raw dump of all properties into test env.
            Properties p = getValue();

            Enumeration e = p.propertyNames();
            while(e.hasMoreElements()) {
                String key = (String)(e.nextElement());
                data.put(key, p.getProperty(key));
            }
        }

    };
    // BEGIN CONFIG FOR SAMPLE TEST SUITE

    //----------------------------------------------------------------------

    private NullQuestion qBasicParams = new NullQuestion(this, "parameters") {
	    public Question getNext() {
		return getEnvSuccessorQuestion();
	    }
    };

    public EnvParameters getEnvParameters() {
        return this;
    }

    // interface EnvParameters
    public TestEnvironment getEnv() {
        // this doesn't do anything right now
        HashMap data = new HashMap();
        export(data);

        Set keys = getPropertyKeys();  //extra values
        
        if(keys != null) {
            Iterator it = keys.iterator();
            while (it.hasNext()) {
                String k = (String)(it.next());     // cast not needed
                data.put(k, retrieveProperty(k));
            }   // while
        }

        try {
            return new TestEnvironment("services", data, "services");
        } catch (TestEnvironment.Fault f) {
            f.printStackTrace();
            throw new IllegalStateException("Broken data");
        }
    }
    
}
