/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 * 
 *      http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
*/
package org.apache.uima.ducc.sm;

import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
import java.io.StringReader;
import java.io.StringWriter;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.HashMap;
import java.util.Map;

import org.apache.uima.ducc.cli.AServicePing;
import org.apache.uima.ducc.cli.CommandLine;
import org.apache.uima.ducc.cli.IUiOption;
import org.apache.uima.ducc.cli.ServiceStatistics;
import org.apache.uima.ducc.common.IServiceStatistics;
import org.apache.uima.ducc.common.utils.DuccProperties;


/**
 * If an external pinger is specified for a service, this method instantiates and executes
 * the pinger.
 *
 * The pinger must extend org.apache.uima.ducc.sm.cli.ServicePing and implement the ping() method.
 *
 */

public class ServicePingMain
    implements SmConstants
{

    /**
	 * 
	 */
	boolean debug = false;
    int error_max = 10;
    int error_count = 0;

    CommandLine command_line = null;

    enum OptionSet
        implements IUiOption
    {
        Class   { 
            public String pname()       { return "class"; } 
            public String argname()     { return "Java classname"; }
            public boolean required()   { return true; }
            public String description() { return "This is the name of the class implementing the pinger"; }
            public String example()     { return "org.bob.PingClass"; }
        },
        Endpoint   { 
            public String pname()       { return "endpoint"; } 
            public String argname()     { return "string"; }
            public boolean required()    { return true; }
            public String description() { return "Thsi is the endpoint specified in teh registration."; }
            public String example()     { return "UIMA-AS:MyUimaAsEndpoint:/tcp//broker1:1234"; }
        },
        Port   { 
            public String pname()       { return "port"; } 
            public String argname()     { return "integer"; }
            public boolean required()   { return true; }
            public String description() { return "This is the port the broker is listening on."; }
            public String example()     { return "12345"; }
            public String label()       { return name(); }
        },
        Arguments   { 
            public String pname()       { return "arguments"; } 
            public String argname()     { return "string"; }
            public String description() { return "Argument string from pinger registration, if any."; }
        },
        Initprops   { 
            public String pname()       { return "initprops"; } 
            public String argname()     { return "string"; }
            public String description() { return "Initialization properties, if any."; }
        },
        ;
        public boolean multiargs() { return false; } // the option can have >1 arg
        public boolean required()  { return false; } // this option is required
        public String  deflt()     { return null; }  // default, or ""
        public String  label()     { return null; }  // Parameter name for label in web form
        public String  sname()     { return null; }  // short name of option
        public boolean optargs()   { return false; } // is the argument optional?
        public boolean noargs()    { return false; }
        public String  example()   { return null; }

        public String makeDesc()
        {
            if ( example() == null ) return description();
            return description() + "\nexample: " + example();
        }
    };

    IUiOption[] options = {
        OptionSet.Class,
        OptionSet.Endpoint,
        OptionSet.Port,
        OptionSet.Arguments,
        OptionSet.Initprops,
    };

    public ServicePingMain()
    {
    }

    public void usage()
    {
        System.out.println(command_line.formatHelp(this.getClass().getName()));        
        System.exit(1);
    }

    void appendStackTrace(StringBuffer s, Throwable t)
    {
    	s.append("\nAt:\n");
        StackTraceElement[] stacktrace = t.getStackTrace();
        for ( StackTraceElement ste : stacktrace ) {
            s.append("\t");
            s.append(ste.toString());
            s.append("\n");
        }
    }
    
    
    public void print(Object ... args)
    {
    	StringBuffer s = new StringBuffer();
        for ( Object a : args ) {
            if ( a == null ) a = "<null>"; // avoid null pointers

            s.append(" ");
            if ( a instanceof Throwable ) {
            	Throwable t = (Throwable ) a;
                s.append(t.toString());
                s.append("\n");
                appendStackTrace(s, t);
            } else {                
                s.append(a.toString());
            }
        }
        System.err.println(s.toString());
    }

    //
    // resolve the customMeta string inta a class if we can
    //
    AServicePing resolve(String cl, String args, String ep, Map<String, Object> initprops)
    {
    	print("ServicePingMain.resolve:", cl, "ep", ep);
    	AServicePing pinger = null;
		try {
			@SuppressWarnings("rawtypes")
			Class cls = Class.forName(cl);
			pinger = (AServicePing) cls.newInstance();
			pinger.init(args, ep, initprops);
		} catch (Exception e) {
            //print(e);         // To the logs
            e.printStackTrace();
		} 
        return pinger;
    }

    void handleError(AServicePing custom, Throwable t)
    {
        t.printStackTrace();
        if ( ++error_count >= error_max ) {
            custom.stop();
            System.out.println("Exceeded error count. Exiting.");
            System.exit(1);
        }
    }

    // /**
    //  * Simple argument parser for this class.  It is spawned only by SM so even though we do
    //  * validity checking, we assume the args are correct and complete, and just crash hard if not as
    //  * it's an internal error that should not occur.
    //  */
    // void parseOptions(String[] args)
    // {
    //     // First read them all in
    //     if ( debug ) {
    //         for ( int i = 0; i < args.length; i++ ) {
    //             print("Args[" + i + "] = ", args[i]);
    //         }
    //     }

    //     for ( int i = 0; i < args.length; ) {
    //         if ( clioptions.containsKey(args[i]) ) {
    //             Object o = clioptions.get(args[i]);
    //             if ( (o != clioptions) && ( o != None ) ) {
    //                 System.out.println("Duplicate argument, not allowed: " + args[i]);
    //                 System.exit(1);
    //             }
    //             System.out.println("Put " + args[i] + ", " + args[i+1]);
    //             clioptions.put(args[i], args[i+1]);
    //             i += 2;
    //         } else {
    //             System.out.println("Invalid argument: " + args[i]);
    //             System.exit(1);
    //         }
    //     }

    //     // Now make sure they all exist
    //     ArrayList<String> toRemove = new ArrayList<String>();
    //     for ( Object o : clioptions.keySet()) {
    //         String k = (String) o;
    //         Object v = clioptions.get(k);
    //         if ( v == clioptions ) {
    //             System.out.println("Missing argument: " + k);
    //             System.exit(1);
    //         }
    //         if ( v == None ) {             // optional arg, we want fetches to return null if it wasn't set 
    //             toRemove.add(k);
    //         }
    //     }
    //     for ( String k : toRemove ) {
    //         clioptions.remove(k);
    //     }
    // }

    /**
     * Convert the initialization props into a map<string, object>
     *
     * It seems perhaps dumb at first, why not just use properties?
     *
     * It's because the internal pinger can use the map directly without lots of conversion and
     * parsing, and that's by far the most common case.  To insure common code all around we
     * jump through this tiny hoop for external pingers.
     */
    protected Map<String, Object> stringToProperties(String prop_string)
    {
        String[] as = prop_string.split(",");
        StringWriter sw = new StringWriter();
        for ( String s : as ) sw.write(s + "\n");
        StringReader sr = new StringReader(sw.toString());            
        DuccProperties props = new DuccProperties();
        try {
            props.load(sr);
        } catch (IOException e) {
            // nastery internal error if this occurs
            e.printStackTrace();
            System.exit(1);
        }

        Map<String, Object> ret = new HashMap<String, Object>();
        int     v_int;
        long    v_long;
        boolean v_bool;
        String k;

        k = "failure-window";
        v_int = props.getIntProperty(k);
        ret.put(k, v_int);

        k = "failure-max";
        v_int = props.getIntProperty(k);
        ret.put(k, v_int);

        k = "monitor-rate";
        v_int = props.getIntProperty(k);
        ret.put(k, v_int);

        k = "service-id";
        v_long = props.getLongProperty(k);
        ret.put(k, v_long);

        k = "do-log";
        v_bool = props.getBooleanProperty(k, false);
        ret.put(k, v_bool);

        k = "autostart-enabled";
        v_bool = props.getBooleanProperty(k, false);
        ret.put(k, v_bool);

        k = "last-use";
        v_long = props.getLongProperty(k, 0L);
        ret.put(k, v_long);

        for ( String rk : ret.keySet() ) {
            print("init:", rk, "=", ret.get(rk));
        }
        return ret;
    }
    
    //
    // 1. Instantiate the pinger if possible.
    // 2. Read ducc.proeprties to find the ping interval
    // 3. Start pinging and wriging results to stdout
    //
    // The ServiceManager must start this process as the user.  It monitors stdout for success
    // or failute of the ping and reacts accordingly.
    //
	protected int start(String[] args)
    {

        command_line = new CommandLine(args, options);
        command_line.parse();
        IServiceStatistics default_statistics = new ServiceStatistics(false, false, "<N/A>");

        String arguments = command_line.get   (OptionSet.Arguments);
        String pingClass = command_line.get   (OptionSet.Class);
        String endpoint  = command_line.get   (OptionSet.Endpoint);
        int port         = command_line.getInt(OptionSet.Port);
        String initters  = command_line.get   (OptionSet.Initprops);
        Map<String, Object> initprops = stringToProperties(initters);

        Socket sock = null;

		try {
			try {
				sock = new Socket("localhost", port);
			} catch (NumberFormatException e2) {
				e2.printStackTrace();
				return 1;
			} catch (UnknownHostException e2) {
				e2.printStackTrace();
				return 1;
			} catch (IOException e2) {
				e2.printStackTrace();
				return 1;
			} 

			print ("ServicePingMain listens on port", sock.getLocalPort());
			InputStream sock_in = null;
			OutputStream sock_out = null;
			try {
				sock_in = sock.getInputStream();
				sock_out = sock.getOutputStream();
			} catch (IOException e2) {
				e2.printStackTrace();
				return 1;
			}

			ObjectOutputStream oos;
			try {
				oos = new ObjectOutputStream(sock_out);
				oos.flush();
			} catch (IOException e1) {
				e1.printStackTrace();
				return 1;
			}        

			ObjectInputStream ois;
			try {
				ois = new ObjectInputStream(sock_in);
			} catch (IOException e1) {
				e1.printStackTrace();
				return 1;
			}        

			AServicePing custom = resolve(pingClass, arguments, endpoint, initprops);
			if ( custom == null ) {
			    print("bad_pinger:", pingClass, endpoint);
			    return 1;
			}

			while ( true ) {  
				if ( debug ) print("ServicePingMeta starts ping.");

			    Ping ping = null;
				try {
			        ping = (Ping) ois.readObject();
			        if ( debug ) {
			            print("Total instances:" , ping.getSmState().get("total-instances"));
			            print("Active instances:", ping.getSmState().get("active-instances"));
			            print("References:"      , ping.getSmState().get("references"));
			            print("Run Failures:"    , ping.getSmState().get("runfailures"));
			        }
				} catch (IOException e) {
			        handleError(custom, e);
				} catch ( ClassNotFoundException e) {
					handleError(custom, e);
				}
			    
			    boolean quit = ping.isQuit();
			    if ( debug ) print("Read ping: ", quit);

			    try {
					if ( quit ) {
			            if ( debug ) System.out.println("Calling custom.stop");
					    custom.stop();                
			            oos.close();
			            ois.close();
			            sock.close();
			            if ( debug ) System.out.println("Custom.stop returns");
					    return 0;
			        } else {
			            Pong pr = new Pong();
			            custom.setSmState(ping.getSmState());
			            IServiceStatistics ss = custom.getStatistics();
			            if ( ss == null ) {
			                ss = default_statistics;
			            }

			            pr.setStatistics     (ss);
			            pr.setAdditions      (custom.getAdditions());
			            pr.setDeletions      (custom.getDeletions());
			            pr.setExcessiveFailures(custom.isExcessiveFailures());
			            pr.setAutostart      (custom.isAutostart());
			            pr.setLastUse        (custom.getLastUse());

			            oos.writeObject(pr);
			            oos.flush();

			            // The ObjectOutputStream will cache instances and if all you do is change a
			            // field or two in the object, it won't be detected and the stale object will be
			            // sent.  So you have to reset() the stream, (or use a new object, or use
			            // clone() here also if you want, but this is simplest and safest since we have
			            // no control over what the external pinger gives us.
			            oos.reset();
					} 
			    } catch (Throwable e) {
			        handleError(custom, e);
				}            
			}
		} finally {
			try {
				if ( sock != null ) {
					sock.close();
				}
			} catch (IOException e) {
				// Junk catch to keep Eclipse from whining
				e.printStackTrace();
			}
		}
    }

    public static void main(String[] args)
    {
        ServicePingMain wrapper = new ServicePingMain();
        int rc = wrapper.start(args);
        System.exit(rc);
    }
    
}

