package condor.gahp.gt3;

import condor.gahp.*;
import condor.gahp.gsi.GSIUtils;

import org.globus.ogsa.impl.base.gram.client.*;
import org.globus.ogsa.impl.security.authentication.Constants;
import org.globus.ogsa.impl.security.authorization.Authorization;
import org.globus.ogsa.impl.security.authorization.SelfAuthorization;
import org.globus.ogsa.base.gram.types.JobStateType;

import org.globus.ogsa.base.gram.service.ManagedJobServiceGridLocator;
import org.globus.ogsa.impl.security.authorization.SelfAuthorization;
import org.gridforum.ogsi.GridService;
import org.globus.ogsa.impl.base.gram.client.GramRsl2XmlConverter;
import org.globus.rsl.ParseException;
import org.gridforum.ogsi.GridService;
import org.gridforum.ogsi.OGSIServiceLocator;
import org.globus.ogsa.handlers.GrimProxyPolicyHandler;
import org.globus.ogsa.impl.security.authentication.Constants;
import org.globus.ogsa.utils.AnyHelper;
import org.gridforum.ogsi.ExtensibilityType;
import org.globus.ogsa.types.properties.PropertiesDetailType;
import org.gridforum.ogsi.EntryType;
import org.globus.ogsa.base.gram.service.ManagedJobServiceLocator;
import org.gridforum.ogsi.EntryContentType;
import org.gridforum.ogsi.ServiceDataValuesType;
import org.gridforum.ogsi.Factory;
import org.globus.ogsa.utils.QueryHelper;
import org.globus.ogsa.impl.security.authorization.Authorization;
import org.globus.ogsa.ServiceData;
import org.gridforum.ogsi.TerminationTimeType;
import org.gridforum.ogsi.ExtendedDateTimeType;
import org.globus.ogsa.base.gram.ManagedJobPortType;
import org.gridforum.ogsi.LocatorType;
import org.globus.ogsa.utils.GridServiceFactory;
import org.globus.ogsa.impl.base.gram.utils.rsl.RslParser;
import org.globus.ogsa.impl.base.gram.utils.rsl.RslParseException;
import org.globus.ogsa.impl.base.gram.utils.rsl.RslParserFactory;
import org.globus.ogsa.base.gram.types.JobStatusType;
import org.globus.axis.gsi.GSIConstants;
import org.globus.ogsa.base.gram.types.JobStateType;
import org.globus.ogsa.impl.base.gram.client.*;
import org.globus.ogsa.NotificationSinkCallback;
import org.globus.ogsa.client.managers.NotificationSinkManager;
import org.globus.ogsa.impl.core.service.ServicePropertiesImpl;

import org.w3c.dom.Element;
import javax.xml.namespace.QName;
import org.ietf.jgss.GSSCredential;
import org.ietf.jgss.GSSException;
import org.gridforum.jgss.ExtendedGSSManager;
import org.gridforum.ogsi.HandleType;
import javax.xml.rpc.Stub;
import java.net.URL;
import java.io.StringReader;
import java.util.Calendar;
import java.util.Date;

public  class Gt3GramJobCallbackRegisterHandler implements CommandHandler {
    private GahpInterface gahp;
    
    public void setGahp (GahpInterface g) {
        gahp = g;
    }

    public CommandHandlerResponse handleCommand (String[] cmd) {
        Integer reqId;
        String contactString = null;
        String callbackContact = null;

        try {
            // cmd[0] = GRAM_JOB_REQUEST
            reqId = new Integer(cmd[1]);
            contactString = cmd[2];
            callbackContact = cmd[3];
        }
        catch (Exception e) {
            e.printStackTrace(System.err);
            return CommandHandlerResponse.SYNTAX_ERROR;
        }

        // Check that callbackcontact is valid
        if (CallbackSink.getCallbackSink(gahp, callbackContact) == null) {
            // TODO: is this right? What if GAHP was restarted? maybe we would create a new one?
            System.err.println ("Unable to find notification sink manager "+callbackContact);
            return CommandHandlerResponse.SYNTAX_ERROR;
        }

        // TODO:
        // Use callback contact
        RegisterJobCallbackRunnable toRun =
            new RegisterJobCallbackRunnable (reqId,
                                             contactString,
                                             callbackContact,
                                             gahp);

        return new CommandHandlerResponse (CommandHandlerResponse.SUCCESS,
                                           toRun);
    }

    class RegisterJobCallbackRunnable 
        extends ServicePropertiesImpl 
        implements Runnable,  NotificationSinkCallback {

        public final String jobURL;
        public final Integer requestID;
        private String callbackContact;
        private GahpInterface gahp;

        public RegisterJobCallbackRunnable(Integer requestID, 
                                           String jobURL, 
                                           String callbackContact,
                                           GahpInterface gahp) {
            this.jobURL = jobURL;
            this.requestID = requestID;
            this.gahp = gahp;
            this.callbackContact = callbackContact;
        }

        public void run () {
            String [] result = null;
            try {

                ManagedJobServiceGridLocator serviceLocator =
                    new ManagedJobServiceGridLocator();
                ManagedJobPortType job =
                    serviceLocator.getManagedJobPort(new URL(jobURL));

                GrimProxyPolicyHandler grimPolicyHandler = new GrimProxyPolicyHandler();
                grimPolicyHandler.reset();
                ((Stub)job)._setProperty(Constants.GSI_SEC_CONV,
                                         Constants.SIGNATURE);
                ((Stub)job)._setProperty(Constants.GRIM_POLICY_HANDLER,
                                         grimPolicyHandler);
                ((Stub)job)._setProperty(Constants.AUTHORIZATION,
                                         SelfAuthorization.getInstance());
                ((Stub)job)._setProperty(GSIConstants.GSI_MODE,
                                         GSIConstants.GSI_MODE_LIMITED_DELEG);
                GSSCredential cred = GSIUtils.getCredential (gahp);
                if ( cred != null ) {
                    ((Stub)job)._setProperty(GSIConstants.GSI_CREDENTIALS,cred);
                } 

                grimPolicyHandler.reset();

                CallbackSink sink =
                    CallbackSink.getCallbackSink(gahp, callbackContact);
                sink.addJobListener (serviceLocator, job);

                result = new String [] { "0", "NULL" };
            }
            catch (Exception e) {
                System.err.println ("Error registering for callbacks");
                e.printStackTrace(System.err);
                String errorString = e.toString();
                if (errorString == null) errorString = "unknown";
                result = new String[] { "1", errorString};
            }
            gahp.addResult( requestID.intValue(), result );
        }

        public void deliverNotification(org.gridforum.ogsi.ExtensibilityType extensibilityType) throws java.rmi.RemoteException {
        }

    }
    
}
